15767 lines
471 KiB
Diff
15767 lines
471 KiB
Diff
From 1adf4b1e78d961522e4d598dd82456630458e617 Mon Sep 17 00:00:00 2001
|
||
From: Hans de Goede <hdegoede@redhat.com>
|
||
Date: Sat, 20 Feb 2010 21:40:38 +0100
|
||
Subject: [PATCH] Rebase gspca webcamdrivers to latest upstream
|
||
|
||
This adds drivers for benq, cpia1 and sn9c2028 bridges + support for
|
||
more devices and many bugfixes in other drivers.
|
||
|
||
This also adds support for the button found on most cameras in most
|
||
gspca sub drivers.
|
||
---
|
||
drivers/media/video/gspca/Kconfig | 46 +-
|
||
drivers/media/video/gspca/Makefile | 8 +
|
||
drivers/media/video/gspca/benq.c | 322 ++++
|
||
drivers/media/video/gspca/coarse_expo_autogain.h | 116 ++
|
||
drivers/media/video/gspca/conex.c | 4 +-
|
||
drivers/media/video/gspca/cpia1.c | 2022 ++++++++++++++++++++
|
||
drivers/media/video/gspca/etoms.c | 10 +-
|
||
drivers/media/video/gspca/gl860/gl860.c | 10 +-
|
||
drivers/media/video/gspca/gspca.c | 252 +++-
|
||
drivers/media/video/gspca/gspca.h | 30 +-
|
||
drivers/media/video/gspca/m5602/m5602_mt9m111.c | 16 +-
|
||
drivers/media/video/gspca/m5602/m5602_ov7660.c | 102 +-
|
||
drivers/media/video/gspca/m5602/m5602_ov7660.h | 2 +-
|
||
drivers/media/video/gspca/m5602/m5602_ov9650.c | 2 +-
|
||
drivers/media/video/gspca/m5602/m5602_po1030.c | 14 +-
|
||
drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 2 +-
|
||
drivers/media/video/gspca/m5602/m5602_s5k83a.c | 2 +-
|
||
drivers/media/video/gspca/mars.c | 40 +-
|
||
drivers/media/video/gspca/mr97310a.c | 226 ++-
|
||
drivers/media/video/gspca/ov519.c | 170 ++-
|
||
drivers/media/video/gspca/ov534.c | 1253 ++-----------
|
||
drivers/media/video/gspca/ov534_9.c | 1477 ++++++++++++++
|
||
drivers/media/video/gspca/pac207.c | 25 +-
|
||
drivers/media/video/gspca/pac7302.c | 432 ++---
|
||
drivers/media/video/gspca/pac7311.c | 272 ++--
|
||
drivers/media/video/gspca/pac_common.h | 9 +-
|
||
drivers/media/video/gspca/sn9c2028.c | 757 ++++++++
|
||
drivers/media/video/gspca/sn9c2028.h | 51 +
|
||
drivers/media/video/gspca/sn9c20x.c | 33 +-
|
||
drivers/media/video/gspca/sonixb.c | 481 ++++--
|
||
drivers/media/video/gspca/sonixj.c | 423 ++++-
|
||
drivers/media/video/gspca/spca500.c | 21 +-
|
||
drivers/media/video/gspca/spca501.c | 27 +-
|
||
drivers/media/video/gspca/spca505.c | 2 +-
|
||
drivers/media/video/gspca/spca506.c | 4 +-
|
||
drivers/media/video/gspca/spca508.c | 48 +-
|
||
drivers/media/video/gspca/spca561.c | 35 +-
|
||
drivers/media/video/gspca/sq905c.c | 45 +-
|
||
drivers/media/video/gspca/stk014.c | 2 +-
|
||
drivers/media/video/gspca/stv0680.c | 36 +-
|
||
drivers/media/video/gspca/stv06xx/stv06xx.c | 32 +-
|
||
drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c | 22 +
|
||
drivers/media/video/gspca/sunplus.c | 71 +-
|
||
drivers/media/video/gspca/t613.c | 102 +-
|
||
drivers/media/video/gspca/tv8532.c | 8 +-
|
||
drivers/media/video/gspca/vc032x.c | 1163 +++++++++++-
|
||
drivers/media/video/gspca/zc3xx.c | 712 ++++----
|
||
include/linux/videodev2.h | 2 +
|
||
48 files changed, 8692 insertions(+), 2249 deletions(-)
|
||
create mode 100644 drivers/media/video/gspca/benq.c
|
||
create mode 100644 drivers/media/video/gspca/coarse_expo_autogain.h
|
||
create mode 100644 drivers/media/video/gspca/cpia1.c
|
||
create mode 100644 drivers/media/video/gspca/ov534_9.c
|
||
create mode 100644 drivers/media/video/gspca/sn9c2028.c
|
||
create mode 100644 drivers/media/video/gspca/sn9c2028.h
|
||
|
||
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
|
||
index 609d65b..e0060c1 100644
|
||
--- a/drivers/media/video/gspca/Kconfig
|
||
+++ b/drivers/media/video/gspca/Kconfig
|
||
@@ -21,6 +21,15 @@ source "drivers/media/video/gspca/m5602/Kconfig"
|
||
source "drivers/media/video/gspca/stv06xx/Kconfig"
|
||
source "drivers/media/video/gspca/gl860/Kconfig"
|
||
|
||
+config USB_GSPCA_BENQ
|
||
+ tristate "Benq USB Camera Driver"
|
||
+ depends on VIDEO_V4L2 && USB_GSPCA
|
||
+ help
|
||
+ Say Y here if you want support for the Benq DC E300 camera.
|
||
+
|
||
+ To compile this driver as a module, choose M here: the
|
||
+ module will be called gspca_benq.
|
||
+
|
||
config USB_GSPCA_CONEX
|
||
tristate "Conexant Camera Driver"
|
||
depends on VIDEO_V4L2 && USB_GSPCA
|
||
@@ -30,6 +39,17 @@ config USB_GSPCA_CONEX
|
||
To compile this driver as a module, choose M here: the
|
||
module will be called gspca_conex.
|
||
|
||
+config USB_GSPCA_CPIA1
|
||
+ tristate "cpia CPiA (version 1) Camera Driver"
|
||
+ depends on VIDEO_V4L2 && USB_GSPCA
|
||
+ help
|
||
+ Say Y here if you want support for USB cameras based on the cpia
|
||
+ CPiA chip. Note that you need atleast version 0.6.4 of libv4l for
|
||
+ applications to understand the videoformat generated by this driver.
|
||
+
|
||
+ To compile this driver as a module, choose M here: the
|
||
+ module will be called gspca_cpia1.
|
||
+
|
||
config USB_GSPCA_ETOMS
|
||
tristate "Etoms USB Camera Driver"
|
||
depends on VIDEO_V4L2 && USB_GSPCA
|
||
@@ -86,15 +106,25 @@ config USB_GSPCA_OV519
|
||
module will be called gspca_ov519.
|
||
|
||
config USB_GSPCA_OV534
|
||
- tristate "OV534 USB Camera Driver"
|
||
+ tristate "OV534 OV772x USB Camera Driver"
|
||
depends on VIDEO_V4L2 && USB_GSPCA
|
||
help
|
||
- Say Y here if you want support for cameras based on the OV534 chip.
|
||
- (e.g. Sony Playstation EYE)
|
||
+ Say Y here if you want support for cameras based on the OV534 chip
|
||
+ and sensor OV772x (e.g. Sony Playstation EYE)
|
||
|
||
To compile this driver as a module, choose M here: the
|
||
module will be called gspca_ov534.
|
||
|
||
+config USB_GSPCA_OV534_9
|
||
+ tristate "OV534 OV965x USB Camera Driver"
|
||
+ depends on VIDEO_V4L2 && USB_GSPCA
|
||
+ help
|
||
+ Say Y here if you want support for cameras based on the OV534 chip
|
||
+ and sensor OV965x (e.g. Hercules Dualpix)
|
||
+
|
||
+ To compile this driver as a module, choose M here: the
|
||
+ module will be called gspca_ov534_9.
|
||
+
|
||
config USB_GSPCA_PAC207
|
||
tristate "Pixart PAC207 USB Camera Driver"
|
||
depends on VIDEO_V4L2 && USB_GSPCA
|
||
@@ -122,6 +152,16 @@ config USB_GSPCA_PAC7311
|
||
To compile this driver as a module, choose M here: the
|
||
module will be called gspca_pac7311.
|
||
|
||
+config USB_GSPCA_SN9C2028
|
||
+ tristate "SONIX Dual-Mode USB Camera Driver"
|
||
+ depends on VIDEO_V4L2 && USB_GSPCA
|
||
+ help
|
||
+ Say Y here if you want streaming support for Sonix SN9C2028 cameras.
|
||
+ These are supported as stillcams in libgphoto2/camlibs/sonix.
|
||
+
|
||
+ To compile this driver as a module, choose M here: the
|
||
+ module will be called gspca_sn9c2028.
|
||
+
|
||
config USB_GSPCA_SN9C20X
|
||
tristate "SN9C20X USB Camera Driver"
|
||
depends on VIDEO_V4L2 && USB_GSPCA
|
||
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
|
||
index ff2c727..6e4cf1c 100644
|
||
--- a/drivers/media/video/gspca/Makefile
|
||
+++ b/drivers/media/video/gspca/Makefile
|
||
@@ -1,5 +1,7 @@
|
||
obj-$(CONFIG_USB_GSPCA) += gspca_main.o
|
||
+obj-$(CONFIG_USB_GSPCA_BENQ) += gspca_benq.o
|
||
obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o
|
||
+obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.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
|
||
@@ -7,9 +9,11 @@ obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o
|
||
obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
|
||
obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o
|
||
obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o
|
||
+obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o
|
||
obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o
|
||
obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o
|
||
obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
|
||
+obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o
|
||
obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o
|
||
obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o
|
||
obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o
|
||
@@ -30,7 +34,9 @@ obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o
|
||
obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o
|
||
|
||
gspca_main-objs := gspca.o
|
||
+gspca_benq-objs := benq.o
|
||
gspca_conex-objs := conex.o
|
||
+gspca_cpia1-objs := cpia1.o
|
||
gspca_etoms-objs := etoms.o
|
||
gspca_finepix-objs := finepix.o
|
||
gspca_jeilinj-objs := jeilinj.o
|
||
@@ -38,9 +44,11 @@ gspca_mars-objs := mars.o
|
||
gspca_mr97310a-objs := mr97310a.o
|
||
gspca_ov519-objs := ov519.o
|
||
gspca_ov534-objs := ov534.o
|
||
+gspca_ov534_9-objs := ov534_9.o
|
||
gspca_pac207-objs := pac207.o
|
||
gspca_pac7302-objs := pac7302.o
|
||
gspca_pac7311-objs := pac7311.o
|
||
+gspca_sn9c2028-objs := sn9c2028.o
|
||
gspca_sn9c20x-objs := sn9c20x.o
|
||
gspca_sonixb-objs := sonixb.o
|
||
gspca_sonixj-objs := sonixj.o
|
||
diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c
|
||
new file mode 100644
|
||
index 0000000..43ac4af
|
||
--- /dev/null
|
||
+++ b/drivers/media/video/gspca/benq.c
|
||
@@ -0,0 +1,322 @@
|
||
+/*
|
||
+ * Benq DC E300 subdriver
|
||
+ *
|
||
+ * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr)
|
||
+ *
|
||
+ * 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 "benq"
|
||
+
|
||
+#include "gspca.h"
|
||
+
|
||
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
|
||
+MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver");
|
||
+MODULE_LICENSE("GPL");
|
||
+
|
||
+/* specific webcam descriptor */
|
||
+struct sd {
|
||
+ struct gspca_dev gspca_dev; /* !! must be the first item */
|
||
+};
|
||
+
|
||
+/* V4L2 controls supported by the driver */
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
+};
|
||
+
|
||
+static const struct v4l2_pix_format vga_mode[] = {
|
||
+ {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 320,
|
||
+ .sizeimage = 320 * 240 * 3 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG},
|
||
+};
|
||
+
|
||
+static void sd_isoc_irq(struct urb *urb);
|
||
+
|
||
+/* -- write a register -- */
|
||
+static void reg_w(struct gspca_dev *gspca_dev,
|
||
+ u16 value, u16 index)
|
||
+{
|
||
+ struct usb_device *dev = gspca_dev->dev;
|
||
+ int ret;
|
||
+
|
||
+ if (gspca_dev->usb_err < 0)
|
||
+ return;
|
||
+ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||
+ 0x02,
|
||
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||
+ value,
|
||
+ index,
|
||
+ NULL,
|
||
+ 0,
|
||
+ 500);
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "reg_w err %d", ret);
|
||
+ gspca_dev->usb_err = ret;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* this function is called at probe time */
|
||
+static int sd_config(struct gspca_dev *gspca_dev,
|
||
+ const struct usb_device_id *id)
|
||
+{
|
||
+ gspca_dev->cam.cam_mode = vga_mode;
|
||
+ gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
|
||
+ gspca_dev->cam.no_urb_create = 1;
|
||
+ gspca_dev->cam.reverse_alts = 1;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* this function is called at probe and resume time */
|
||
+static int sd_init(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface,
|
||
+ gspca_dev->nbalt - 1);
|
||
+ if (ret < 0) {
|
||
+ err("usb_set_interface failed");
|
||
+ return ret;
|
||
+ }
|
||
+/* reg_w(gspca_dev, 0x0003, 0x0002); */
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* -- start the camera -- */
|
||
+static int sd_start(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct urb *urb;
|
||
+ int i, n;
|
||
+
|
||
+ /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
|
||
+#if MAX_NURBS < 4
|
||
+#error "Not enough URBs in the gspca table"
|
||
+#endif
|
||
+#define SD_PKT_SZ 64
|
||
+#define SD_NPKT 32
|
||
+ for (n = 0; n < 4; n++) {
|
||
+ urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
|
||
+ if (!urb) {
|
||
+ err("usb_alloc_urb failed");
|
||
+ return -ENOMEM;
|
||
+ }
|
||
+ gspca_dev->urb[n] = urb;
|
||
+ urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
|
||
+ SD_PKT_SZ * SD_NPKT,
|
||
+ GFP_KERNEL,
|
||
+ &urb->transfer_dma);
|
||
+
|
||
+ if (urb->transfer_buffer == NULL) {
|
||
+ err("usb_buffer_alloc failed");
|
||
+ return -ENOMEM;
|
||
+ }
|
||
+ urb->dev = gspca_dev->dev;
|
||
+ urb->context = gspca_dev;
|
||
+ urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT;
|
||
+ urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
|
||
+ n & 1 ? 0x82 : 0x83);
|
||
+ urb->transfer_flags = URB_ISO_ASAP
|
||
+ | URB_NO_TRANSFER_DMA_MAP;
|
||
+ urb->interval = 1;
|
||
+ urb->complete = sd_isoc_irq;
|
||
+ urb->number_of_packets = SD_NPKT;
|
||
+ for (i = 0; i < SD_NPKT; i++) {
|
||
+ urb->iso_frame_desc[i].length = SD_PKT_SZ;
|
||
+ urb->iso_frame_desc[i].offset = SD_PKT_SZ * i;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+static void sd_stopN(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ reg_w(gspca_dev, 0x003c, 0x0003);
|
||
+ reg_w(gspca_dev, 0x003c, 0x0004);
|
||
+ reg_w(gspca_dev, 0x003c, 0x0005);
|
||
+ reg_w(gspca_dev, 0x003c, 0x0006);
|
||
+ reg_w(gspca_dev, 0x003c, 0x0007);
|
||
+ usb_set_interface(gspca_dev->dev, gspca_dev->iface, gspca_dev->nbalt - 1);
|
||
+}
|
||
+
|
||
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data, /* isoc packet */
|
||
+ int len) /* iso packet length */
|
||
+{
|
||
+ /* unused */
|
||
+}
|
||
+
|
||
+/* reception of an URB */
|
||
+static void sd_isoc_irq(struct urb *urb)
|
||
+{
|
||
+ struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
|
||
+ struct urb *urb0;
|
||
+ u8 *data;
|
||
+ int i, st;
|
||
+
|
||
+ PDEBUG(D_PACK, "sd isoc irq");
|
||
+ if (!gspca_dev->streaming)
|
||
+ return;
|
||
+ if (urb->status != 0) {
|
||
+ if (urb->status == -ESHUTDOWN)
|
||
+ return; /* disconnection */
|
||
+#ifdef CONFIG_PM
|
||
+ if (gspca_dev->frozen)
|
||
+ return;
|
||
+#endif
|
||
+ PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* if this is a control URN (ep 0x83), wait */
|
||
+ if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2])
|
||
+ return;
|
||
+
|
||
+ /* scan both received URBs */
|
||
+ if (urb == gspca_dev->urb[1])
|
||
+ urb0 = gspca_dev->urb[0];
|
||
+ else
|
||
+ urb0 = gspca_dev->urb[2];
|
||
+ for (i = 0; i < urb->number_of_packets; i++) {
|
||
+
|
||
+ /* check the packet status and length */
|
||
+ if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ
|
||
+ || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) {
|
||
+ PDEBUG(D_ERR, "ISOC bad lengths %d / %d",
|
||
+ urb0->iso_frame_desc[i].actual_length,
|
||
+ urb->iso_frame_desc[i].actual_length);
|
||
+ gspca_dev->last_packet_type = DISCARD_PACKET;
|
||
+ continue;
|
||
+ }
|
||
+ st = urb0->iso_frame_desc[i].status;
|
||
+ if (st == 0)
|
||
+ st = urb->iso_frame_desc[i].status;
|
||
+ if (st) {
|
||
+ PDEBUG(D_ERR,
|
||
+ "ISOC data error: [%d] status=%d",
|
||
+ i, st);
|
||
+ gspca_dev->last_packet_type = DISCARD_PACKET;
|
||
+ continue;
|
||
+ }
|
||
+
|
||
+ /*
|
||
+ * The images are received in URBs of different endpoints
|
||
+ * (0x83 and 0x82).
|
||
+ * Image pieces in URBs of ep 0x83 are continuated in URBs of
|
||
+ * ep 0x82 of the same index.
|
||
+ * The packets in the URBs of endpoint 0x83 start with:
|
||
+ * - 80 ba/bb 00 00 = start of image followed by 'ff d8'
|
||
+ * - 04 ba/bb oo oo = image piece
|
||
+ * where 'oo oo' is the image offset
|
||
+ (not cheked)
|
||
+ * - (other -> bad frame)
|
||
+ * The images are JPEG encoded with full header and
|
||
+ * normal ff escape.
|
||
+ * The end of image ('ff d9') may occur in any URB.
|
||
+ * (not cheked)
|
||
+ */
|
||
+ data = (u8 *) urb0->transfer_buffer
|
||
+ + urb0->iso_frame_desc[i].offset;
|
||
+ if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) {
|
||
+
|
||
+ /* new image */
|
||
+ gspca_frame_add(gspca_dev, LAST_PACKET,
|
||
+ NULL, 0);
|
||
+ gspca_frame_add(gspca_dev, FIRST_PACKET,
|
||
+ data + 4, SD_PKT_SZ - 4);
|
||
+ } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) {
|
||
+ gspca_frame_add(gspca_dev, INTER_PACKET,
|
||
+ data + 4, SD_PKT_SZ - 4);
|
||
+ } else {
|
||
+ gspca_dev->last_packet_type = DISCARD_PACKET;
|
||
+ continue;
|
||
+ }
|
||
+ data = (u8 *) urb->transfer_buffer
|
||
+ + urb->iso_frame_desc[i].offset;
|
||
+ gspca_frame_add(gspca_dev, INTER_PACKET,
|
||
+ data, SD_PKT_SZ);
|
||
+ }
|
||
+
|
||
+ /* resubmit the URBs */
|
||
+ st = usb_submit_urb(urb0, GFP_ATOMIC);
|
||
+ if (st < 0)
|
||
+ PDEBUG(D_ERR|D_PACK, "usb_submit_urb(0) ret %d", st);
|
||
+ st = usb_submit_urb(urb, GFP_ATOMIC);
|
||
+ if (st < 0)
|
||
+ PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st);
|
||
+}
|
||
+
|
||
+/* sub-driver description */
|
||
+static const struct sd_desc sd_desc = {
|
||
+ .name = MODULE_NAME,
|
||
+ .ctrls = sd_ctrls,
|
||
+ .nctrls = ARRAY_SIZE(sd_ctrls),
|
||
+ .config = sd_config,
|
||
+ .init = sd_init,
|
||
+ .isoc_init = sd_isoc_init,
|
||
+ .start = sd_start,
|
||
+ .stopN = sd_stopN,
|
||
+ .pkt_scan = sd_pkt_scan,
|
||
+};
|
||
+
|
||
+/* -- module initialisation -- */
|
||
+static const __devinitdata struct usb_device_id device_table[] = {
|
||
+ {USB_DEVICE(0x04a5, 0x3035)},
|
||
+ {}
|
||
+};
|
||
+MODULE_DEVICE_TABLE(usb, device_table);
|
||
+
|
||
+/* -- 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;
|
||
+ info("registered");
|
||
+ return 0;
|
||
+}
|
||
+static void __exit sd_mod_exit(void)
|
||
+{
|
||
+ usb_deregister(&sd_driver);
|
||
+ info("deregistered");
|
||
+}
|
||
+
|
||
+module_init(sd_mod_init);
|
||
+module_exit(sd_mod_exit);
|
||
diff --git a/drivers/media/video/gspca/coarse_expo_autogain.h b/drivers/media/video/gspca/coarse_expo_autogain.h
|
||
new file mode 100644
|
||
index 0000000..1cb9d94
|
||
--- /dev/null
|
||
+++ b/drivers/media/video/gspca/coarse_expo_autogain.h
|
||
@@ -0,0 +1,116 @@
|
||
+/*
|
||
+ * Auto gain algorithm for camera's with a coarse exposure control
|
||
+ *
|
||
+ * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com>
|
||
+ *
|
||
+ * 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
|
||
+ * (at your option) 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
|
||
+ */
|
||
+
|
||
+/* Autogain + exposure algorithm for cameras with a coarse exposure control
|
||
+ (usually this means we can only control the clockdiv to change exposure)
|
||
+ As changing the clockdiv so that the fps drops from 30 to 15 fps for
|
||
+ example, will lead to a huge exposure change (it effectively doubles),
|
||
+ this algorithm normally tries to only adjust the gain (between 40 and
|
||
+ 80 %) and if that does not help, only then changes exposure. This leads
|
||
+ to a much more stable image then using the knee algorithm which at
|
||
+ certain points of the knee graph will only try to adjust exposure,
|
||
+ which leads to oscilating as one exposure step is huge.
|
||
+
|
||
+ Note this assumes that the sd struct for the cam in question has
|
||
+ exp_too_high_cnt and exp_too_high_cnt int members for use by this function.
|
||
+
|
||
+ Returns 0 if no changes were made, 1 if the gain and or exposure settings
|
||
+ where changed. */
|
||
+static int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev,
|
||
+ int avg_lum, int desired_avg_lum, int deadzone)
|
||
+{
|
||
+ int i, steps, gain, orig_gain, exposure, orig_exposure;
|
||
+ int gain_low, gain_high;
|
||
+ const struct ctrl *gain_ctrl = NULL;
|
||
+ const struct ctrl *exposure_ctrl = NULL;
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int retval = 0;
|
||
+
|
||
+ for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
|
||
+ if (gspca_dev->ctrl_dis & (1 << i))
|
||
+ continue;
|
||
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
|
||
+ gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
|
||
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
|
||
+ exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
|
||
+ }
|
||
+ if (!gain_ctrl || !exposure_ctrl) {
|
||
+ PDEBUG(D_ERR, "Error: gspca_coarse_grained_expo_autogain "
|
||
+ "called on cam without gain or exposure");
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ if (gain_ctrl->get(gspca_dev, &gain) ||
|
||
+ exposure_ctrl->get(gspca_dev, &exposure))
|
||
+ return 0;
|
||
+
|
||
+ orig_gain = gain;
|
||
+ orig_exposure = exposure;
|
||
+ gain_low =
|
||
+ (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 2;
|
||
+ gain_low += gain_ctrl->qctrl.minimum;
|
||
+ gain_high =
|
||
+ (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 4;
|
||
+ gain_high += gain_ctrl->qctrl.minimum;
|
||
+
|
||
+ /* If we are of a multiple of deadzone, do multiple steps to reach the
|
||
+ desired lumination fast (with the risc of a slight overshoot) */
|
||
+ steps = (desired_avg_lum - avg_lum) / deadzone;
|
||
+
|
||
+ PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
|
||
+ avg_lum, desired_avg_lum, steps);
|
||
+
|
||
+ if ((gain + steps) > gain_high &&
|
||
+ sd->exposure < exposure_ctrl->qctrl.maximum) {
|
||
+ gain = gain_high;
|
||
+ sd->exp_too_low_cnt++;
|
||
+ } else if ((gain + steps) < gain_low &&
|
||
+ sd->exposure > exposure_ctrl->qctrl.minimum) {
|
||
+ gain = gain_low;
|
||
+ sd->exp_too_high_cnt++;
|
||
+ } else {
|
||
+ gain += steps;
|
||
+ if (gain > gain_ctrl->qctrl.maximum)
|
||
+ gain = gain_ctrl->qctrl.maximum;
|
||
+ else if (gain < gain_ctrl->qctrl.minimum)
|
||
+ gain = gain_ctrl->qctrl.minimum;
|
||
+ sd->exp_too_high_cnt = 0;
|
||
+ sd->exp_too_low_cnt = 0;
|
||
+ }
|
||
+
|
||
+ if (sd->exp_too_high_cnt > 3) {
|
||
+ exposure--;
|
||
+ sd->exp_too_high_cnt = 0;
|
||
+ } else if (sd->exp_too_low_cnt > 3) {
|
||
+ exposure++;
|
||
+ sd->exp_too_low_cnt = 0;
|
||
+ }
|
||
+
|
||
+ if (gain != orig_gain) {
|
||
+ gain_ctrl->set(gspca_dev, gain);
|
||
+ retval = 1;
|
||
+ }
|
||
+ if (exposure != orig_exposure) {
|
||
+ exposure_ctrl->set(gspca_dev, exposure);
|
||
+ retval = 1;
|
||
+ }
|
||
+
|
||
+ return retval;
|
||
+}
|
||
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
|
||
index c98b5d6..19fe6b2 100644
|
||
--- a/drivers/media/video/gspca/conex.c
|
||
+++ b/drivers/media/video/gspca/conex.c
|
||
@@ -52,7 +52,7 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -1032,7 +1032,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
|
||
}
|
||
|
||
/* sub-driver description */
|
||
-static struct sd_desc sd_desc = {
|
||
+static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls,
|
||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c
|
||
new file mode 100644
|
||
index 0000000..7afdc58
|
||
--- /dev/null
|
||
+++ b/drivers/media/video/gspca/cpia1.c
|
||
@@ -0,0 +1,2022 @@
|
||
+/*
|
||
+ * cpia CPiA (1) gspca driver
|
||
+ *
|
||
+ * Copyright (C) 2010 Hans de Goede <hdgoede@redhat.com>
|
||
+ *
|
||
+ * This module is adapted from the in kernel v4l1 cpia driver which is :
|
||
+ *
|
||
+ * (C) Copyright 1999-2000 Peter Pregler
|
||
+ * (C) Copyright 1999-2000 Scott J. Bertin
|
||
+ * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
|
||
+ * (C) Copyright 2000 STMicroelectronics
|
||
+ *
|
||
+ * 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
|
||
+ * (at your option) 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 "cpia1"
|
||
+
|
||
+#include "gspca.h"
|
||
+
|
||
+MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>");
|
||
+MODULE_DESCRIPTION("Vision CPiA");
|
||
+MODULE_LICENSE("GPL");
|
||
+
|
||
+/* constant value's */
|
||
+#define MAGIC_0 0x19
|
||
+#define MAGIC_1 0x68
|
||
+#define DATA_IN 0xC0
|
||
+#define DATA_OUT 0x40
|
||
+#define VIDEOSIZE_QCIF 0 /* 176x144 */
|
||
+#define VIDEOSIZE_CIF 1 /* 352x288 */
|
||
+#define SUBSAMPLE_420 0
|
||
+#define SUBSAMPLE_422 1
|
||
+#define YUVORDER_YUYV 0
|
||
+#define YUVORDER_UYVY 1
|
||
+#define NOT_COMPRESSED 0
|
||
+#define COMPRESSED 1
|
||
+#define NO_DECIMATION 0
|
||
+#define DECIMATION_ENAB 1
|
||
+#define EOI 0xff /* End Of Image */
|
||
+#define EOL 0xfd /* End Of Line */
|
||
+#define FRAME_HEADER_SIZE 64
|
||
+
|
||
+/* Image grab modes */
|
||
+#define CPIA_GRAB_SINGLE 0
|
||
+#define CPIA_GRAB_CONTINEOUS 1
|
||
+
|
||
+/* Compression parameters */
|
||
+#define CPIA_COMPRESSION_NONE 0
|
||
+#define CPIA_COMPRESSION_AUTO 1
|
||
+#define CPIA_COMPRESSION_MANUAL 2
|
||
+#define CPIA_COMPRESSION_TARGET_QUALITY 0
|
||
+#define CPIA_COMPRESSION_TARGET_FRAMERATE 1
|
||
+
|
||
+/* Return offsets for GetCameraState */
|
||
+#define SYSTEMSTATE 0
|
||
+#define GRABSTATE 1
|
||
+#define STREAMSTATE 2
|
||
+#define FATALERROR 3
|
||
+#define CMDERROR 4
|
||
+#define DEBUGFLAGS 5
|
||
+#define VPSTATUS 6
|
||
+#define ERRORCODE 7
|
||
+
|
||
+/* SystemState */
|
||
+#define UNINITIALISED_STATE 0
|
||
+#define PASS_THROUGH_STATE 1
|
||
+#define LO_POWER_STATE 2
|
||
+#define HI_POWER_STATE 3
|
||
+#define WARM_BOOT_STATE 4
|
||
+
|
||
+/* GrabState */
|
||
+#define GRAB_IDLE 0
|
||
+#define GRAB_ACTIVE 1
|
||
+#define GRAB_DONE 2
|
||
+
|
||
+/* StreamState */
|
||
+#define STREAM_NOT_READY 0
|
||
+#define STREAM_READY 1
|
||
+#define STREAM_OPEN 2
|
||
+#define STREAM_PAUSED 3
|
||
+#define STREAM_FINISHED 4
|
||
+
|
||
+/* Fatal Error, CmdError, and DebugFlags */
|
||
+#define CPIA_FLAG 1
|
||
+#define SYSTEM_FLAG 2
|
||
+#define INT_CTRL_FLAG 4
|
||
+#define PROCESS_FLAG 8
|
||
+#define COM_FLAG 16
|
||
+#define VP_CTRL_FLAG 32
|
||
+#define CAPTURE_FLAG 64
|
||
+#define DEBUG_FLAG 128
|
||
+
|
||
+/* VPStatus */
|
||
+#define VP_STATE_OK 0x00
|
||
+
|
||
+#define VP_STATE_FAILED_VIDEOINIT 0x01
|
||
+#define VP_STATE_FAILED_AECACBINIT 0x02
|
||
+#define VP_STATE_AEC_MAX 0x04
|
||
+#define VP_STATE_ACB_BMAX 0x08
|
||
+
|
||
+#define VP_STATE_ACB_RMIN 0x10
|
||
+#define VP_STATE_ACB_GMIN 0x20
|
||
+#define VP_STATE_ACB_RMAX 0x40
|
||
+#define VP_STATE_ACB_GMAX 0x80
|
||
+
|
||
+/* default (minimum) compensation values */
|
||
+#define COMP_RED 220
|
||
+#define COMP_GREEN1 214
|
||
+#define COMP_GREEN2 COMP_GREEN1
|
||
+#define COMP_BLUE 230
|
||
+
|
||
+/* exposure status */
|
||
+#define EXPOSURE_VERY_LIGHT 0
|
||
+#define EXPOSURE_LIGHT 1
|
||
+#define EXPOSURE_NORMAL 2
|
||
+#define EXPOSURE_DARK 3
|
||
+#define EXPOSURE_VERY_DARK 4
|
||
+
|
||
+#define CPIA_MODULE_CPIA (0 << 5)
|
||
+#define CPIA_MODULE_SYSTEM (1 << 5)
|
||
+#define CPIA_MODULE_VP_CTRL (5 << 5)
|
||
+#define CPIA_MODULE_CAPTURE (6 << 5)
|
||
+#define CPIA_MODULE_DEBUG (7 << 5)
|
||
+
|
||
+#define INPUT (DATA_IN << 8)
|
||
+#define OUTPUT (DATA_OUT << 8)
|
||
+
|
||
+#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1)
|
||
+#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2)
|
||
+#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3)
|
||
+#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4)
|
||
+#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5)
|
||
+#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7)
|
||
+#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8)
|
||
+#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10)
|
||
+
|
||
+#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1)
|
||
+#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2)
|
||
+#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3)
|
||
+#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4)
|
||
+#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5)
|
||
+#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6)
|
||
+#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7)
|
||
+#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8)
|
||
+#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9)
|
||
+#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10)
|
||
+#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11)
|
||
+#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12)
|
||
+#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13)
|
||
+
|
||
+#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1)
|
||
+#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2)
|
||
+#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3)
|
||
+#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4)
|
||
+#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6)
|
||
+#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7)
|
||
+#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8)
|
||
+#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9)
|
||
+#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10)
|
||
+#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11)
|
||
+#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16)
|
||
+#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17)
|
||
+#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18)
|
||
+#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19)
|
||
+#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25)
|
||
+#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30)
|
||
+#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31)
|
||
+
|
||
+#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1)
|
||
+#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2)
|
||
+#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3)
|
||
+#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4)
|
||
+#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5)
|
||
+#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6)
|
||
+#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7)
|
||
+#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8)
|
||
+#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9)
|
||
+#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10)
|
||
+#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
|
||
+#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12)
|
||
+#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
|
||
+#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14)
|
||
+#define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15)
|
||
+
|
||
+#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1)
|
||
+#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4)
|
||
+#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5)
|
||
+#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6)
|
||
+#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8)
|
||
+#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9)
|
||
+#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10)
|
||
+#define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11)
|
||
+
|
||
+#define ROUND_UP_EXP_FOR_FLICKER 15
|
||
+
|
||
+/* Constants for automatic frame rate adjustment */
|
||
+#define MAX_EXP 302
|
||
+#define MAX_EXP_102 255
|
||
+#define LOW_EXP 140
|
||
+#define VERY_LOW_EXP 70
|
||
+#define TC 94
|
||
+#define EXP_ACC_DARK 50
|
||
+#define EXP_ACC_LIGHT 90
|
||
+#define HIGH_COMP_102 160
|
||
+#define MAX_COMP 239
|
||
+#define DARK_TIME 3
|
||
+#define LIGHT_TIME 3
|
||
+
|
||
+#define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \
|
||
+ sd->params.version.firmwareRevision == (y))
|
||
+
|
||
+/* Developer's Guide Table 5 p 3-34
|
||
+ * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
|
||
+static u8 flicker_jumps[2][2][4] =
|
||
+{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
|
||
+ { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
|
||
+};
|
||
+
|
||
+struct cam_params {
|
||
+ struct {
|
||
+ u8 firmwareVersion;
|
||
+ u8 firmwareRevision;
|
||
+ u8 vcVersion;
|
||
+ u8 vcRevision;
|
||
+ } version;
|
||
+ struct {
|
||
+ u16 vendor;
|
||
+ u16 product;
|
||
+ u16 deviceRevision;
|
||
+ } pnpID;
|
||
+ struct {
|
||
+ u8 vpVersion;
|
||
+ u8 vpRevision;
|
||
+ u16 cameraHeadID;
|
||
+ } vpVersion;
|
||
+ struct {
|
||
+ u8 systemState;
|
||
+ u8 grabState;
|
||
+ u8 streamState;
|
||
+ u8 fatalError;
|
||
+ u8 cmdError;
|
||
+ u8 debugFlags;
|
||
+ u8 vpStatus;
|
||
+ u8 errorCode;
|
||
+ } status;
|
||
+ struct {
|
||
+ u8 brightness;
|
||
+ u8 contrast;
|
||
+ u8 saturation;
|
||
+ } colourParams;
|
||
+ struct {
|
||
+ u8 gainMode;
|
||
+ u8 expMode;
|
||
+ u8 compMode;
|
||
+ u8 centreWeight;
|
||
+ u8 gain;
|
||
+ u8 fineExp;
|
||
+ u8 coarseExpLo;
|
||
+ u8 coarseExpHi;
|
||
+ u8 redComp;
|
||
+ u8 green1Comp;
|
||
+ u8 green2Comp;
|
||
+ u8 blueComp;
|
||
+ } exposure;
|
||
+ struct {
|
||
+ u8 balanceMode;
|
||
+ u8 redGain;
|
||
+ u8 greenGain;
|
||
+ u8 blueGain;
|
||
+ } colourBalance;
|
||
+ struct {
|
||
+ u8 divisor;
|
||
+ u8 baserate;
|
||
+ } sensorFps;
|
||
+ struct {
|
||
+ u8 gain1;
|
||
+ u8 gain2;
|
||
+ u8 gain4;
|
||
+ u8 gain8;
|
||
+ } apcor;
|
||
+ struct {
|
||
+ u8 disabled;
|
||
+ u8 flickerMode;
|
||
+ u8 coarseJump;
|
||
+ u8 allowableOverExposure;
|
||
+ } flickerControl;
|
||
+ struct {
|
||
+ u8 gain1;
|
||
+ u8 gain2;
|
||
+ u8 gain4;
|
||
+ u8 gain8;
|
||
+ } vlOffset;
|
||
+ struct {
|
||
+ u8 mode;
|
||
+ u8 decimation;
|
||
+ } compression;
|
||
+ struct {
|
||
+ u8 frTargeting;
|
||
+ u8 targetFR;
|
||
+ u8 targetQ;
|
||
+ } compressionTarget;
|
||
+ struct {
|
||
+ u8 yThreshold;
|
||
+ u8 uvThreshold;
|
||
+ } yuvThreshold;
|
||
+ struct {
|
||
+ u8 hysteresis;
|
||
+ u8 threshMax;
|
||
+ u8 smallStep;
|
||
+ u8 largeStep;
|
||
+ u8 decimationHysteresis;
|
||
+ u8 frDiffStepThresh;
|
||
+ u8 qDiffStepThresh;
|
||
+ u8 decimationThreshMod;
|
||
+ } compressionParams;
|
||
+ struct {
|
||
+ u8 videoSize; /* CIF/QCIF */
|
||
+ u8 subSample;
|
||
+ u8 yuvOrder;
|
||
+ } format;
|
||
+ struct { /* Intel QX3 specific data */
|
||
+ u8 qx3_detected; /* a QX3 is present */
|
||
+ u8 toplight; /* top light lit , R/W */
|
||
+ u8 bottomlight; /* bottom light lit, R/W */
|
||
+ u8 button; /* snapshot button pressed (R/O) */
|
||
+ u8 cradled; /* microscope is in cradle (R/O) */
|
||
+ } qx3;
|
||
+ struct {
|
||
+ u8 colStart; /* skip first 8*colStart pixels */
|
||
+ u8 colEnd; /* finish at 8*colEnd pixels */
|
||
+ u8 rowStart; /* skip first 4*rowStart lines */
|
||
+ u8 rowEnd; /* finish at 4*rowEnd lines */
|
||
+ } roi;
|
||
+ u8 ecpTiming;
|
||
+ u8 streamStartLine;
|
||
+};
|
||
+
|
||
+/* specific webcam descriptor */
|
||
+struct sd {
|
||
+ struct gspca_dev gspca_dev; /* !! must be the first item */
|
||
+ struct cam_params params; /* camera settings */
|
||
+
|
||
+ atomic_t cam_exposure;
|
||
+ atomic_t fps;
|
||
+ int exposure_count;
|
||
+ u8 exposure_status;
|
||
+ u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */
|
||
+ u8 first_frame;
|
||
+ u8 freq;
|
||
+};
|
||
+
|
||
+/* V4L2 controls supported by the driver */
|
||
+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);
|
||
+static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+
|
||
+static struct ctrl sd_ctrls[] = {
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_BRIGHTNESS,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Brightness",
|
||
+ .minimum = 0,
|
||
+ .maximum = 100,
|
||
+ .step = 1,
|
||
+#define BRIGHTNESS_DEF 50
|
||
+ .default_value = BRIGHTNESS_DEF,
|
||
+ .flags = 0,
|
||
+ },
|
||
+ .set = sd_setbrightness,
|
||
+ .get = sd_getbrightness,
|
||
+ },
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_CONTRAST,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Contrast",
|
||
+ .minimum = 0,
|
||
+ .maximum = 96,
|
||
+ .step = 8,
|
||
+#define CONTRAST_DEF 48
|
||
+ .default_value = CONTRAST_DEF,
|
||
+ },
|
||
+ .set = sd_setcontrast,
|
||
+ .get = sd_getcontrast,
|
||
+ },
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_SATURATION,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Saturation",
|
||
+ .minimum = 0,
|
||
+ .maximum = 100,
|
||
+ .step = 1,
|
||
+#define SATURATION_DEF 50
|
||
+ .default_value = SATURATION_DEF,
|
||
+ },
|
||
+ .set = sd_setsaturation,
|
||
+ .get = sd_getsaturation,
|
||
+ },
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_POWER_LINE_FREQUENCY,
|
||
+ .type = V4L2_CTRL_TYPE_MENU,
|
||
+ .name = "Light frequency filter",
|
||
+ .minimum = 0,
|
||
+ .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
|
||
+ .step = 1,
|
||
+#define FREQ_DEF 1
|
||
+ .default_value = FREQ_DEF,
|
||
+ },
|
||
+ .set = sd_setfreq,
|
||
+ .get = sd_getfreq,
|
||
+ },
|
||
+ {
|
||
+ {
|
||
+#define V4L2_CID_COMP_TARGET V4L2_CID_PRIVATE_BASE
|
||
+ .id = V4L2_CID_COMP_TARGET,
|
||
+ .type = V4L2_CTRL_TYPE_MENU,
|
||
+ .name = "Compression Target",
|
||
+ .minimum = 0,
|
||
+ .maximum = 1,
|
||
+ .step = 1,
|
||
+#define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY
|
||
+ .default_value = COMP_TARGET_DEF,
|
||
+ },
|
||
+ .set = sd_setcomptarget,
|
||
+ .get = sd_getcomptarget,
|
||
+ },
|
||
+};
|
||
+
|
||
+static const struct v4l2_pix_format mode[] = {
|
||
+ {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
|
||
+ /* The sizeimage is trial and error, as with low framerates
|
||
+ the camera will pad out usb frames, making the image
|
||
+ data larger then strictly necessary */
|
||
+ .bytesperline = 160,
|
||
+ .sizeimage = 65536,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = 3},
|
||
+ {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 172,
|
||
+ .sizeimage = 65536,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = 2},
|
||
+ {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 320,
|
||
+ .sizeimage = 262144,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = 1},
|
||
+ {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 352,
|
||
+ .sizeimage = 262144,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = 0},
|
||
+};
|
||
+
|
||
+/**********************************************************************
|
||
+ *
|
||
+ * General functions
|
||
+ *
|
||
+ **********************************************************************/
|
||
+
|
||
+static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command)
|
||
+{
|
||
+ u8 requesttype;
|
||
+ unsigned int pipe;
|
||
+ int ret, databytes = command[6] | (command[7] << 8);
|
||
+ /* Sometimes we see spurious EPIPE errors */
|
||
+ int retries = 3;
|
||
+
|
||
+ if (command[0] == DATA_IN) {
|
||
+ pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
|
||
+ requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
|
||
+ } else if (command[0] == DATA_OUT) {
|
||
+ pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
|
||
+ requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
|
||
+ } else {
|
||
+ PDEBUG(D_ERR, "Unexpected first byte of command: %x",
|
||
+ command[0]);
|
||
+ return -EINVAL;
|
||
+ }
|
||
+
|
||
+retry:
|
||
+ ret = usb_control_msg(gspca_dev->dev, pipe,
|
||
+ command[1],
|
||
+ requesttype,
|
||
+ command[2] | (command[3] << 8),
|
||
+ command[4] | (command[5] << 8),
|
||
+ gspca_dev->usb_buf, databytes, 1000);
|
||
+
|
||
+ if (ret < 0)
|
||
+ PDEBUG(D_ERR, "usb_control_msg %02x, error %d", command[1],
|
||
+ ret);
|
||
+
|
||
+ if (ret == -EPIPE && retries > 0) {
|
||
+ retries--;
|
||
+ goto retry;
|
||
+ }
|
||
+
|
||
+ return (ret < 0) ? ret : 0;
|
||
+}
|
||
+
|
||
+/* send an arbitrary command to the camera */
|
||
+static int do_command(struct gspca_dev *gspca_dev, u16 command,
|
||
+ u8 a, u8 b, u8 c, u8 d)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int ret, datasize;
|
||
+ u8 cmd[8];
|
||
+
|
||
+ switch (command) {
|
||
+ case CPIA_COMMAND_GetCPIAVersion:
|
||
+ case CPIA_COMMAND_GetPnPID:
|
||
+ case CPIA_COMMAND_GetCameraStatus:
|
||
+ case CPIA_COMMAND_GetVPVersion:
|
||
+ case CPIA_COMMAND_GetColourParams:
|
||
+ case CPIA_COMMAND_GetColourBalance:
|
||
+ case CPIA_COMMAND_GetExposure:
|
||
+ datasize = 8;
|
||
+ break;
|
||
+ case CPIA_COMMAND_ReadMCPorts:
|
||
+ case CPIA_COMMAND_ReadVCRegs:
|
||
+ datasize = 4;
|
||
+ break;
|
||
+ default:
|
||
+ datasize = 0;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ cmd[0] = command >> 8;
|
||
+ cmd[1] = command & 0xff;
|
||
+ cmd[2] = a;
|
||
+ cmd[3] = b;
|
||
+ cmd[4] = c;
|
||
+ cmd[5] = d;
|
||
+ cmd[6] = datasize;
|
||
+ cmd[7] = 0;
|
||
+
|
||
+ ret = cpia_usb_transferCmd(gspca_dev, cmd);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ switch (command) {
|
||
+ case CPIA_COMMAND_GetCPIAVersion:
|
||
+ sd->params.version.firmwareVersion = gspca_dev->usb_buf[0];
|
||
+ sd->params.version.firmwareRevision = gspca_dev->usb_buf[1];
|
||
+ sd->params.version.vcVersion = gspca_dev->usb_buf[2];
|
||
+ sd->params.version.vcRevision = gspca_dev->usb_buf[3];
|
||
+ break;
|
||
+ case CPIA_COMMAND_GetPnPID:
|
||
+ sd->params.pnpID.vendor =
|
||
+ gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
|
||
+ sd->params.pnpID.product =
|
||
+ gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
|
||
+ sd->params.pnpID.deviceRevision =
|
||
+ gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8);
|
||
+ break;
|
||
+ case CPIA_COMMAND_GetCameraStatus:
|
||
+ sd->params.status.systemState = gspca_dev->usb_buf[0];
|
||
+ sd->params.status.grabState = gspca_dev->usb_buf[1];
|
||
+ sd->params.status.streamState = gspca_dev->usb_buf[2];
|
||
+ sd->params.status.fatalError = gspca_dev->usb_buf[3];
|
||
+ sd->params.status.cmdError = gspca_dev->usb_buf[4];
|
||
+ sd->params.status.debugFlags = gspca_dev->usb_buf[5];
|
||
+ sd->params.status.vpStatus = gspca_dev->usb_buf[6];
|
||
+ sd->params.status.errorCode = gspca_dev->usb_buf[7];
|
||
+ break;
|
||
+ case CPIA_COMMAND_GetVPVersion:
|
||
+ sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0];
|
||
+ sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1];
|
||
+ sd->params.vpVersion.cameraHeadID =
|
||
+ gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
|
||
+ break;
|
||
+ case CPIA_COMMAND_GetColourParams:
|
||
+ sd->params.colourParams.brightness = gspca_dev->usb_buf[0];
|
||
+ sd->params.colourParams.contrast = gspca_dev->usb_buf[1];
|
||
+ sd->params.colourParams.saturation = gspca_dev->usb_buf[2];
|
||
+ break;
|
||
+ case CPIA_COMMAND_GetColourBalance:
|
||
+ sd->params.colourBalance.redGain = gspca_dev->usb_buf[0];
|
||
+ sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1];
|
||
+ sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2];
|
||
+ break;
|
||
+ case CPIA_COMMAND_GetExposure:
|
||
+ sd->params.exposure.gain = gspca_dev->usb_buf[0];
|
||
+ sd->params.exposure.fineExp = gspca_dev->usb_buf[1];
|
||
+ sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2];
|
||
+ sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3];
|
||
+ sd->params.exposure.redComp = gspca_dev->usb_buf[4];
|
||
+ sd->params.exposure.green1Comp = gspca_dev->usb_buf[5];
|
||
+ sd->params.exposure.green2Comp = gspca_dev->usb_buf[6];
|
||
+ sd->params.exposure.blueComp = gspca_dev->usb_buf[7];
|
||
+ break;
|
||
+
|
||
+ case CPIA_COMMAND_ReadMCPorts:
|
||
+ if (!sd->params.qx3.qx3_detected)
|
||
+ break;
|
||
+ /* test button press */
|
||
+ sd->params.qx3.button = ((gspca_dev->usb_buf[1] & 0x02) == 0);
|
||
+ if (sd->params.qx3.button) {
|
||
+ /* button pressed - unlock the latch */
|
||
+ do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
|
||
+ 3, 0xDF, 0xDF, 0);
|
||
+ do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
|
||
+ 3, 0xFF, 0xFF, 0);
|
||
+ }
|
||
+
|
||
+ /* test whether microscope is cradled */
|
||
+ sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* send a command to the camera with an additional data transaction */
|
||
+static int do_command_extended(struct gspca_dev *gspca_dev, u16 command,
|
||
+ u8 a, u8 b, u8 c, u8 d,
|
||
+ u8 e, u8 f, u8 g, u8 h,
|
||
+ u8 i, u8 j, u8 k, u8 l)
|
||
+{
|
||
+ u8 cmd[8];
|
||
+
|
||
+ cmd[0] = command >> 8;
|
||
+ cmd[1] = command & 0xff;
|
||
+ cmd[2] = a;
|
||
+ cmd[3] = b;
|
||
+ cmd[4] = c;
|
||
+ cmd[5] = d;
|
||
+ cmd[6] = 8;
|
||
+ cmd[7] = 0;
|
||
+ gspca_dev->usb_buf[0] = e;
|
||
+ gspca_dev->usb_buf[1] = f;
|
||
+ gspca_dev->usb_buf[2] = g;
|
||
+ gspca_dev->usb_buf[3] = h;
|
||
+ gspca_dev->usb_buf[4] = i;
|
||
+ gspca_dev->usb_buf[5] = j;
|
||
+ gspca_dev->usb_buf[6] = k;
|
||
+ gspca_dev->usb_buf[7] = l;
|
||
+
|
||
+ return cpia_usb_transferCmd(gspca_dev, cmd);
|
||
+}
|
||
+
|
||
+/* find_over_exposure
|
||
+ * Finds a suitable value of OverExposure for use with SetFlickerCtrl
|
||
+ * Some calculation is required because this value changes with the brightness
|
||
+ * set with SetColourParameters
|
||
+ *
|
||
+ * Parameters: Brightness - last brightness value set with SetColourParameters
|
||
+ *
|
||
+ * Returns: OverExposure value to use with SetFlickerCtrl
|
||
+ */
|
||
+#define FLICKER_MAX_EXPOSURE 250
|
||
+#define FLICKER_ALLOWABLE_OVER_EXPOSURE 146
|
||
+#define FLICKER_BRIGHTNESS_CONSTANT 59
|
||
+static int find_over_exposure(int brightness)
|
||
+{
|
||
+ int MaxAllowableOverExposure, OverExposure;
|
||
+
|
||
+ MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
|
||
+ FLICKER_BRIGHTNESS_CONSTANT;
|
||
+
|
||
+ if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE)
|
||
+ OverExposure = MaxAllowableOverExposure;
|
||
+ else
|
||
+ OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE;
|
||
+
|
||
+ return OverExposure;
|
||
+}
|
||
+#undef FLICKER_MAX_EXPOSURE
|
||
+#undef FLICKER_ALLOWABLE_OVER_EXPOSURE
|
||
+#undef FLICKER_BRIGHTNESS_CONSTANT
|
||
+
|
||
+/* initialise cam_data structure */
|
||
+static void reset_camera_params(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ struct cam_params *params = &sd->params;
|
||
+
|
||
+ /* The following parameter values are the defaults from
|
||
+ * "Software Developer's Guide for CPiA Cameras". Any changes
|
||
+ * to the defaults are noted in comments. */
|
||
+ params->colourParams.brightness = BRIGHTNESS_DEF;
|
||
+ params->colourParams.contrast = CONTRAST_DEF;
|
||
+ params->colourParams.saturation = SATURATION_DEF;
|
||
+ params->exposure.gainMode = 4;
|
||
+ params->exposure.expMode = 2; /* AEC */
|
||
+ params->exposure.compMode = 1;
|
||
+ params->exposure.centreWeight = 1;
|
||
+ params->exposure.gain = 0;
|
||
+ params->exposure.fineExp = 0;
|
||
+ params->exposure.coarseExpLo = 185;
|
||
+ params->exposure.coarseExpHi = 0;
|
||
+ params->exposure.redComp = COMP_RED;
|
||
+ params->exposure.green1Comp = COMP_GREEN1;
|
||
+ params->exposure.green2Comp = COMP_GREEN2;
|
||
+ params->exposure.blueComp = COMP_BLUE;
|
||
+ params->colourBalance.balanceMode = 2; /* ACB */
|
||
+ params->colourBalance.redGain = 32;
|
||
+ params->colourBalance.greenGain = 6;
|
||
+ params->colourBalance.blueGain = 92;
|
||
+ params->apcor.gain1 = 0x18;
|
||
+ params->apcor.gain2 = 0x16;
|
||
+ params->apcor.gain4 = 0x24;
|
||
+ params->apcor.gain8 = 0x34;
|
||
+ params->flickerControl.flickerMode = 0;
|
||
+ params->flickerControl.disabled = 1;
|
||
+
|
||
+ params->flickerControl.coarseJump =
|
||
+ flicker_jumps[sd->mainsFreq]
|
||
+ [params->sensorFps.baserate]
|
||
+ [params->sensorFps.divisor];
|
||
+ params->flickerControl.allowableOverExposure =
|
||
+ find_over_exposure(params->colourParams.brightness);
|
||
+ params->vlOffset.gain1 = 20;
|
||
+ params->vlOffset.gain2 = 24;
|
||
+ params->vlOffset.gain4 = 26;
|
||
+ params->vlOffset.gain8 = 26;
|
||
+ params->compressionParams.hysteresis = 3;
|
||
+ params->compressionParams.threshMax = 11;
|
||
+ params->compressionParams.smallStep = 1;
|
||
+ params->compressionParams.largeStep = 3;
|
||
+ params->compressionParams.decimationHysteresis = 2;
|
||
+ params->compressionParams.frDiffStepThresh = 5;
|
||
+ params->compressionParams.qDiffStepThresh = 3;
|
||
+ params->compressionParams.decimationThreshMod = 2;
|
||
+ /* End of default values from Software Developer's Guide */
|
||
+
|
||
+ /* Set Sensor FPS to 15fps. This seems better than 30fps
|
||
+ * for indoor lighting. */
|
||
+ params->sensorFps.divisor = 1;
|
||
+ params->sensorFps.baserate = 1;
|
||
+
|
||
+ params->yuvThreshold.yThreshold = 6; /* From windows driver */
|
||
+ params->yuvThreshold.uvThreshold = 6; /* From windows driver */
|
||
+
|
||
+ params->format.subSample = SUBSAMPLE_420;
|
||
+ params->format.yuvOrder = YUVORDER_YUYV;
|
||
+
|
||
+ params->compression.mode = CPIA_COMPRESSION_AUTO;
|
||
+ params->compression.decimation = NO_DECIMATION;
|
||
+
|
||
+ params->compressionTarget.frTargeting = COMP_TARGET_DEF;
|
||
+ params->compressionTarget.targetFR = 15; /* From windows driver */
|
||
+ params->compressionTarget.targetQ = 5; /* From windows driver */
|
||
+
|
||
+ params->qx3.qx3_detected = 0;
|
||
+ params->qx3.toplight = 0;
|
||
+ params->qx3.bottomlight = 0;
|
||
+ params->qx3.button = 0;
|
||
+ params->qx3.cradled = 0;
|
||
+}
|
||
+
|
||
+static void printstatus(struct cam_params *params)
|
||
+{
|
||
+ PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||
+ params->status.systemState, params->status.grabState,
|
||
+ params->status.streamState, params->status.fatalError,
|
||
+ params->status.cmdError, params->status.debugFlags,
|
||
+ params->status.vpStatus, params->status.errorCode);
|
||
+}
|
||
+
|
||
+static int goto_low_power(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int ret;
|
||
+
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ if (sd->params.status.systemState != LO_POWER_STATE) {
|
||
+ if (sd->params.status.systemState != WARM_BOOT_STATE) {
|
||
+ PDEBUG(D_ERR,
|
||
+ "unexpected state after lo power cmd: %02x",
|
||
+ sd->params.status.systemState);
|
||
+ printstatus(&sd->params);
|
||
+ }
|
||
+ return -EIO;
|
||
+ }
|
||
+
|
||
+ PDEBUG(D_CONF, "camera now in LOW power state");
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int goto_high_power(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int ret;
|
||
+
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ msleep_interruptible(40); /* windows driver does it too */
|
||
+
|
||
+ if (signal_pending(current))
|
||
+ return -EINTR;
|
||
+
|
||
+ do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ if (sd->params.status.systemState != HI_POWER_STATE) {
|
||
+ PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x",
|
||
+ sd->params.status.systemState);
|
||
+ printstatus(&sd->params);
|
||
+ return -EIO;
|
||
+ }
|
||
+
|
||
+ PDEBUG(D_CONF, "camera now in HIGH power state");
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int get_version_information(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ /* GetCPIAVersion */
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ /* GetPnPID */
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
|
||
+}
|
||
+
|
||
+static int save_camera_state(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
|
||
+}
|
||
+
|
||
+int command_setformat(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int ret;
|
||
+
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat,
|
||
+ sd->params.format.videoSize,
|
||
+ sd->params.format.subSample,
|
||
+ sd->params.format.yuvOrder, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetROI,
|
||
+ sd->params.roi.colStart, sd->params.roi.colEnd,
|
||
+ sd->params.roi.rowStart, sd->params.roi.rowEnd);
|
||
+}
|
||
+
|
||
+int command_setcolourparams(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetColourParams,
|
||
+ sd->params.colourParams.brightness,
|
||
+ sd->params.colourParams.contrast,
|
||
+ sd->params.colourParams.saturation, 0);
|
||
+}
|
||
+
|
||
+int command_setapcor(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetApcor,
|
||
+ sd->params.apcor.gain1,
|
||
+ sd->params.apcor.gain2,
|
||
+ sd->params.apcor.gain4,
|
||
+ sd->params.apcor.gain8);
|
||
+}
|
||
+
|
||
+int command_setvloffset(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset,
|
||
+ sd->params.vlOffset.gain1,
|
||
+ sd->params.vlOffset.gain2,
|
||
+ sd->params.vlOffset.gain4,
|
||
+ sd->params.vlOffset.gain8);
|
||
+}
|
||
+
|
||
+int command_setexposure(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int ret;
|
||
+
|
||
+ ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
|
||
+ sd->params.exposure.gainMode,
|
||
+ 1,
|
||
+ sd->params.exposure.compMode,
|
||
+ sd->params.exposure.centreWeight,
|
||
+ sd->params.exposure.gain,
|
||
+ sd->params.exposure.fineExp,
|
||
+ sd->params.exposure.coarseExpLo,
|
||
+ sd->params.exposure.coarseExpHi,
|
||
+ sd->params.exposure.redComp,
|
||
+ sd->params.exposure.green1Comp,
|
||
+ sd->params.exposure.green2Comp,
|
||
+ sd->params.exposure.blueComp);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ if (sd->params.exposure.expMode != 1) {
|
||
+ ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
|
||
+ 0,
|
||
+ sd->params.exposure.expMode,
|
||
+ 0, 0,
|
||
+ sd->params.exposure.gain,
|
||
+ sd->params.exposure.fineExp,
|
||
+ sd->params.exposure.coarseExpLo,
|
||
+ sd->params.exposure.coarseExpHi,
|
||
+ 0, 0, 0, 0);
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+int command_setcolourbalance(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ if (sd->params.colourBalance.balanceMode == 1) {
|
||
+ int ret;
|
||
+
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
|
||
+ 1,
|
||
+ sd->params.colourBalance.redGain,
|
||
+ sd->params.colourBalance.greenGain,
|
||
+ sd->params.colourBalance.blueGain);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
|
||
+ 3, 0, 0, 0);
|
||
+ }
|
||
+ if (sd->params.colourBalance.balanceMode == 2) {
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
|
||
+ 2, 0, 0, 0);
|
||
+ }
|
||
+ if (sd->params.colourBalance.balanceMode == 3) {
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
|
||
+ 3, 0, 0, 0);
|
||
+ }
|
||
+
|
||
+ return -EINVAL;
|
||
+}
|
||
+
|
||
+int command_setcompressiontarget(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget,
|
||
+ sd->params.compressionTarget.frTargeting,
|
||
+ sd->params.compressionTarget.targetFR,
|
||
+ sd->params.compressionTarget.targetQ, 0);
|
||
+}
|
||
+
|
||
+int command_setyuvtresh(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh,
|
||
+ sd->params.yuvThreshold.yThreshold,
|
||
+ sd->params.yuvThreshold.uvThreshold, 0, 0);
|
||
+}
|
||
+
|
||
+int command_setcompressionparams(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ return do_command_extended(gspca_dev,
|
||
+ CPIA_COMMAND_SetCompressionParams,
|
||
+ 0, 0, 0, 0,
|
||
+ sd->params.compressionParams.hysteresis,
|
||
+ sd->params.compressionParams.threshMax,
|
||
+ sd->params.compressionParams.smallStep,
|
||
+ sd->params.compressionParams.largeStep,
|
||
+ sd->params.compressionParams.decimationHysteresis,
|
||
+ sd->params.compressionParams.frDiffStepThresh,
|
||
+ sd->params.compressionParams.qDiffStepThresh,
|
||
+ sd->params.compressionParams.decimationThreshMod);
|
||
+}
|
||
+
|
||
+int command_setcompression(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetCompression,
|
||
+ sd->params.compression.mode,
|
||
+ sd->params.compression.decimation, 0, 0);
|
||
+}
|
||
+
|
||
+int command_setsensorfps(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS,
|
||
+ sd->params.sensorFps.divisor,
|
||
+ sd->params.sensorFps.baserate, 0, 0);
|
||
+}
|
||
+
|
||
+int command_setflickerctrl(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl,
|
||
+ sd->params.flickerControl.flickerMode,
|
||
+ sd->params.flickerControl.coarseJump,
|
||
+ sd->params.flickerControl.allowableOverExposure,
|
||
+ 0);
|
||
+}
|
||
+
|
||
+int command_setecptiming(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming,
|
||
+ sd->params.ecpTiming, 0, 0, 0);
|
||
+}
|
||
+
|
||
+int command_pause(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
|
||
+}
|
||
+
|
||
+int command_resume(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap,
|
||
+ 0, sd->params.streamStartLine, 0, 0);
|
||
+}
|
||
+
|
||
+int command_setlights(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int ret, p1, p2;
|
||
+
|
||
+ if (!sd->params.qx3.qx3_detected)
|
||
+ return 0;
|
||
+
|
||
+ p1 = (sd->params.qx3.bottomlight == 0) << 1;
|
||
+ p2 = (sd->params.qx3.toplight == 0) << 3;
|
||
+
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg,
|
||
+ 0x90, 0x8F, 0x50, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0,
|
||
+ p1 | p2 | 0xE0, 0);
|
||
+}
|
||
+
|
||
+static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply)
|
||
+{
|
||
+ /* Everything in here is from the Windows driver */
|
||
+/* define for compgain calculation */
|
||
+#if 0 /* keep */
|
||
+#define COMPGAIN(base, curexp, newexp) \
|
||
+ (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5)
|
||
+#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
|
||
+ (u16)((float)curexp * (float)(u8)(curcomp + 128) / \
|
||
+ (float)(u8)(basecomp - 128))
|
||
+#else
|
||
+ /* equivalent functions without floating point math */
|
||
+#define COMPGAIN(base, curexp, newexp) \
|
||
+ (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp)))
|
||
+#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
|
||
+ (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
|
||
+#endif
|
||
+
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int currentexp = sd->params.exposure.coarseExpLo +
|
||
+ sd->params.exposure.coarseExpHi * 256;
|
||
+ int ret, startexp;
|
||
+
|
||
+ if (on) {
|
||
+ int cj = sd->params.flickerControl.coarseJump;
|
||
+ sd->params.flickerControl.flickerMode = 1;
|
||
+ sd->params.flickerControl.disabled = 0;
|
||
+ if (sd->params.exposure.expMode != 2) {
|
||
+ sd->params.exposure.expMode = 2;
|
||
+ sd->exposure_status = EXPOSURE_NORMAL;
|
||
+ }
|
||
+ currentexp = currentexp << sd->params.exposure.gain;
|
||
+ sd->params.exposure.gain = 0;
|
||
+ /* round down current exposure to nearest value */
|
||
+ startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj;
|
||
+ if (startexp < 1)
|
||
+ startexp = 1;
|
||
+ startexp = (startexp * cj) - 1;
|
||
+ if (FIRMWARE_VERSION(1, 2))
|
||
+ while (startexp > MAX_EXP_102)
|
||
+ startexp -= cj;
|
||
+ else
|
||
+ while (startexp > MAX_EXP)
|
||
+ startexp -= cj;
|
||
+ sd->params.exposure.coarseExpLo = startexp & 0xff;
|
||
+ sd->params.exposure.coarseExpHi = startexp >> 8;
|
||
+ if (currentexp > startexp) {
|
||
+ if (currentexp > (2 * startexp))
|
||
+ currentexp = 2 * startexp;
|
||
+ sd->params.exposure.redComp =
|
||
+ COMPGAIN(COMP_RED, currentexp, startexp);
|
||
+ sd->params.exposure.green1Comp =
|
||
+ COMPGAIN(COMP_GREEN1, currentexp, startexp);
|
||
+ sd->params.exposure.green2Comp =
|
||
+ COMPGAIN(COMP_GREEN2, currentexp, startexp);
|
||
+ sd->params.exposure.blueComp =
|
||
+ COMPGAIN(COMP_BLUE, currentexp, startexp);
|
||
+ } else {
|
||
+ sd->params.exposure.redComp = COMP_RED;
|
||
+ sd->params.exposure.green1Comp = COMP_GREEN1;
|
||
+ sd->params.exposure.green2Comp = COMP_GREEN2;
|
||
+ sd->params.exposure.blueComp = COMP_BLUE;
|
||
+ }
|
||
+ if (FIRMWARE_VERSION(1, 2))
|
||
+ sd->params.exposure.compMode = 0;
|
||
+ else
|
||
+ sd->params.exposure.compMode = 1;
|
||
+
|
||
+ sd->params.apcor.gain1 = 0x18;
|
||
+ sd->params.apcor.gain2 = 0x18;
|
||
+ sd->params.apcor.gain4 = 0x16;
|
||
+ sd->params.apcor.gain8 = 0x14;
|
||
+ } else {
|
||
+ sd->params.flickerControl.flickerMode = 0;
|
||
+ sd->params.flickerControl.disabled = 1;
|
||
+ /* Average equivalent coarse for each comp channel */
|
||
+ startexp = EXP_FROM_COMP(COMP_RED,
|
||
+ sd->params.exposure.redComp, currentexp);
|
||
+ startexp += EXP_FROM_COMP(COMP_GREEN1,
|
||
+ sd->params.exposure.green1Comp, currentexp);
|
||
+ startexp += EXP_FROM_COMP(COMP_GREEN2,
|
||
+ sd->params.exposure.green2Comp, currentexp);
|
||
+ startexp += EXP_FROM_COMP(COMP_BLUE,
|
||
+ sd->params.exposure.blueComp, currentexp);
|
||
+ startexp = startexp >> 2;
|
||
+ while (startexp > MAX_EXP && sd->params.exposure.gain <
|
||
+ sd->params.exposure.gainMode - 1) {
|
||
+ startexp = startexp >> 1;
|
||
+ ++sd->params.exposure.gain;
|
||
+ }
|
||
+ if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102)
|
||
+ startexp = MAX_EXP_102;
|
||
+ if (startexp > MAX_EXP)
|
||
+ startexp = MAX_EXP;
|
||
+ sd->params.exposure.coarseExpLo = startexp & 0xff;
|
||
+ sd->params.exposure.coarseExpHi = startexp >> 8;
|
||
+ sd->params.exposure.redComp = COMP_RED;
|
||
+ sd->params.exposure.green1Comp = COMP_GREEN1;
|
||
+ sd->params.exposure.green2Comp = COMP_GREEN2;
|
||
+ sd->params.exposure.blueComp = COMP_BLUE;
|
||
+ sd->params.exposure.compMode = 1;
|
||
+ sd->params.apcor.gain1 = 0x18;
|
||
+ sd->params.apcor.gain2 = 0x16;
|
||
+ sd->params.apcor.gain4 = 0x24;
|
||
+ sd->params.apcor.gain8 = 0x34;
|
||
+ }
|
||
+ sd->params.vlOffset.gain1 = 20;
|
||
+ sd->params.vlOffset.gain2 = 24;
|
||
+ sd->params.vlOffset.gain4 = 26;
|
||
+ sd->params.vlOffset.gain8 = 26;
|
||
+
|
||
+ if (apply) {
|
||
+ ret = command_setexposure(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ ret = command_setapcor(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ ret = command_setvloffset(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ ret = command_setflickerctrl(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+#undef EXP_FROM_COMP
|
||
+#undef COMPGAIN
|
||
+}
|
||
+
|
||
+/* monitor the exposure and adjust the sensor frame rate if needed */
|
||
+static void monitor_exposure(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ u8 exp_acc, bcomp, gain, coarseL, cmd[8];
|
||
+ int ret, light_exp, dark_exp, very_dark_exp;
|
||
+ int old_exposure, new_exposure, framerate;
|
||
+ int setfps = 0, setexp = 0, setflicker = 0;
|
||
+
|
||
+ /* get necessary stats and register settings from camera */
|
||
+ /* do_command can't handle this, so do it ourselves */
|
||
+ cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8;
|
||
+ cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff;
|
||
+ cmd[2] = 30;
|
||
+ cmd[3] = 4;
|
||
+ cmd[4] = 9;
|
||
+ cmd[5] = 8;
|
||
+ cmd[6] = 8;
|
||
+ cmd[7] = 0;
|
||
+ ret = cpia_usb_transferCmd(gspca_dev, cmd);
|
||
+ if (ret) {
|
||
+ PDEBUG(D_ERR, "ReadVPRegs(30,4,9,8) - failed: %d", ret);
|
||
+ return;
|
||
+ }
|
||
+ exp_acc = gspca_dev->usb_buf[0];
|
||
+ bcomp = gspca_dev->usb_buf[1];
|
||
+ gain = gspca_dev->usb_buf[2];
|
||
+ coarseL = gspca_dev->usb_buf[3];
|
||
+
|
||
+ light_exp = sd->params.colourParams.brightness +
|
||
+ TC - 50 + EXP_ACC_LIGHT;
|
||
+ if (light_exp > 255)
|
||
+ light_exp = 255;
|
||
+ dark_exp = sd->params.colourParams.brightness +
|
||
+ TC - 50 - EXP_ACC_DARK;
|
||
+ if (dark_exp < 0)
|
||
+ dark_exp = 0;
|
||
+ very_dark_exp = dark_exp / 2;
|
||
+
|
||
+ old_exposure = sd->params.exposure.coarseExpHi * 256 +
|
||
+ sd->params.exposure.coarseExpLo;
|
||
+
|
||
+ if (!sd->params.flickerControl.disabled) {
|
||
+ /* Flicker control on */
|
||
+ int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP :
|
||
+ HIGH_COMP_102;
|
||
+ bcomp += 128; /* decode */
|
||
+ if (bcomp >= max_comp && exp_acc < dark_exp) {
|
||
+ /* dark */
|
||
+ if (exp_acc < very_dark_exp) {
|
||
+ /* very dark */
|
||
+ if (sd->exposure_status == EXPOSURE_VERY_DARK)
|
||
+ ++sd->exposure_count;
|
||
+ else {
|
||
+ sd->exposure_status =
|
||
+ EXPOSURE_VERY_DARK;
|
||
+ sd->exposure_count = 1;
|
||
+ }
|
||
+ } else {
|
||
+ /* just dark */
|
||
+ if (sd->exposure_status == EXPOSURE_DARK)
|
||
+ ++sd->exposure_count;
|
||
+ else {
|
||
+ sd->exposure_status = EXPOSURE_DARK;
|
||
+ sd->exposure_count = 1;
|
||
+ }
|
||
+ }
|
||
+ } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
|
||
+ /* light */
|
||
+ if (old_exposure <= VERY_LOW_EXP) {
|
||
+ /* very light */
|
||
+ if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
|
||
+ ++sd->exposure_count;
|
||
+ else {
|
||
+ sd->exposure_status =
|
||
+ EXPOSURE_VERY_LIGHT;
|
||
+ sd->exposure_count = 1;
|
||
+ }
|
||
+ } else {
|
||
+ /* just light */
|
||
+ if (sd->exposure_status == EXPOSURE_LIGHT)
|
||
+ ++sd->exposure_count;
|
||
+ else {
|
||
+ sd->exposure_status = EXPOSURE_LIGHT;
|
||
+ sd->exposure_count = 1;
|
||
+ }
|
||
+ }
|
||
+ } else {
|
||
+ /* not dark or light */
|
||
+ sd->exposure_status = EXPOSURE_NORMAL;
|
||
+ }
|
||
+ } else {
|
||
+ /* Flicker control off */
|
||
+ if (old_exposure >= MAX_EXP && exp_acc < dark_exp) {
|
||
+ /* dark */
|
||
+ if (exp_acc < very_dark_exp) {
|
||
+ /* very dark */
|
||
+ if (sd->exposure_status == EXPOSURE_VERY_DARK)
|
||
+ ++sd->exposure_count;
|
||
+ else {
|
||
+ sd->exposure_status =
|
||
+ EXPOSURE_VERY_DARK;
|
||
+ sd->exposure_count = 1;
|
||
+ }
|
||
+ } else {
|
||
+ /* just dark */
|
||
+ if (sd->exposure_status == EXPOSURE_DARK)
|
||
+ ++sd->exposure_count;
|
||
+ else {
|
||
+ sd->exposure_status = EXPOSURE_DARK;
|
||
+ sd->exposure_count = 1;
|
||
+ }
|
||
+ }
|
||
+ } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
|
||
+ /* light */
|
||
+ if (old_exposure <= VERY_LOW_EXP) {
|
||
+ /* very light */
|
||
+ if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
|
||
+ ++sd->exposure_count;
|
||
+ else {
|
||
+ sd->exposure_status =
|
||
+ EXPOSURE_VERY_LIGHT;
|
||
+ sd->exposure_count = 1;
|
||
+ }
|
||
+ } else {
|
||
+ /* just light */
|
||
+ if (sd->exposure_status == EXPOSURE_LIGHT)
|
||
+ ++sd->exposure_count;
|
||
+ else {
|
||
+ sd->exposure_status = EXPOSURE_LIGHT;
|
||
+ sd->exposure_count = 1;
|
||
+ }
|
||
+ }
|
||
+ } else {
|
||
+ /* not dark or light */
|
||
+ sd->exposure_status = EXPOSURE_NORMAL;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ framerate = atomic_read(&sd->fps);
|
||
+ if (framerate > 30 || framerate < 1)
|
||
+ framerate = 1;
|
||
+
|
||
+ if (!sd->params.flickerControl.disabled) {
|
||
+ /* Flicker control on */
|
||
+ if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
|
||
+ sd->exposure_status == EXPOSURE_DARK) &&
|
||
+ sd->exposure_count >= DARK_TIME * framerate &&
|
||
+ sd->params.sensorFps.divisor < 3) {
|
||
+
|
||
+ /* dark for too long */
|
||
+ ++sd->params.sensorFps.divisor;
|
||
+ setfps = 1;
|
||
+
|
||
+ sd->params.flickerControl.coarseJump =
|
||
+ flicker_jumps[sd->mainsFreq]
|
||
+ [sd->params.sensorFps.baserate]
|
||
+ [sd->params.sensorFps.divisor];
|
||
+ setflicker = 1;
|
||
+
|
||
+ new_exposure = sd->params.flickerControl.coarseJump-1;
|
||
+ while (new_exposure < old_exposure / 2)
|
||
+ new_exposure +=
|
||
+ sd->params.flickerControl.coarseJump;
|
||
+ sd->params.exposure.coarseExpLo = new_exposure & 0xff;
|
||
+ sd->params.exposure.coarseExpHi = new_exposure >> 8;
|
||
+ setexp = 1;
|
||
+ sd->exposure_status = EXPOSURE_NORMAL;
|
||
+ PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
|
||
+
|
||
+ } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
|
||
+ sd->exposure_status == EXPOSURE_LIGHT) &&
|
||
+ sd->exposure_count >= LIGHT_TIME * framerate &&
|
||
+ sd->params.sensorFps.divisor > 0) {
|
||
+
|
||
+ /* light for too long */
|
||
+ int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 :
|
||
+ MAX_EXP;
|
||
+ --sd->params.sensorFps.divisor;
|
||
+ setfps = 1;
|
||
+
|
||
+ sd->params.flickerControl.coarseJump =
|
||
+ flicker_jumps[sd->mainsFreq]
|
||
+ [sd->params.sensorFps.baserate]
|
||
+ [sd->params.sensorFps.divisor];
|
||
+ setflicker = 1;
|
||
+
|
||
+ new_exposure = sd->params.flickerControl.coarseJump-1;
|
||
+ while (new_exposure < 2 * old_exposure &&
|
||
+ new_exposure +
|
||
+ sd->params.flickerControl.coarseJump < max_exp)
|
||
+ new_exposure +=
|
||
+ sd->params.flickerControl.coarseJump;
|
||
+ sd->params.exposure.coarseExpLo = new_exposure & 0xff;
|
||
+ sd->params.exposure.coarseExpHi = new_exposure >> 8;
|
||
+ setexp = 1;
|
||
+ sd->exposure_status = EXPOSURE_NORMAL;
|
||
+ PDEBUG(D_CONF, "Automatically increasing sensor_fps");
|
||
+ }
|
||
+ } else {
|
||
+ /* Flicker control off */
|
||
+ if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
|
||
+ sd->exposure_status == EXPOSURE_DARK) &&
|
||
+ sd->exposure_count >= DARK_TIME * framerate &&
|
||
+ sd->params.sensorFps.divisor < 3) {
|
||
+
|
||
+ /* dark for too long */
|
||
+ ++sd->params.sensorFps.divisor;
|
||
+ setfps = 1;
|
||
+
|
||
+ if (sd->params.exposure.gain > 0) {
|
||
+ --sd->params.exposure.gain;
|
||
+ setexp = 1;
|
||
+ }
|
||
+ sd->exposure_status = EXPOSURE_NORMAL;
|
||
+ PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
|
||
+
|
||
+ } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
|
||
+ sd->exposure_status == EXPOSURE_LIGHT) &&
|
||
+ sd->exposure_count >= LIGHT_TIME * framerate &&
|
||
+ sd->params.sensorFps.divisor > 0) {
|
||
+
|
||
+ /* light for too long */
|
||
+ --sd->params.sensorFps.divisor;
|
||
+ setfps = 1;
|
||
+
|
||
+ if (sd->params.exposure.gain <
|
||
+ sd->params.exposure.gainMode - 1) {
|
||
+ ++sd->params.exposure.gain;
|
||
+ setexp = 1;
|
||
+ }
|
||
+ sd->exposure_status = EXPOSURE_NORMAL;
|
||
+ PDEBUG(D_CONF, "Automatically increasing sensor_fps");
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (setexp)
|
||
+ command_setexposure(gspca_dev);
|
||
+
|
||
+ if (setfps)
|
||
+ command_setsensorfps(gspca_dev);
|
||
+
|
||
+ if (setflicker)
|
||
+ command_setflickerctrl(gspca_dev);
|
||
+}
|
||
+
|
||
+/*-----------------------------------------------------------------*/
|
||
+/* if flicker is switched off, this function switches it back on.It checks,
|
||
+ however, that conditions are suitable before restarting it.
|
||
+ This should only be called for firmware version 1.2.
|
||
+
|
||
+ It also adjust the colour balance when an exposure step is detected - as
|
||
+ long as flicker is running
|
||
+*/
|
||
+static void restart_flicker(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int cam_exposure, old_exp;
|
||
+
|
||
+ if (!FIRMWARE_VERSION(1, 2))
|
||
+ return;
|
||
+
|
||
+ cam_exposure = atomic_read(&sd->cam_exposure);
|
||
+
|
||
+ if (sd->params.flickerControl.flickerMode == 0 ||
|
||
+ cam_exposure == 0)
|
||
+ return;
|
||
+
|
||
+ old_exp = sd->params.exposure.coarseExpLo +
|
||
+ sd->params.exposure.coarseExpHi*256;
|
||
+ /*
|
||
+ see how far away camera exposure is from a valid
|
||
+ flicker exposure value
|
||
+ */
|
||
+ cam_exposure %= sd->params.flickerControl.coarseJump;
|
||
+ if (!sd->params.flickerControl.disabled &&
|
||
+ cam_exposure <= sd->params.flickerControl.coarseJump - 3) {
|
||
+ /* Flicker control auto-disabled */
|
||
+ sd->params.flickerControl.disabled = 1;
|
||
+ }
|
||
+
|
||
+ if (sd->params.flickerControl.disabled &&
|
||
+ old_exp > sd->params.flickerControl.coarseJump +
|
||
+ ROUND_UP_EXP_FOR_FLICKER) {
|
||
+ /* exposure is now high enough to switch
|
||
+ flicker control back on */
|
||
+ set_flicker(gspca_dev, 1, 1);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* this function is called at probe time */
|
||
+static int sd_config(struct gspca_dev *gspca_dev,
|
||
+ const struct usb_device_id *id)
|
||
+{
|
||
+ struct cam *cam;
|
||
+
|
||
+ reset_camera_params(gspca_dev);
|
||
+
|
||
+ PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)",
|
||
+ id->idVendor, id->idProduct);
|
||
+
|
||
+ cam = &gspca_dev->cam;
|
||
+ cam->cam_mode = mode;
|
||
+ cam->nmodes = ARRAY_SIZE(mode);
|
||
+
|
||
+ sd_setfreq(gspca_dev, FREQ_DEF);
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* -- start the camera -- */
|
||
+static int sd_start(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int priv, ret;
|
||
+
|
||
+ /* Start the camera in low power mode */
|
||
+ if (goto_low_power(gspca_dev)) {
|
||
+ if (sd->params.status.systemState != WARM_BOOT_STATE) {
|
||
+ PDEBUG(D_ERR, "unexpected systemstate: %02x",
|
||
+ sd->params.status.systemState);
|
||
+ printstatus(&sd->params);
|
||
+ return -ENODEV;
|
||
+ }
|
||
+
|
||
+ /* FIXME: this is just dirty trial and error */
|
||
+ ret = goto_high_power(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame,
|
||
+ 0, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ ret = goto_low_power(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ }
|
||
+
|
||
+ /* procedure described in developer's guide p3-28 */
|
||
+
|
||
+ /* Check the firmware version. */
|
||
+ sd->params.version.firmwareVersion = 0;
|
||
+ get_version_information(gspca_dev);
|
||
+ if (sd->params.version.firmwareVersion != 1) {
|
||
+ PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)",
|
||
+ sd->params.version.firmwareVersion);
|
||
+ return -ENODEV;
|
||
+ }
|
||
+
|
||
+ /* A bug in firmware 1-02 limits gainMode to 2 */
|
||
+ if (sd->params.version.firmwareRevision <= 2 &&
|
||
+ sd->params.exposure.gainMode > 2) {
|
||
+ sd->params.exposure.gainMode = 2;
|
||
+ }
|
||
+
|
||
+ /* set QX3 detected flag */
|
||
+ sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 &&
|
||
+ sd->params.pnpID.product == 0x0001);
|
||
+
|
||
+ /* The fatal error checking should be done after
|
||
+ * the camera powers up (developer's guide p 3-38) */
|
||
+
|
||
+ /* Set streamState before transition to high power to avoid bug
|
||
+ * in firmware 1-02 */
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus,
|
||
+ STREAMSTATE, 0, STREAM_NOT_READY, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ /* GotoHiPower */
|
||
+ ret = goto_high_power(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ /* Check the camera status */
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ if (sd->params.status.fatalError) {
|
||
+ PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x",
|
||
+ sd->params.status.fatalError,
|
||
+ sd->params.status.vpStatus);
|
||
+ return -EIO;
|
||
+ }
|
||
+
|
||
+ /* VPVersion can't be retrieved before the camera is in HiPower,
|
||
+ * so get it here instead of in get_version_information. */
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ /* Determine video mode settings */
|
||
+ sd->params.streamStartLine = 120;
|
||
+
|
||
+ priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
|
||
+ if (priv & 0x01) { /* crop */
|
||
+ sd->params.roi.colStart = 2;
|
||
+ sd->params.roi.rowStart = 6;
|
||
+ } else {
|
||
+ sd->params.roi.colStart = 0;
|
||
+ sd->params.roi.rowStart = 0;
|
||
+ }
|
||
+
|
||
+ if (priv & 0x02) { /* quarter */
|
||
+ sd->params.format.videoSize = VIDEOSIZE_QCIF;
|
||
+ sd->params.roi.colStart /= 2;
|
||
+ sd->params.roi.rowStart /= 2;
|
||
+ sd->params.streamStartLine /= 2;
|
||
+ } else
|
||
+ sd->params.format.videoSize = VIDEOSIZE_CIF;
|
||
+
|
||
+ sd->params.roi.colEnd = sd->params.roi.colStart +
|
||
+ (gspca_dev->width >> 3);
|
||
+ sd->params.roi.rowEnd = sd->params.roi.rowStart +
|
||
+ (gspca_dev->height >> 2);
|
||
+
|
||
+ /* And now set the camera to a known state */
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode,
|
||
+ CPIA_GRAB_CONTINEOUS, 0, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ /* We start with compression disabled, as we need one uncompressed
|
||
+ frame to handle later compressed frames */
|
||
+ ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression,
|
||
+ CPIA_COMPRESSION_NONE,
|
||
+ NO_DECIMATION, 0, 0);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setcompressiontarget(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setcolourparams(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setformat(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setyuvtresh(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setecptiming(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setcompressionparams(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setexposure(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setcolourbalance(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setsensorfps(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setapcor(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setflickerctrl(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ ret = command_setvloffset(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ /* Start stream */
|
||
+ ret = command_resume(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ /* Wait 6 frames before turning compression on for the sensor to get
|
||
+ all settings and AEC/ACB to settle */
|
||
+ sd->first_frame = 6;
|
||
+ sd->exposure_status = EXPOSURE_NORMAL;
|
||
+ sd->exposure_count = 0;
|
||
+ atomic_set(&sd->cam_exposure, 0);
|
||
+ atomic_set(&sd->fps, 0);
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static void sd_stopN(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ command_pause(gspca_dev);
|
||
+
|
||
+ /* save camera state for later open (developers guide ch 3.5.3) */
|
||
+ save_camera_state(gspca_dev);
|
||
+
|
||
+ /* GotoLoPower */
|
||
+ goto_low_power(gspca_dev);
|
||
+
|
||
+ /* Update the camera status */
|
||
+ do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
|
||
+}
|
||
+
|
||
+/* this function is called at probe and resume time */
|
||
+static int sd_init(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int ret;
|
||
+
|
||
+ /* Start / Stop the camera to make sure we are talking to
|
||
+ a supported camera, and to get some information from it
|
||
+ to print. */
|
||
+ ret = sd_start(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+
|
||
+ sd_stopN(gspca_dev);
|
||
+
|
||
+ PDEBUG(D_PROBE, "CPIA Version: %d.%02d (%d.%d)",
|
||
+ sd->params.version.firmwareVersion,
|
||
+ sd->params.version.firmwareRevision,
|
||
+ sd->params.version.vcVersion,
|
||
+ sd->params.version.vcRevision);
|
||
+ PDEBUG(D_PROBE, "CPIA PnP-ID: %04x:%04x:%04x",
|
||
+ sd->params.pnpID.vendor, sd->params.pnpID.product,
|
||
+ sd->params.pnpID.deviceRevision);
|
||
+ PDEBUG(D_PROBE, "VP-Version: %d.%d %04x",
|
||
+ sd->params.vpVersion.vpVersion,
|
||
+ sd->params.vpVersion.vpRevision,
|
||
+ sd->params.vpVersion.cameraHeadID);
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data,
|
||
+ int len)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ /* Check for SOF */
|
||
+ if (len >= 64 &&
|
||
+ data[0] == MAGIC_0 && data[1] == MAGIC_1 &&
|
||
+ data[16] == sd->params.format.videoSize &&
|
||
+ data[17] == sd->params.format.subSample &&
|
||
+ data[18] == sd->params.format.yuvOrder &&
|
||
+ data[24] == sd->params.roi.colStart &&
|
||
+ data[25] == sd->params.roi.colEnd &&
|
||
+ data[26] == sd->params.roi.rowStart &&
|
||
+ data[27] == sd->params.roi.rowEnd) {
|
||
+ struct gspca_frame *frame = gspca_get_i_frame(gspca_dev);
|
||
+
|
||
+ atomic_set(&sd->cam_exposure, data[39] * 2);
|
||
+ atomic_set(&sd->fps, data[41]);
|
||
+
|
||
+ if (frame == NULL) {
|
||
+ gspca_dev->last_packet_type = DISCARD_PACKET;
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* Check for proper EOF for last frame */
|
||
+ if ((frame->data_end - frame->data) > 4 &&
|
||
+ frame->data_end[-4] == 0xff &&
|
||
+ frame->data_end[-3] == 0xff &&
|
||
+ frame->data_end[-2] == 0xff &&
|
||
+ frame->data_end[-1] == 0xff)
|
||
+ gspca_frame_add(gspca_dev, LAST_PACKET,
|
||
+ NULL, 0);
|
||
+
|
||
+ gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
|
||
+}
|
||
+
|
||
+static void sd_dq_callback(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ /* Set the normal compression settings once we have captured a
|
||
+ few uncompressed frames (and AEC has hopefully settled) */
|
||
+ if (sd->first_frame) {
|
||
+ sd->first_frame--;
|
||
+ if (sd->first_frame == 0)
|
||
+ command_setcompression(gspca_dev);
|
||
+ }
|
||
+
|
||
+ /* Switch flicker control back on if it got turned off */
|
||
+ restart_flicker(gspca_dev);
|
||
+
|
||
+ /* If AEC is enabled, monitor the exposure and
|
||
+ adjust the sensor frame rate if needed */
|
||
+ if (sd->params.exposure.expMode == 2)
|
||
+ monitor_exposure(gspca_dev);
|
||
+
|
||
+ /* Update our knowledge of the camera state */
|
||
+ do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
|
||
+ if (sd->params.qx3.qx3_detected)
|
||
+ do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
|
||
+}
|
||
+
|
||
+static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int ret;
|
||
+
|
||
+ sd->params.colourParams.brightness = val;
|
||
+ sd->params.flickerControl.allowableOverExposure =
|
||
+ find_over_exposure(sd->params.colourParams.brightness);
|
||
+ if (gspca_dev->streaming) {
|
||
+ ret = command_setcolourparams(gspca_dev);
|
||
+ if (ret)
|
||
+ return ret;
|
||
+ return command_setflickerctrl(gspca_dev);
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->params.colourParams.brightness;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->params.colourParams.contrast = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ return command_setcolourparams(gspca_dev);
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->params.colourParams.contrast;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->params.colourParams.saturation = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ return command_setcolourparams(gspca_dev);
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->params.colourParams.saturation;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int on;
|
||
+
|
||
+ switch (val) {
|
||
+ case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
|
||
+ on = 0;
|
||
+ break;
|
||
+ case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
|
||
+ on = 1;
|
||
+ sd->mainsFreq = 0;
|
||
+ break;
|
||
+ case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
|
||
+ on = 1;
|
||
+ sd->mainsFreq = 1;
|
||
+ break;
|
||
+ default:
|
||
+ return -EINVAL;
|
||
+ }
|
||
+
|
||
+ sd->freq = val;
|
||
+ sd->params.flickerControl.coarseJump =
|
||
+ flicker_jumps[sd->mainsFreq]
|
||
+ [sd->params.sensorFps.baserate]
|
||
+ [sd->params.sensorFps.divisor];
|
||
+
|
||
+ return set_flicker(gspca_dev, on, gspca_dev->streaming);
|
||
+}
|
||
+
|
||
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->freq;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->params.compressionTarget.frTargeting = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ return command_setcompressiontarget(gspca_dev);
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->params.compressionTarget.frTargeting;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_querymenu(struct gspca_dev *gspca_dev,
|
||
+ struct v4l2_querymenu *menu)
|
||
+{
|
||
+ switch (menu->id) {
|
||
+ case V4L2_CID_POWER_LINE_FREQUENCY:
|
||
+ switch (menu->index) {
|
||
+ case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
|
||
+ strcpy((char *) menu->name, "NoFliker");
|
||
+ return 0;
|
||
+ case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
|
||
+ strcpy((char *) menu->name, "50 Hz");
|
||
+ return 0;
|
||
+ case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
|
||
+ strcpy((char *) menu->name, "60 Hz");
|
||
+ return 0;
|
||
+ }
|
||
+ break;
|
||
+ case V4L2_CID_COMP_TARGET:
|
||
+ switch (menu->index) {
|
||
+ case CPIA_COMPRESSION_TARGET_QUALITY:
|
||
+ strcpy((char *) menu->name, "Quality");
|
||
+ return 0;
|
||
+ case CPIA_COMPRESSION_TARGET_FRAMERATE:
|
||
+ strcpy((char *) menu->name, "Framerate");
|
||
+ return 0;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ return -EINVAL;
|
||
+}
|
||
+
|
||
+/* sub-driver description */
|
||
+static const struct sd_desc sd_desc = {
|
||
+ .name = MODULE_NAME,
|
||
+ .ctrls = sd_ctrls,
|
||
+ .nctrls = ARRAY_SIZE(sd_ctrls),
|
||
+ .config = sd_config,
|
||
+ .init = sd_init,
|
||
+ .start = sd_start,
|
||
+ .stopN = sd_stopN,
|
||
+ .dq_callback = sd_dq_callback,
|
||
+ .pkt_scan = sd_pkt_scan,
|
||
+ .querymenu = sd_querymenu,
|
||
+};
|
||
+
|
||
+/* -- module initialisation -- */
|
||
+static const __devinitdata struct usb_device_id device_table[] = {
|
||
+ {USB_DEVICE(0x0553, 0x0002)},
|
||
+ {USB_DEVICE(0x0813, 0x0001)},
|
||
+ {}
|
||
+};
|
||
+MODULE_DEVICE_TABLE(usb, device_table);
|
||
+
|
||
+/* -- 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/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
|
||
index fdf4c0e..6ac9eac 100644
|
||
--- a/drivers/media/video/gspca/etoms.c
|
||
+++ b/drivers/media/video/gspca/etoms.c
|
||
@@ -52,7 +52,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||
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[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -706,6 +706,12 @@ static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain)
|
||
|
||
i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
|
||
i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1);
|
||
+#if 0
|
||
+ i2c_w(gspca_dev, 0x09, &gain, 1, 1);
|
||
+ i2c_w(gspca_dev, 0x0a, &gain, 1, 1);
|
||
+ i2c_w(gspca_dev, 0x0b, &gain, 1, 1);
|
||
+ i2c_w(gspca_dev, 0x0c, &gain, 1, 1);
|
||
+#endif
|
||
}
|
||
}
|
||
|
||
@@ -851,7 +857,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
}
|
||
|
||
/* sub-driver description */
|
||
-static struct sd_desc sd_desc = {
|
||
+static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls,
|
||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c
|
||
index 4878c8f..9e42476 100644
|
||
--- a/drivers/media/video/gspca/gl860/gl860.c
|
||
+++ b/drivers/media/video/gspca/gl860/gl860.c
|
||
@@ -161,7 +161,7 @@ static int gl860_build_control_table(struct gspca_dev *gspca_dev)
|
||
|
||
/*==================== sud-driver structure initialisation =================*/
|
||
|
||
-static struct sd_desc sd_desc_mi1320 = {
|
||
+static const struct sd_desc sd_desc_mi1320 = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls_mi1320,
|
||
.nctrls = GL860_NCTRLS,
|
||
@@ -174,7 +174,7 @@ static struct sd_desc sd_desc_mi1320 = {
|
||
.dq_callback = sd_callback,
|
||
};
|
||
|
||
-static struct sd_desc sd_desc_mi2020 = {
|
||
+static const struct sd_desc sd_desc_mi2020 = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls_mi2020,
|
||
.nctrls = GL860_NCTRLS,
|
||
@@ -187,7 +187,7 @@ static struct sd_desc sd_desc_mi2020 = {
|
||
.dq_callback = sd_callback,
|
||
};
|
||
|
||
-static struct sd_desc sd_desc_mi2020b = {
|
||
+static const struct sd_desc sd_desc_mi2020b = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls_mi2020b,
|
||
.nctrls = GL860_NCTRLS,
|
||
@@ -200,7 +200,7 @@ static struct sd_desc sd_desc_mi2020b = {
|
||
.dq_callback = sd_callback,
|
||
};
|
||
|
||
-static struct sd_desc sd_desc_ov2640 = {
|
||
+static const struct sd_desc sd_desc_ov2640 = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls_ov2640,
|
||
.nctrls = GL860_NCTRLS,
|
||
@@ -213,7 +213,7 @@ static struct sd_desc sd_desc_ov2640 = {
|
||
.dq_callback = sd_callback,
|
||
};
|
||
|
||
-static struct sd_desc sd_desc_ov9655 = {
|
||
+static const struct sd_desc sd_desc_ov9655 = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls_ov9655,
|
||
.nctrls = GL860_NCTRLS,
|
||
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
|
||
index bd6214d..85c966e 100644
|
||
--- a/drivers/media/video/gspca/gspca.c
|
||
+++ b/drivers/media/video/gspca/gspca.c
|
||
@@ -3,6 +3,9 @@
|
||
*
|
||
* Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr)
|
||
*
|
||
+ * Camera button input handling by Márton Németh
|
||
+ * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
|
||
+ *
|
||
* 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 (at your
|
||
@@ -37,6 +40,9 @@
|
||
|
||
#include "gspca.h"
|
||
|
||
+#include <linux/input.h>
|
||
+#include <linux/usb/input.h>
|
||
+
|
||
/* global values */
|
||
#define DEF_NURBS 3 /* default number of URBs */
|
||
#if DEF_NURBS > MAX_NURBS
|
||
@@ -47,7 +53,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
|
||
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
|
||
MODULE_LICENSE("GPL");
|
||
|
||
-#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 8, 0)
|
||
+#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 9, 0)
|
||
|
||
#ifdef GSPCA_DEBUG
|
||
int gspca_debug = D_ERR | D_PROBE;
|
||
@@ -104,15 +110,184 @@ static const struct vm_operations_struct gspca_vm_ops = {
|
||
.close = gspca_vm_close,
|
||
};
|
||
|
||
+/*
|
||
+ * Input and interrupt endpoint handling functions
|
||
+ */
|
||
+#ifdef CONFIG_INPUT
|
||
+static void int_irq(struct urb *urb)
|
||
+{
|
||
+ struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
|
||
+ int ret;
|
||
+
|
||
+ ret = urb->status;
|
||
+ switch (ret) {
|
||
+ case 0:
|
||
+ if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev,
|
||
+ urb->transfer_buffer, urb->actual_length) < 0) {
|
||
+ PDEBUG(D_ERR, "Unknown packet received");
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case -ENOENT:
|
||
+ case -ECONNRESET:
|
||
+ case -ENODEV:
|
||
+ case -ESHUTDOWN:
|
||
+ /* Stop is requested either by software or hardware is gone,
|
||
+ * keep the ret value non-zero and don't resubmit later.
|
||
+ */
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status);
|
||
+ urb->status = 0;
|
||
+ ret = 0;
|
||
+ }
|
||
+
|
||
+ if (ret == 0) {
|
||
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||
+ if (ret < 0)
|
||
+ PDEBUG(D_ERR, "Resubmit URB failed with error %i", ret);
|
||
+ }
|
||
+}
|
||
+
|
||
+static int gspca_input_connect(struct gspca_dev *dev)
|
||
+{
|
||
+ struct input_dev *input_dev;
|
||
+ int err = 0;
|
||
+
|
||
+ dev->input_dev = NULL;
|
||
+ if (dev->sd_desc->int_pkt_scan || dev->sd_desc->other_input) {
|
||
+ input_dev = input_allocate_device();
|
||
+ if (!input_dev)
|
||
+ return -ENOMEM;
|
||
+
|
||
+ usb_make_path(dev->dev, dev->phys, sizeof(dev->phys));
|
||
+ strlcat(dev->phys, "/input0", sizeof(dev->phys));
|
||
+
|
||
+ input_dev->name = dev->sd_desc->name;
|
||
+ input_dev->phys = dev->phys;
|
||
+
|
||
+ usb_to_input_id(dev->dev, &input_dev->id);
|
||
+
|
||
+ input_dev->evbit[0] = BIT_MASK(EV_KEY);
|
||
+ input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
|
||
+ input_dev->dev.parent = &dev->dev->dev;
|
||
+ err = input_register_device(input_dev);
|
||
+ if (err) {
|
||
+ PDEBUG(D_ERR, "Input device registration failed "
|
||
+ "with error %i", err);
|
||
+ input_dev->dev.parent = NULL;
|
||
+ input_free_device(input_dev);
|
||
+ } else {
|
||
+ dev->input_dev = input_dev;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return err;
|
||
+}
|
||
+
|
||
+static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
|
||
+ struct usb_endpoint_descriptor *ep)
|
||
+{
|
||
+ unsigned int buffer_len;
|
||
+ int interval;
|
||
+ struct urb *urb;
|
||
+ struct usb_device *dev;
|
||
+ void *buffer = NULL;
|
||
+ int ret = -EINVAL;
|
||
+
|
||
+ buffer_len = ep->wMaxPacketSize;
|
||
+ interval = ep->bInterval;
|
||
+ PDEBUG(D_PROBE, "found int in endpoint: 0x%x, "
|
||
+ "buffer_len=%u, interval=%u",
|
||
+ ep->bEndpointAddress, buffer_len, interval);
|
||
+
|
||
+ dev = gspca_dev->dev;
|
||
+
|
||
+ urb = usb_alloc_urb(0, GFP_KERNEL);
|
||
+ if (!urb) {
|
||
+ ret = -ENOMEM;
|
||
+ goto error;
|
||
+ }
|
||
+
|
||
+ buffer = usb_buffer_alloc(dev, ep->wMaxPacketSize,
|
||
+ GFP_KERNEL, &urb->transfer_dma);
|
||
+ if (!buffer) {
|
||
+ ret = -ENOMEM;
|
||
+ goto error_buffer;
|
||
+ }
|
||
+ usb_fill_int_urb(urb, dev,
|
||
+ usb_rcvintpipe(dev, ep->bEndpointAddress),
|
||
+ buffer, buffer_len,
|
||
+ int_irq, (void *)gspca_dev, interval);
|
||
+ gspca_dev->int_urb = urb;
|
||
+ ret = usb_submit_urb(urb, GFP_KERNEL);
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "submit URB failed with error %i", ret);
|
||
+ goto error_submit;
|
||
+ }
|
||
+ return ret;
|
||
+
|
||
+error_submit:
|
||
+ usb_buffer_free(dev,
|
||
+ urb->transfer_buffer_length,
|
||
+ urb->transfer_buffer,
|
||
+ urb->transfer_dma);
|
||
+error_buffer:
|
||
+ usb_free_urb(urb);
|
||
+error:
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+static void gspca_input_create_urb(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct usb_interface *intf;
|
||
+ struct usb_host_interface *intf_desc;
|
||
+ struct usb_endpoint_descriptor *ep;
|
||
+ int i;
|
||
+
|
||
+ if (gspca_dev->sd_desc->int_pkt_scan) {
|
||
+ intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
|
||
+ intf_desc = intf->cur_altsetting;
|
||
+ for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
|
||
+ ep = &intf_desc->endpoint[i].desc;
|
||
+ if (usb_endpoint_dir_in(ep) &&
|
||
+ usb_endpoint_xfer_int(ep)) {
|
||
+
|
||
+ alloc_and_submit_int_urb(gspca_dev, ep);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct urb *urb;
|
||
+
|
||
+ urb = gspca_dev->int_urb;
|
||
+ if (urb) {
|
||
+ gspca_dev->int_urb = NULL;
|
||
+ usb_kill_urb(urb);
|
||
+ usb_buffer_free(gspca_dev->dev,
|
||
+ urb->transfer_buffer_length,
|
||
+ urb->transfer_buffer,
|
||
+ urb->transfer_dma);
|
||
+ usb_free_urb(urb);
|
||
+ }
|
||
+}
|
||
+#else
|
||
+#define gspca_input_connect(gspca_dev) 0
|
||
+#define gspca_input_create_urb(gspca_dev)
|
||
+#define gspca_input_destroy_urb(gspca_dev)
|
||
+#endif
|
||
+
|
||
/* get the current input frame buffer */
|
||
struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct gspca_frame *frame;
|
||
- int i;
|
||
|
||
- i = gspca_dev->fr_i;
|
||
- i = gspca_dev->fr_queue[i];
|
||
- frame = &gspca_dev->frame[i];
|
||
+ frame = gspca_dev->cur_frame;
|
||
if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
|
||
!= V4L2_BUF_FLAG_QUEUED)
|
||
return NULL;
|
||
@@ -486,11 +661,13 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
|
||
i, ep->desc.bEndpointAddress);
|
||
gspca_dev->alt = i; /* memorize the current alt setting */
|
||
if (gspca_dev->nbalt > 1) {
|
||
+ gspca_input_destroy_urb(gspca_dev);
|
||
ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
|
||
if (ret < 0) {
|
||
err("set alt %d err %d", i, ret);
|
||
- return NULL;
|
||
+ ep = NULL;
|
||
}
|
||
+ gspca_input_create_urb(gspca_dev);
|
||
}
|
||
return ep;
|
||
}
|
||
@@ -534,26 +711,22 @@ static int create_urbs(struct gspca_dev *gspca_dev,
|
||
nurbs = 1;
|
||
}
|
||
|
||
- gspca_dev->nurbs = nurbs;
|
||
for (n = 0; n < nurbs; n++) {
|
||
urb = usb_alloc_urb(npkt, GFP_KERNEL);
|
||
if (!urb) {
|
||
err("usb_alloc_urb failed");
|
||
- destroy_urbs(gspca_dev);
|
||
return -ENOMEM;
|
||
}
|
||
+ gspca_dev->urb[n] = urb;
|
||
urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
|
||
bsize,
|
||
GFP_KERNEL,
|
||
&urb->transfer_dma);
|
||
|
||
if (urb->transfer_buffer == NULL) {
|
||
- usb_free_urb(urb);
|
||
- err("usb_buffer_urb failed");
|
||
- destroy_urbs(gspca_dev);
|
||
+ err("usb_buffer_alloc failed");
|
||
return -ENOMEM;
|
||
}
|
||
- gspca_dev->urb[n] = urb;
|
||
urb->dev = gspca_dev->dev;
|
||
urb->context = gspca_dev;
|
||
urb->transfer_buffer_length = bsize;
|
||
@@ -585,6 +758,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,
|
||
static int gspca_init_transfer(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct usb_host_endpoint *ep;
|
||
+ struct urb *urb;
|
||
int n, ret;
|
||
|
||
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
|
||
@@ -595,6 +769,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
|
||
goto out;
|
||
}
|
||
|
||
+ gspca_dev->usb_err = 0;
|
||
+
|
||
/* set the higher alternate setting and
|
||
* loop until urb submit succeeds */
|
||
if (gspca_dev->cam.reverse_alts)
|
||
@@ -613,10 +789,15 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
|
||
goto out;
|
||
}
|
||
for (;;) {
|
||
- PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
|
||
- ret = create_urbs(gspca_dev, ep);
|
||
- if (ret < 0)
|
||
- goto out;
|
||
+ if (!gspca_dev->cam.no_urb_create) {
|
||
+ PDEBUG(D_STREAM, "init transfer alt %d",
|
||
+ gspca_dev->alt);
|
||
+ ret = create_urbs(gspca_dev, ep);
|
||
+ if (ret < 0) {
|
||
+ destroy_urbs(gspca_dev);
|
||
+ goto out;
|
||
+ }
|
||
+ }
|
||
|
||
/* clear the bulk endpoint */
|
||
if (gspca_dev->cam.bulk)
|
||
@@ -636,8 +817,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
|
||
break;
|
||
|
||
/* submit the URBs */
|
||
- for (n = 0; n < gspca_dev->nurbs; n++) {
|
||
- ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
|
||
+ for (n = 0; n < MAX_NURBS; n++) {
|
||
+ urb = gspca_dev->urb[n];
|
||
+ if (urb == NULL)
|
||
+ break;
|
||
+ ret = usb_submit_urb(urb, GFP_KERNEL);
|
||
if (ret < 0)
|
||
break;
|
||
}
|
||
@@ -694,7 +878,9 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
|
||
if (gspca_dev->sd_desc->stopN)
|
||
gspca_dev->sd_desc->stopN(gspca_dev);
|
||
destroy_urbs(gspca_dev);
|
||
+ gspca_input_destroy_urb(gspca_dev);
|
||
gspca_set_alt0(gspca_dev);
|
||
+ gspca_input_create_urb(gspca_dev);
|
||
}
|
||
|
||
/* always call stop0 to free the subdriver's resources */
|
||
@@ -2060,11 +2246,12 @@ int gspca_dev_probe(struct usb_interface *intf,
|
||
PDEBUG(D_ERR, "Too many config");
|
||
return -ENODEV;
|
||
}
|
||
+
|
||
+ /* the USB video interface must be the first one */
|
||
interface = &intf->cur_altsetting->desc;
|
||
- if (interface->bInterfaceNumber > 0) {
|
||
- PDEBUG(D_ERR, "intf != 0");
|
||
+ if (dev->config->desc.bNumInterfaces != 1 &&
|
||
+ interface->bInterfaceNumber != 0)
|
||
return -ENODEV;
|
||
- }
|
||
|
||
/* create the device */
|
||
if (dev_size < sizeof *gspca_dev)
|
||
@@ -2096,6 +2283,10 @@ int gspca_dev_probe(struct usb_interface *intf,
|
||
goto out;
|
||
gspca_set_default_mode(gspca_dev);
|
||
|
||
+ ret = gspca_input_connect(gspca_dev);
|
||
+ if (ret)
|
||
+ goto out;
|
||
+
|
||
mutex_init(&gspca_dev->usb_lock);
|
||
mutex_init(&gspca_dev->read_lock);
|
||
mutex_init(&gspca_dev->queue_lock);
|
||
@@ -2116,8 +2307,15 @@ int gspca_dev_probe(struct usb_interface *intf,
|
||
|
||
usb_set_intfdata(intf, gspca_dev);
|
||
PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev));
|
||
+
|
||
+ gspca_input_create_urb(gspca_dev);
|
||
+
|
||
return 0;
|
||
out:
|
||
+#ifdef CONFIG_INPUT
|
||
+ if (gspca_dev->input_dev)
|
||
+ input_unregister_device(gspca_dev->input_dev);
|
||
+#endif
|
||
kfree(gspca_dev->usb_buf);
|
||
kfree(gspca_dev);
|
||
return ret;
|
||
@@ -2133,6 +2331,7 @@ EXPORT_SYMBOL(gspca_dev_probe);
|
||
void gspca_disconnect(struct usb_interface *intf)
|
||
{
|
||
struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
|
||
+ struct input_dev *input_dev;
|
||
|
||
PDEBUG(D_PROBE, "%s disconnect",
|
||
video_device_node_name(&gspca_dev->vdev));
|
||
@@ -2144,6 +2343,13 @@ void gspca_disconnect(struct usb_interface *intf)
|
||
wake_up_interruptible(&gspca_dev->wq);
|
||
}
|
||
|
||
+ gspca_input_destroy_urb(gspca_dev);
|
||
+ input_dev = gspca_dev->input_dev;
|
||
+ if (input_dev) {
|
||
+ gspca_dev->input_dev = NULL;
|
||
+ input_unregister_device(input_dev);
|
||
+ }
|
||
+
|
||
/* the device is freed at exit of this function */
|
||
gspca_dev->dev = NULL;
|
||
mutex_unlock(&gspca_dev->usb_lock);
|
||
@@ -2169,6 +2375,7 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message)
|
||
if (gspca_dev->sd_desc->stopN)
|
||
gspca_dev->sd_desc->stopN(gspca_dev);
|
||
destroy_urbs(gspca_dev);
|
||
+ gspca_input_destroy_urb(gspca_dev);
|
||
gspca_set_alt0(gspca_dev);
|
||
if (gspca_dev->sd_desc->stop0)
|
||
gspca_dev->sd_desc->stop0(gspca_dev);
|
||
@@ -2182,6 +2389,7 @@ int gspca_resume(struct usb_interface *intf)
|
||
|
||
gspca_dev->frozen = 0;
|
||
gspca_dev->sd_desc->init(gspca_dev);
|
||
+ gspca_input_create_urb(gspca_dev);
|
||
if (gspca_dev->streaming)
|
||
return gspca_init_transfer(gspca_dev);
|
||
return 0;
|
||
@@ -2205,6 +2413,8 @@ int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
|
||
int retval = 0;
|
||
|
||
for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
|
||
+ if (gspca_dev->ctrl_dis & (1 << i))
|
||
+ continue;
|
||
if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
|
||
gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
|
||
if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
|
||
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
|
||
index 59c7941..02c696a 100644
|
||
--- a/drivers/media/video/gspca/gspca.h
|
||
+++ b/drivers/media/video/gspca/gspca.h
|
||
@@ -48,26 +48,27 @@ extern int gspca_debug;
|
||
|
||
/* used to list framerates supported by a camera mode (resolution) */
|
||
struct framerates {
|
||
- int *rates;
|
||
+ const u8 *rates;
|
||
int nrates;
|
||
};
|
||
|
||
/* device information - set at probe time */
|
||
struct cam {
|
||
- int bulk_size; /* buffer size when image transfer by bulk */
|
||
const struct v4l2_pix_format *cam_mode; /* size nmodes */
|
||
- char nmodes;
|
||
const struct framerates *mode_framerates; /* must have size nmode,
|
||
* just like cam_mode */
|
||
- __u8 bulk_nurbs; /* number of URBs in bulk mode
|
||
+ u32 bulk_size; /* buffer size when image transfer by bulk */
|
||
+ u32 input_flags; /* value for ENUM_INPUT status flags */
|
||
+ u8 nmodes; /* size of cam_mode */
|
||
+ u8 no_urb_create; /* don't create transfer URBs */
|
||
+ u8 bulk_nurbs; /* number of URBs in bulk mode
|
||
* - cannot be > MAX_NURBS
|
||
* - when 0 and bulk_size != 0 means
|
||
* 1 URB and submit done by subdriver */
|
||
u8 bulk; /* image transfer by 0:isoc / 1:bulk */
|
||
u8 npkt; /* number of packets in an ISOC message
|
||
* 0 is the default value: 32 packets */
|
||
- u32 input_flags; /* value for ENUM_INPUT status flags */
|
||
- char reverse_alts; /* Alt settings are in high to low order */
|
||
+ u8 reverse_alts; /* Alt settings are in high to low order */
|
||
};
|
||
|
||
struct gspca_dev;
|
||
@@ -90,6 +91,9 @@ typedef int (*cam_qmnu_op) (struct gspca_dev *,
|
||
typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
|
||
u8 *data,
|
||
int len);
|
||
+typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev,
|
||
+ u8 *data,
|
||
+ int len);
|
||
|
||
struct ctrl {
|
||
struct v4l2_queryctrl qctrl;
|
||
@@ -125,6 +129,12 @@ struct sd_desc {
|
||
cam_reg_op get_register;
|
||
#endif
|
||
cam_ident_op get_chip_ident;
|
||
+#ifdef CONFIG_INPUT
|
||
+ cam_int_pkt_op int_pkt_scan;
|
||
+ /* other_input makes the gspca core create gspca_dev->input even when
|
||
+ int_pkt_scan is NULL, for cams with non interrupt driven buttons */
|
||
+ u8 other_input;
|
||
+#endif
|
||
};
|
||
|
||
/* packet types when moving from iso buf to frame buf */
|
||
@@ -147,6 +157,10 @@ struct gspca_dev {
|
||
struct module *module; /* subdriver handling the device */
|
||
struct usb_device *dev;
|
||
struct file *capt_file; /* file doing video capture */
|
||
+#ifdef CONFIG_INPUT
|
||
+ struct input_dev *input_dev;
|
||
+ char phys[64]; /* physical device path */
|
||
+#endif
|
||
|
||
struct cam cam; /* device information */
|
||
const struct sd_desc *sd_desc; /* subdriver description */
|
||
@@ -156,6 +170,9 @@ struct gspca_dev {
|
||
#define USB_BUF_SZ 64
|
||
__u8 *usb_buf; /* buffer for USB exchanges */
|
||
struct urb *urb[MAX_NURBS];
|
||
+#ifdef CONFIG_INPUT
|
||
+ struct urb *int_urb;
|
||
+#endif
|
||
|
||
__u8 *frbuf; /* buffer for nframes */
|
||
struct gspca_frame frame[GSPCA_MAX_FRAMES];
|
||
@@ -187,7 +204,6 @@ struct gspca_dev {
|
||
char users; /* number of opens */
|
||
char present; /* device connected */
|
||
char nbufread; /* number of buffers for read() */
|
||
- char nurbs; /* number of allocated URBs */
|
||
char memory; /* memory type (V4L2_MEMORY_xxx) */
|
||
__u8 iface; /* USB interface number */
|
||
__u8 alt; /* USB alternate setting */
|
||
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
|
||
index 8d071df..de5425a 100644
|
||
--- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c
|
||
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
|
||
@@ -36,6 +36,18 @@ static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
|
||
|
||
static struct v4l2_pix_format mt9m111_modes[] = {
|
||
+#if 0
|
||
+ {
|
||
+ 320,
|
||
+ 240,
|
||
+ V4L2_PIX_FMT_SBGGR8,
|
||
+ V4L2_FIELD_NONE,
|
||
+ .sizeimage = 320 * 240,
|
||
+ .bytesperline = 320,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = 0
|
||
+ },
|
||
+#endif
|
||
{
|
||
640,
|
||
480,
|
||
@@ -48,7 +60,7 @@ static struct v4l2_pix_format mt9m111_modes[] = {
|
||
}
|
||
};
|
||
|
||
-const static struct ctrl mt9m111_ctrls[] = {
|
||
+static const struct ctrl mt9m111_ctrls[] = {
|
||
#define VFLIP_IDX 0
|
||
{
|
||
{
|
||
@@ -171,7 +183,7 @@ int mt9m111_probe(struct sd *sd)
|
||
return -ENODEV;
|
||
}
|
||
|
||
- info("Probing for a mt9m111 sensor");
|
||
+ PDEBUG(D_PROBE, "Probing for a mt9m111 sensor");
|
||
|
||
/* Do the preinit */
|
||
for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
|
||
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.c b/drivers/media/video/gspca/m5602/m5602_ov7660.c
|
||
index 2a28b74..99fef65 100644
|
||
--- a/drivers/media/video/gspca/m5602/m5602_ov7660.c
|
||
+++ b/drivers/media/video/gspca/m5602/m5602_ov7660.c
|
||
@@ -20,6 +20,12 @@
|
||
|
||
static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
|
||
+#if 0
|
||
+static int ov7660_get_blue_gain(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int ov7660_set_blue_gain(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int ov7660_get_red_gain(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int ov7660_set_red_gain(struct gspca_dev *gspca_dev, __s32 val);
|
||
+#endif
|
||
static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
|
||
__s32 *val);
|
||
static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
|
||
@@ -33,7 +39,7 @@ static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
|
||
|
||
-const static struct ctrl ov7660_ctrls[] = {
|
||
+static const struct ctrl ov7660_ctrls[] = {
|
||
#define GAIN_IDX 1
|
||
{
|
||
{
|
||
@@ -50,7 +56,39 @@ const static struct ctrl ov7660_ctrls[] = {
|
||
.get = ov7660_get_gain
|
||
},
|
||
#define BLUE_BALANCE_IDX 2
|
||
+#if 0
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_BLUE_BALANCE,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "blue balance",
|
||
+ .minimum = 0x00,
|
||
+ .maximum = 0x7f,
|
||
+ .step = 0x1,
|
||
+ .default_value = OV7660_DEFAULT_BLUE_GAIN,
|
||
+ .flags = V4L2_CTRL_FLAG_SLIDER
|
||
+ },
|
||
+ .set = ov7660_set_blue_gain,
|
||
+ .get = ov7660_get_blue_gain
|
||
+ },
|
||
+#endif
|
||
#define RED_BALANCE_IDX 3
|
||
+#if 0
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_RED_BALANCE,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "red balance",
|
||
+ .minimum = 0x00,
|
||
+ .maximum = 0x7f,
|
||
+ .step = 0x1,
|
||
+ .default_value = OV7660_DEFAULT_RED_GAIN,
|
||
+ .flags = V4L2_CTRL_FLAG_SLIDER
|
||
+ },
|
||
+ .set = ov7660_set_red_gain,
|
||
+ .get = ov7660_get_red_gain
|
||
+ },
|
||
+#endif
|
||
#define AUTO_WHITE_BALANCE_IDX 4
|
||
{
|
||
{
|
||
@@ -247,6 +285,17 @@ int ov7660_init(struct sd *sd)
|
||
sensor_settings[AUTO_EXPOSURE_IDX]);
|
||
if (err < 0)
|
||
return err;
|
||
+#if 0
|
||
+ err = ov7660_set_blue_gain(&sd->gspca_dev,
|
||
+ sensor_settings[BLUE_BALANCE_IDX]);
|
||
+ if (err < 0)
|
||
+ return err;
|
||
+
|
||
+ err = ov7660_set_red_gain(&sd->gspca_dev,
|
||
+ sensor_settings[RED_BALANCE_IDX]);
|
||
+ if (err < 0)
|
||
+ return err;
|
||
+#endif
|
||
err = ov7660_set_hflip(&sd->gspca_dev,
|
||
sensor_settings[HFLIP_IDX]);
|
||
if (err < 0)
|
||
@@ -301,6 +350,57 @@ static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
|
||
return err;
|
||
}
|
||
|
||
+#if 0
|
||
+static int ov7660_get_blue_gain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ s32 *sensor_settings = sd->sensor_priv;
|
||
+
|
||
+ *val = sensor_settings[BLUE_BALANCE_IDX];
|
||
+ PDEBUG(D_V4L2, "Read blue balance %d", *val);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int ov7660_set_blue_gain(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ int err;
|
||
+ u8 i2c_data;
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ s32 *sensor_settings = sd->sensor_priv;
|
||
+
|
||
+ PDEBUG(D_V4L2, "Setting blue balance to %d", val);
|
||
+
|
||
+ sensor_settings[BLUE_BALANCE_IDX] = val;
|
||
+
|
||
+ err = m5602_write_sensor(sd, OV7660_BLUE_GAIN, &i2c_data, 1);
|
||
+ return err;
|
||
+}
|
||
+
|
||
+static int ov7660_get_red_gain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ s32 *sensor_settings = sd->sensor_priv;
|
||
+
|
||
+ *val = sensor_settings[RED_BALANCE_IDX];
|
||
+ PDEBUG(D_V4L2, "Read red balance %d", *val);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int ov7660_set_red_gain(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ int err;
|
||
+ u8 i2c_data;
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ s32 *sensor_settings = sd->sensor_priv;
|
||
+
|
||
+ PDEBUG(D_V4L2, "Setting red balance to %d", val);
|
||
+
|
||
+ sensor_settings[RED_BALANCE_IDX] = val;
|
||
+
|
||
+ err = m5602_write_sensor(sd, OV7660_RED_GAIN, &i2c_data, 1);
|
||
+ return err;
|
||
+}
|
||
+#endif
|
||
|
||
static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
|
||
__s32 *val)
|
||
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.h b/drivers/media/video/gspca/m5602/m5602_ov7660.h
|
||
index f5588eb..4d9dcf2 100644
|
||
--- a/drivers/media/video/gspca/m5602/m5602_ov7660.h
|
||
+++ b/drivers/media/video/gspca/m5602/m5602_ov7660.h
|
||
@@ -94,7 +94,7 @@ int ov7660_start(struct sd *sd);
|
||
int ov7660_stop(struct sd *sd);
|
||
void ov7660_disconnect(struct sd *sd);
|
||
|
||
-const static struct m5602_sensor ov7660 = {
|
||
+static const struct m5602_sensor ov7660 = {
|
||
.name = "ov7660",
|
||
.i2c_slave_id = 0x42,
|
||
.i2c_regW = 1,
|
||
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
|
||
index 923cdd5..069ba00 100644
|
||
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.c
|
||
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
|
||
@@ -307,7 +307,7 @@ int ov9650_probe(struct sd *sd)
|
||
return -ENODEV;
|
||
}
|
||
|
||
- info("Probing for an ov9650 sensor");
|
||
+ PDEBUG(D_PROBE, "Probing for an ov9650 sensor");
|
||
|
||
/* Run the pre-init before probing the sensor */
|
||
for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
|
||
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
|
||
index 8d74d80..03b8a3a 100644
|
||
--- a/drivers/media/video/gspca/m5602/m5602_po1030.c
|
||
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.c
|
||
@@ -42,6 +42,18 @@ static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
|
||
__s32 *val);
|
||
|
||
static struct v4l2_pix_format po1030_modes[] = {
|
||
+#if 0
|
||
+ {
|
||
+ 320,
|
||
+ 240,
|
||
+ V4L2_PIX_FMT_SBGGR8,
|
||
+ V4L2_FIELD_NONE,
|
||
+ .sizeimage = 320 * 240,
|
||
+ .bytesperline = 320,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = 2
|
||
+ },
|
||
+#endif
|
||
{
|
||
640,
|
||
480,
|
||
@@ -205,7 +217,7 @@ int po1030_probe(struct sd *sd)
|
||
return -ENODEV;
|
||
}
|
||
|
||
- info("Probing for a po1030 sensor");
|
||
+ PDEBUG(D_PROBE, "Probing for a po1030 sensor");
|
||
|
||
/* Run the pre-init to actually probe the unit */
|
||
for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
|
||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
|
||
index 1b536f7..da0a38c 100644
|
||
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
|
||
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
|
||
@@ -248,7 +248,7 @@ int s5k4aa_probe(struct sd *sd)
|
||
return -ENODEV;
|
||
}
|
||
|
||
- info("Probing for a s5k4aa sensor");
|
||
+ PDEBUG(D_PROBE, "Probing for a s5k4aa sensor");
|
||
|
||
/* Preinit the sensor */
|
||
for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
|
||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
|
||
index 6b89f33..fbd9154 100644
|
||
--- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c
|
||
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
|
||
@@ -143,7 +143,7 @@ int s5k83a_probe(struct sd *sd)
|
||
return -ENODEV;
|
||
}
|
||
|
||
- info("Probing for a s5k83a sensor");
|
||
+ PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
|
||
|
||
/* Preinit the sensor */
|
||
for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
|
||
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
|
||
index 9cf8d68..a08cd2b 100644
|
||
--- a/drivers/media/video/gspca/mars.c
|
||
+++ b/drivers/media/video/gspca/mars.c
|
||
@@ -54,7 +54,7 @@ static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -232,8 +232,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */
|
||
/* else */
|
||
data[9] = 0x52; /* reg 8, 24MHz, no scale down */
|
||
+#if 1
|
||
/*jfm: from win trace*/
|
||
data[10] = 0x18;
|
||
+#else
|
||
+ data[10] = 0x5d; /* reg 9, I2C device address
|
||
+ * [for PAS5101 (0x40)] [for MI (0x5d)] */
|
||
+#endif
|
||
|
||
err_code = reg_w(gspca_dev, 11);
|
||
if (err_code < 0)
|
||
@@ -260,6 +265,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
/* auto dark-gain */
|
||
data[0] = 0x5e; /* address */
|
||
data[1] = 0; /* reg 94, Y Gain (auto) */
|
||
+#if 1
|
||
/*jfm: from win trace*/
|
||
/* reg 0x5f/0x60 (LE) = saturation */
|
||
/* h (60): xxxx x100
|
||
@@ -268,12 +274,40 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
data[3] = ((sd->colors >> 2) & 0xf8) | 0x04;
|
||
data[4] = sd->brightness; /* reg 0x61 = brightness */
|
||
data[5] = 0x00;
|
||
+#else
|
||
+ data[2] = 0; /* reg 95, UV Gain (1.75) */
|
||
+ data[3] = 0x78; /* reg 96, Y Gain/UV Gain/disable
|
||
+ * auto dark-gain */
|
||
+ switch (gspca_dev->width) {
|
||
+/* case 1280: */
|
||
+/* data[4] = 154;
|
||
+ * reg 97, %3 shadow point (unit: 256 pixel) */
|
||
+/* data[5] = 51;
|
||
+ * reg 98, %1 highlight point
|
||
+ * (uint: 256 pixel) */
|
||
+/* break; */
|
||
+ default:
|
||
+/* case 640: */
|
||
+ data[4] = 36; /* reg 97, %3 shadow point
|
||
+ * (unit: 256 pixel) */
|
||
+ data[5] = 12; /* reg 98, %1 highlight point
|
||
+ * (uint: 256 pixel) */
|
||
+ break;
|
||
+ case 320:
|
||
+ data[4] = 9; /* reg 97, %3 shadow point
|
||
+ * (unit: 256 pixel) */
|
||
+ data[5] = 3; /* reg 98, %1 highlight point
|
||
+ * (uint: 256 pixel) */
|
||
+ break;
|
||
+ }
|
||
+#endif
|
||
|
||
err_code = reg_w(gspca_dev, 6);
|
||
if (err_code < 0)
|
||
return err_code;
|
||
|
||
data[0] = 0x67;
|
||
+#if 1
|
||
/*jfm: from win trace*/
|
||
data[1] = sd->sharpness * 4 + 3;
|
||
data[2] = 0x14;
|
||
@@ -293,6 +327,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
data[1] = 0x07;
|
||
err_code = reg_w(gspca_dev, 2);
|
||
/*jfm: win trace - many writes here to reg 0x64*/
|
||
+#else
|
||
+ data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */
|
||
+ err_code = reg_w(gspca_dev, 2);
|
||
+#endif
|
||
if (err_code < 0)
|
||
return err_code;
|
||
|
||
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
|
||
index 9154870..33744e7 100644
|
||
--- a/drivers/media/video/gspca/mr97310a.c
|
||
+++ b/drivers/media/video/gspca/mr97310a.c
|
||
@@ -57,6 +57,14 @@
|
||
#define MR97310A_GAIN_MAX 31
|
||
#define MR97310A_GAIN_DEFAULT 25
|
||
|
||
+#define MR97310A_CONTRAST_MIN 0
|
||
+#define MR97310A_CONTRAST_MAX 31
|
||
+#define MR97310A_CONTRAST_DEFAULT 23
|
||
+
|
||
+#define MR97310A_CS_GAIN_MIN 0
|
||
+#define MR97310A_CS_GAIN_MAX 0x7ff
|
||
+#define MR97310A_CS_GAIN_DEFAULT 0x110
|
||
+
|
||
#define MR97310A_MIN_CLOCKDIV_MIN 3
|
||
#define MR97310A_MIN_CLOCKDIV_MAX 8
|
||
#define MR97310A_MIN_CLOCKDIV_DEFAULT 3
|
||
@@ -82,7 +90,8 @@ struct sd {
|
||
|
||
int brightness;
|
||
u16 exposure;
|
||
- u8 gain;
|
||
+ u32 gain;
|
||
+ u8 contrast;
|
||
u8 min_clockdiv;
|
||
};
|
||
|
||
@@ -98,6 +107,8 @@ 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_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int sd_setcontrast(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 int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val);
|
||
@@ -105,11 +116,13 @@ static int sd_getmin_clockdiv(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);
|
||
+static void setcontrast(struct gspca_dev *gspca_dev);
|
||
|
||
/* V4L2 controls supported by the driver */
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
/* Separate brightness control description for Argus QuickClix as it has
|
||
- different limits from the other mr97310a cameras */
|
||
+ * different limits from the other mr97310a cameras, and separate gain
|
||
+ * control for Sakar CyberPix camera. */
|
||
{
|
||
#define NORM_BRIGHTNESS_IDX 0
|
||
{
|
||
@@ -171,7 +184,37 @@ static struct ctrl sd_ctrls[] = {
|
||
.get = sd_getgain,
|
||
},
|
||
{
|
||
-#define MIN_CLOCKDIV_IDX 4
|
||
+#define SAKAR_CS_GAIN_IDX 4
|
||
+ {
|
||
+ .id = V4L2_CID_GAIN,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Gain",
|
||
+ .minimum = MR97310A_CS_GAIN_MIN,
|
||
+ .maximum = MR97310A_CS_GAIN_MAX,
|
||
+ .step = 1,
|
||
+ .default_value = MR97310A_CS_GAIN_DEFAULT,
|
||
+ .flags = 0,
|
||
+ },
|
||
+ .set = sd_setgain,
|
||
+ .get = sd_getgain,
|
||
+ },
|
||
+ {
|
||
+#define CONTRAST_IDX 5
|
||
+ {
|
||
+ .id = V4L2_CID_CONTRAST,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Contrast",
|
||
+ .minimum = MR97310A_CONTRAST_MIN,
|
||
+ .maximum = MR97310A_CONTRAST_MAX,
|
||
+ .step = 1,
|
||
+ .default_value = MR97310A_CONTRAST_DEFAULT,
|
||
+ .flags = 0,
|
||
+ },
|
||
+ .set = sd_setcontrast,
|
||
+ .get = sd_getcontrast,
|
||
+ },
|
||
+ {
|
||
+#define MIN_CLOCKDIV_IDX 6
|
||
{
|
||
.id = V4L2_CID_PRIVATE_BASE,
|
||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||
@@ -327,7 +370,6 @@ static int zero_the_pointer(struct gspca_dev *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);
|
||
@@ -437,6 +479,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct cam *cam;
|
||
+ int gain_default = MR97310A_GAIN_DEFAULT;
|
||
int err_code;
|
||
|
||
cam = &gspca_dev->cam;
|
||
@@ -460,12 +503,14 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
if (err_code < 0)
|
||
return err_code;
|
||
|
||
+ /* Now, the query for sensor type. */
|
||
+ err_code = cam_get_response16(gspca_dev, 0x07, 1);
|
||
+ if (err_code < 0)
|
||
+ return err_code;
|
||
+
|
||
if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
|
||
sd->cam_type = CAM_TYPE_CIF;
|
||
cam->nmodes--;
|
||
- err_code = cam_get_response16(gspca_dev, 0x06, 1);
|
||
- if (err_code < 0)
|
||
- return err_code;
|
||
/*
|
||
* All but one of the known CIF cameras share the same USB ID,
|
||
* but two different init routines are in use, and the control
|
||
@@ -473,12 +518,12 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
* of the two known varieties is connected!
|
||
*
|
||
* A list of known CIF cameras follows. They all report either
|
||
- * 0002 for type 0 or 0003 for type 1.
|
||
+ * 0200 for type 0 or 0300 for type 1.
|
||
* If you have another to report, please do
|
||
*
|
||
* Name sd->sensor_type reported by
|
||
*
|
||
- * Sakar Spy-shot 0 T. Kilgore
|
||
+ * Sakar 56379 Spy-shot 0 T. Kilgore
|
||
* Innovage 0 T. Kilgore
|
||
* Vivitar Mini 0 H. De Goede
|
||
* Vivitar Mini 0 E. Rodriguez
|
||
@@ -487,7 +532,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
* Philips dig. keych. 1 T. Kilgore
|
||
* Trust Spyc@m 100 1 A. Jacobs
|
||
*/
|
||
- switch (gspca_dev->usb_buf[1]) {
|
||
+ switch (gspca_dev->usb_buf[0]) {
|
||
case 2:
|
||
sd->sensor_type = 0;
|
||
break;
|
||
@@ -504,20 +549,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
} else {
|
||
sd->cam_type = CAM_TYPE_VGA;
|
||
|
||
- err_code = cam_get_response16(gspca_dev, 0x07, 1);
|
||
- if (err_code < 0)
|
||
- return err_code;
|
||
-
|
||
/*
|
||
- * Here is a table of the responses to the previous command
|
||
- * from the known MR97310A VGA cameras.
|
||
+ * Here is a table of the responses to the query for sensor
|
||
+ * type, from the known MR97310A VGA cameras. Six different
|
||
+ * cameras of which five share the same USB ID.
|
||
*
|
||
* Name gspca_dev->usb_buf[] sd->sensor_type
|
||
* sd->do_lcd_stop
|
||
* Aiptek Pencam VGA+ 0300 0 1
|
||
- * ION digital 0350 0 1
|
||
+ * ION digital 0300 0 1
|
||
* Argus DC-1620 0450 1 0
|
||
* Argus QuickClix 0420 1 1
|
||
+ * Sakar 77379 Digital 0350 0 1
|
||
+ * Sakar 1638x CyberPix 0120 0 2
|
||
*
|
||
* Based upon these results, we assume default settings
|
||
* and then correct as necessary, as follows.
|
||
@@ -527,10 +571,12 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
sd->sensor_type = 1;
|
||
sd->do_lcd_stop = 0;
|
||
sd->adj_colors = 0;
|
||
- if ((gspca_dev->usb_buf[0] != 0x03) &&
|
||
+ if (gspca_dev->usb_buf[0] == 0x01) {
|
||
+ sd->sensor_type = 2;
|
||
+ } else if ((gspca_dev->usb_buf[0] != 0x03) &&
|
||
(gspca_dev->usb_buf[0] != 0x04)) {
|
||
PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x",
|
||
- gspca_dev->usb_buf[1]);
|
||
+ gspca_dev->usb_buf[0]);
|
||
PDEBUG(D_ERR, "Defaults assumed, may not work");
|
||
PDEBUG(D_ERR, "Please report this");
|
||
}
|
||
@@ -560,7 +606,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
|
||
sd->sensor_type);
|
||
}
|
||
- /* Stop streaming as we've started it to probe the sensor type. */
|
||
+ /* Stop streaming as we've started it only to probe the sensor type. */
|
||
sd_stopN(gspca_dev);
|
||
|
||
if (force_sensor_type != -1) {
|
||
@@ -574,9 +620,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
/* No brightness for sensor_type 0 */
|
||
if (sd->sensor_type == 0)
|
||
gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
|
||
- (1 << ARGUS_QC_BRIGHTNESS_IDX);
|
||
+ (1 << ARGUS_QC_BRIGHTNESS_IDX) |
|
||
+ (1 << CONTRAST_IDX) |
|
||
+ (1 << SAKAR_CS_GAIN_IDX);
|
||
else
|
||
gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |
|
||
+ (1 << CONTRAST_IDX) |
|
||
+ (1 << SAKAR_CS_GAIN_IDX) |
|
||
(1 << MIN_CLOCKDIV_IDX);
|
||
} else {
|
||
/* All controls need to be disabled if VGA sensor_type is 0 */
|
||
@@ -585,17 +635,30 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
(1 << ARGUS_QC_BRIGHTNESS_IDX) |
|
||
(1 << EXPOSURE_IDX) |
|
||
(1 << GAIN_IDX) |
|
||
+ (1 << CONTRAST_IDX) |
|
||
+ (1 << SAKAR_CS_GAIN_IDX) |
|
||
(1 << MIN_CLOCKDIV_IDX);
|
||
- else if (sd->do_lcd_stop)
|
||
+ else if (sd->sensor_type == 2) {
|
||
+ gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
|
||
+ (1 << ARGUS_QC_BRIGHTNESS_IDX) |
|
||
+ (1 << GAIN_IDX) |
|
||
+ (1 << MIN_CLOCKDIV_IDX);
|
||
+ gain_default = MR97310A_CS_GAIN_DEFAULT;
|
||
+ } else if (sd->do_lcd_stop)
|
||
/* Argus QuickClix has different brightness limits */
|
||
- gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX);
|
||
+ gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
|
||
+ (1 << CONTRAST_IDX) |
|
||
+ (1 << SAKAR_CS_GAIN_IDX);
|
||
else
|
||
- gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX);
|
||
+ gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |
|
||
+ (1 << CONTRAST_IDX) |
|
||
+ (1 << SAKAR_CS_GAIN_IDX);
|
||
}
|
||
|
||
sd->brightness = MR97310A_BRIGHTNESS_DEFAULT;
|
||
sd->exposure = MR97310A_EXPOSURE_DEFAULT;
|
||
- sd->gain = MR97310A_GAIN_DEFAULT;
|
||
+ sd->gain = gain_default;
|
||
+ sd->contrast = MR97310A_CONTRAST_DEFAULT;
|
||
sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT;
|
||
|
||
return 0;
|
||
@@ -697,6 +760,12 @@ static int start_cif_cam(struct gspca_dev *gspca_dev)
|
||
{0x13, 0x00, {0x01}, 1},
|
||
{0, 0, {0}, 0}
|
||
};
|
||
+ /* Without this command the cam won't work with USB-UHCI */
|
||
+ gspca_dev->usb_buf[0] = 0x0a;
|
||
+ gspca_dev->usb_buf[1] = 0x00;
|
||
+ err_code = mr_write(gspca_dev, 2);
|
||
+ if (err_code < 0)
|
||
+ return err_code;
|
||
err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
|
||
ARRAY_SIZE(cif_sensor1_init_data));
|
||
}
|
||
@@ -717,6 +786,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
|
||
data[5] = 0x00;
|
||
data[10] = 0x91;
|
||
}
|
||
+ if (sd->sensor_type == 2) {
|
||
+ data[5] = 0x00;
|
||
+ data[10] = 0x18;
|
||
+ }
|
||
|
||
switch (gspca_dev->width) {
|
||
case 160:
|
||
@@ -731,6 +804,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
|
||
data[4] = 0x78; /* reg 3, V size/4 */
|
||
data[6] = 0x04; /* reg 5, H start */
|
||
data[8] = 0x03; /* reg 7, V start */
|
||
+ if (sd->sensor_type == 2) {
|
||
+ data[6] = 2;
|
||
+ data[8] = 1;
|
||
+ }
|
||
if (sd->do_lcd_stop)
|
||
data[8] = 0x04; /* Bayer tile shifted */
|
||
break;
|
||
@@ -753,7 +830,6 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
|
||
return err_code;
|
||
|
||
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},
|
||
@@ -764,7 +840,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
|
||
};
|
||
err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
|
||
ARRAY_SIZE(vga_sensor0_init_data));
|
||
- } else { /* sd->sensor_type = 1 */
|
||
+ } else if (sd->sensor_type == 1) {
|
||
const struct sensor_w_data color_adj[] = {
|
||
{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
|
||
/* adjusted blue, green, red gain correct
|
||
@@ -802,6 +878,48 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
|
||
|
||
err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
|
||
ARRAY_SIZE(vga_sensor1_init_data));
|
||
+ } else { /* sensor type == 2 */
|
||
+ const struct sensor_w_data vga_sensor2_init_data[] = {
|
||
+
|
||
+ {0x01, 0x00, {0x48}, 1},
|
||
+ {0x02, 0x00, {0x22}, 1},
|
||
+ /* Reg 3 msb and 4 is lsb of the exposure setting*/
|
||
+ {0x05, 0x00, {0x10}, 1},
|
||
+ {0x06, 0x00, {0x00}, 1},
|
||
+ {0x07, 0x00, {0x00}, 1},
|
||
+ {0x08, 0x00, {0x00}, 1},
|
||
+ {0x09, 0x00, {0x00}, 1},
|
||
+ /* The following are used in the gain control
|
||
+ * which is BTW completely borked in the OEM driver
|
||
+ * The values for each color go from 0 to 0x7ff
|
||
+ *{0x0a, 0x00, {0x01}, 1}, green1 gain msb
|
||
+ *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb
|
||
+ *{0x0c, 0x00, {0x01}, 1}, red gain msb
|
||
+ *{0x0d, 0x00, {0x10}, 1}, red gain lsb
|
||
+ *{0x0e, 0x00, {0x01}, 1}, blue gain msb
|
||
+ *{0x0f, 0x00, {0x10}, 1}, blue gain lsb
|
||
+ *{0x10, 0x00, {0x01}, 1}, green2 gain msb
|
||
+ *{0x11, 0x00, {0x10}, 1}, green2 gain lsb
|
||
+ */
|
||
+ {0x12, 0x00, {0x00}, 1},
|
||
+ {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */
|
||
+ {0x14, 0x00, {0x00}, 1},
|
||
+ {0x15, 0x00, {0x06}, 1},
|
||
+ {0x16, 0x00, {0x01}, 1},
|
||
+ {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */
|
||
+ {0x18, 0x00, {0x02}, 1},
|
||
+ {0x19, 0x00, {0x82}, 1}, /* don't mess with */
|
||
+ {0x1a, 0x00, {0x00}, 1},
|
||
+ {0x1b, 0x00, {0x20}, 1},
|
||
+ /* {0x1c, 0x00, {0x17}, 1}, contrast control */
|
||
+ {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */
|
||
+ {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */
|
||
+ {0x1f, 0x00, {0x0c}, 1},
|
||
+ {0x20, 0x00, {0x00}, 1},
|
||
+ {0, 0, {0}, 0}
|
||
+ };
|
||
+ err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,
|
||
+ ARRAY_SIZE(vga_sensor2_init_data));
|
||
}
|
||
return err_code;
|
||
}
|
||
@@ -834,6 +952,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
return err_code;
|
||
|
||
setbrightness(gspca_dev);
|
||
+ setcontrast(gspca_dev);
|
||
setexposure(gspca_dev);
|
||
setgain(gspca_dev);
|
||
|
||
@@ -893,7 +1012,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
|
||
static void setexposure(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int exposure;
|
||
+ int exposure = MR97310A_EXPOSURE_DEFAULT;
|
||
u8 buf[2];
|
||
|
||
if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
|
||
@@ -905,6 +1024,11 @@ static void setexposure(struct gspca_dev *gspca_dev)
|
||
exposure = (sd->exposure * 9267) / 10000 + 300;
|
||
sensor_write1(gspca_dev, 3, exposure >> 4);
|
||
sensor_write1(gspca_dev, 4, exposure & 0x0f);
|
||
+ } else if (sd->sensor_type == 2) {
|
||
+ exposure = sd->exposure;
|
||
+ exposure >>= 3;
|
||
+ sensor_write1(gspca_dev, 3, exposure >> 8);
|
||
+ sensor_write1(gspca_dev, 4, exposure & 0xff);
|
||
} else {
|
||
/* We have both a clock divider and an exposure register.
|
||
We first calculate the clock divider, as that determines
|
||
@@ -943,17 +1067,34 @@ static void setexposure(struct gspca_dev *gspca_dev)
|
||
static void setgain(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
+ u8 gainreg;
|
||
|
||
- if (gspca_dev->ctrl_dis & (1 << GAIN_IDX))
|
||
+ if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) &&
|
||
+ (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX)))
|
||
return;
|
||
|
||
- if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
|
||
+ if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)
|
||
sensor_write1(gspca_dev, 0x0e, sd->gain);
|
||
- } else {
|
||
+ else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)
|
||
+ for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {
|
||
+ sensor_write1(gspca_dev, gainreg, sd->gain >> 8);
|
||
+ sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff);
|
||
+ }
|
||
+ else
|
||
sensor_write1(gspca_dev, 0x10, sd->gain);
|
||
- }
|
||
}
|
||
|
||
+static void setcontrast(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX))
|
||
+ return;
|
||
+
|
||
+ sensor_write1(gspca_dev, 0x1c, sd->contrast);
|
||
+}
|
||
+
|
||
+
|
||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
@@ -1008,6 +1149,25 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
return 0;
|
||
}
|
||
|
||
+static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->contrast = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ setcontrast(gspca_dev);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+
|
||
+static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->contrast;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
|
||
index b4f9657..16fabc2 100644
|
||
--- a/drivers/media/video/gspca/ov519.c
|
||
+++ b/drivers/media/video/gspca/ov519.c
|
||
@@ -38,6 +38,7 @@
|
||
*/
|
||
#define MODULE_NAME "ov519"
|
||
|
||
+#include <linux/input.h>
|
||
#include "gspca.h"
|
||
|
||
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
|
||
@@ -70,6 +71,9 @@ struct sd {
|
||
char invert_led;
|
||
#define BRIDGE_INVERT_LED 8
|
||
|
||
+ char snapshot_pressed;
|
||
+ char snapshot_needs_reset;
|
||
+
|
||
/* Determined by sensor type */
|
||
__u8 sif;
|
||
|
||
@@ -99,10 +103,12 @@ struct sd {
|
||
#define SEN_OV66308AF 5
|
||
#define SEN_OV7610 6
|
||
#define SEN_OV7620 7
|
||
-#define SEN_OV7640 8
|
||
-#define SEN_OV7670 9
|
||
-#define SEN_OV76BE 10
|
||
-#define SEN_OV8610 11
|
||
+#define SEN_OV7620AE 8
|
||
+#define SEN_OV7640 9
|
||
+#define SEN_OV7648 10
|
||
+#define SEN_OV7670 11
|
||
+#define SEN_OV76BE 12
|
||
+#define SEN_OV8610 13
|
||
|
||
u8 sensor_addr;
|
||
int sensor_width;
|
||
@@ -139,6 +145,7 @@ static void setautobrightness(struct sd *sd);
|
||
static void setfreq(struct sd *sd);
|
||
|
||
static const struct ctrl sd_ctrls[] = {
|
||
+#define BRIGHTNESS_IDX 0
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -153,6 +160,7 @@ static const struct ctrl sd_ctrls[] = {
|
||
.set = sd_setbrightness,
|
||
.get = sd_getbrightness,
|
||
},
|
||
+#define CONTRAST_IDX 1
|
||
{
|
||
{
|
||
.id = V4L2_CID_CONTRAST,
|
||
@@ -167,6 +175,7 @@ static const struct ctrl sd_ctrls[] = {
|
||
.set = sd_setcontrast,
|
||
.get = sd_getcontrast,
|
||
},
|
||
+#define COLOR_IDX 2
|
||
{
|
||
{
|
||
.id = V4L2_CID_SATURATION,
|
||
@@ -2030,6 +2039,10 @@ static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value)
|
||
|
||
if ((rc & 2) == 0) /* Ack? */
|
||
break;
|
||
+#if 0
|
||
+ /* I2C abort */
|
||
+ reg_w(sd, R511_I2C_CTL, 0x10);
|
||
+#endif
|
||
if (--retries < 0) {
|
||
PDEBUG(D_USBO, "i2c write retries exhausted");
|
||
return -1;
|
||
@@ -2554,7 +2567,7 @@ static int ov7xx0_configure(struct sd *sd)
|
||
/* I don't know what's different about the 76BE yet. */
|
||
if (i2c_r(sd, 0x15) & 1) {
|
||
PDEBUG(D_PROBE, "Sensor is an OV7620AE");
|
||
- sd->sensor = SEN_OV7620;
|
||
+ sd->sensor = SEN_OV7620AE;
|
||
} else {
|
||
PDEBUG(D_PROBE, "Sensor is an OV76BE");
|
||
sd->sensor = SEN_OV76BE;
|
||
@@ -2588,7 +2601,7 @@ static int ov7xx0_configure(struct sd *sd)
|
||
break;
|
||
case 0x48:
|
||
PDEBUG(D_PROBE, "Sensor is an OV7648");
|
||
- sd->sensor = SEN_OV7640; /* FIXME */
|
||
+ sd->sensor = SEN_OV7648;
|
||
break;
|
||
default:
|
||
PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
|
||
@@ -2680,6 +2693,36 @@ static void ov51x_led_control(struct sd *sd, int on)
|
||
}
|
||
}
|
||
|
||
+static void sd_reset_snapshot(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ if (!sd->snapshot_needs_reset)
|
||
+ return;
|
||
+
|
||
+ /* Note it is important that we clear sd->snapshot_needs_reset,
|
||
+ before actually clearing the snapshot state in the bridge
|
||
+ otherwise we might race with the pkt_scan interrupt handler */
|
||
+ sd->snapshot_needs_reset = 0;
|
||
+
|
||
+ switch (sd->bridge) {
|
||
+ case BRIDGE_OV511:
|
||
+ case BRIDGE_OV511PLUS:
|
||
+ reg_w(sd, R51x_SYS_SNAP, 0x02);
|
||
+ reg_w(sd, R51x_SYS_SNAP, 0x00);
|
||
+ break;
|
||
+ case BRIDGE_OV518:
|
||
+ case BRIDGE_OV518PLUS:
|
||
+ reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */
|
||
+ reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */
|
||
+ break;
|
||
+ case BRIDGE_OV519:
|
||
+ reg_w(sd, R51x_SYS_RESET, 0x40);
|
||
+ reg_w(sd, R51x_SYS_RESET, 0x00);
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
static int ov51x_upload_quan_tables(struct sd *sd)
|
||
{
|
||
const unsigned char yQuanTable511[] = {
|
||
@@ -3115,7 +3158,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
(1 << OV7670_FREQ_IDX);
|
||
}
|
||
sd->quality = QUALITY_DEF;
|
||
- if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
|
||
+ if (sd->sensor == SEN_OV7640 ||
|
||
+ sd->sensor == SEN_OV7648)
|
||
+ gspca_dev->ctrl_dis |= (1 << AUTOBRIGHT_IDX) |
|
||
+ (1 << CONTRAST_IDX);
|
||
+ if (sd->sensor == SEN_OV7670)
|
||
gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX;
|
||
/* OV8610 Frequency filter control should work but needs testing */
|
||
if (sd->sensor == SEN_OV8610)
|
||
@@ -3169,10 +3216,12 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||
return -EIO;
|
||
break;
|
||
case SEN_OV7620:
|
||
+ case SEN_OV7620AE:
|
||
if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
|
||
return -EIO;
|
||
break;
|
||
case SEN_OV7640:
|
||
+ case SEN_OV7648:
|
||
if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
|
||
return -EIO;
|
||
break;
|
||
@@ -3246,7 +3295,9 @@ static int ov511_mode_init_regs(struct sd *sd)
|
||
/* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed
|
||
for more sensors we need to do this for them too */
|
||
case SEN_OV7620:
|
||
+ case SEN_OV7620AE:
|
||
case SEN_OV7640:
|
||
+ case SEN_OV7648:
|
||
case SEN_OV76BE:
|
||
if (sd->gspca_dev.width == 320)
|
||
interlaced = 1;
|
||
@@ -3377,7 +3428,7 @@ static int ov518_mode_init_regs(struct sd *sd)
|
||
|
||
if (sd->bridge == BRIDGE_OV518PLUS) {
|
||
switch (sd->sensor) {
|
||
- case SEN_OV7620:
|
||
+ case SEN_OV7620AE:
|
||
if (sd->gspca_dev.width == 320) {
|
||
reg_w(sd, 0x20, 0x00);
|
||
reg_w(sd, 0x21, 0x19);
|
||
@@ -3386,6 +3437,10 @@ static int ov518_mode_init_regs(struct sd *sd)
|
||
reg_w(sd, 0x21, 0x1f);
|
||
}
|
||
break;
|
||
+ case SEN_OV7620:
|
||
+ reg_w(sd, 0x20, 0x00);
|
||
+ reg_w(sd, 0x21, 0x19);
|
||
+ break;
|
||
default:
|
||
reg_w(sd, 0x21, 0x19);
|
||
}
|
||
@@ -3488,7 +3543,8 @@ static int ov519_mode_init_regs(struct sd *sd)
|
||
if (write_regvals(sd, mode_init_519,
|
||
ARRAY_SIZE(mode_init_519)))
|
||
return -EIO;
|
||
- if (sd->sensor == SEN_OV7640) {
|
||
+ if (sd->sensor == SEN_OV7640 ||
|
||
+ sd->sensor == SEN_OV7648) {
|
||
/* Select 8-bit input mode */
|
||
reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
|
||
}
|
||
@@ -3503,6 +3559,9 @@ static int ov519_mode_init_regs(struct sd *sd)
|
||
if (sd->sensor == SEN_OV7670 &&
|
||
sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
|
||
reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
|
||
+ else if (sd->sensor == SEN_OV7648 &&
|
||
+ sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
|
||
+ reg_w(sd, OV519_R12_X_OFFSETL, 0x01);
|
||
else
|
||
reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
|
||
reg_w(sd, OV519_R13_X_OFFSETH, 0x00);
|
||
@@ -3520,6 +3579,7 @@ static int ov519_mode_init_regs(struct sd *sd)
|
||
sd->clockdiv = 0;
|
||
switch (sd->sensor) {
|
||
case SEN_OV7640:
|
||
+ case SEN_OV7648:
|
||
switch (sd->frame_rate) {
|
||
default:
|
||
/* case 30: */
|
||
@@ -3637,6 +3697,14 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
|
||
case SEN_OV8610:
|
||
/* For OV8610 qvga means qsvga */
|
||
i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
|
||
+#if 0
|
||
+ /* FIXME: Does this improve the image quality or frame rate? */
|
||
+ i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
|
||
+ i2c_w(sd, 0x24, 0x10);
|
||
+ i2c_w(sd, 0x25, qvga ? 0x40 : 0x8a);
|
||
+ i2c_w(sd, 0x2f, qvga ? 0x30 : 0xb0);
|
||
+ i2c_w(sd, 0x35, qvga ? 0x1c : 0x9c);
|
||
+#endif
|
||
i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
|
||
i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
|
||
i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */
|
||
@@ -3644,11 +3712,19 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
|
||
break;
|
||
case SEN_OV7610:
|
||
i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
|
||
+#if 0
|
||
+ /* FIXME: Does this improve the image quality or frame rate? */
|
||
+ i2c_w_mask(sd, 0x28, qvga?0x00:0x20, 0x20);
|
||
+ i2c_w(sd, 0x24, 0x10);
|
||
+ i2c_w(sd, 0x25, qvga?0x40:0x8a);
|
||
+ i2c_w(sd, 0x2f, qvga?0x30:0xb0);
|
||
+#endif
|
||
i2c_w(sd, 0x35, qvga?0x1e:0x9e);
|
||
i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
|
||
i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
|
||
break;
|
||
case SEN_OV7620:
|
||
+ case SEN_OV7620AE:
|
||
case SEN_OV76BE:
|
||
i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
|
||
i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
|
||
@@ -3663,13 +3739,16 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
|
||
i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
|
||
break;
|
||
case SEN_OV7640:
|
||
+ case SEN_OV7648:
|
||
i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
|
||
i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
|
||
-/* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */
|
||
-/* i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); */
|
||
-/* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */
|
||
-/* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */
|
||
-/* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */
|
||
+ /* Setting this undocumented bit in qvga mode removes a very
|
||
+ annoying vertical shaking of the image */
|
||
+ i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
|
||
+ /* Unknown */
|
||
+ i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
|
||
+ /* Allow higher automatic gain (to allow higher framerates) */
|
||
+ i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
|
||
i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */
|
||
break;
|
||
case SEN_OV7670:
|
||
@@ -3795,11 +3874,13 @@ static int set_ov_sensor_window(struct sd *sd)
|
||
}
|
||
break;
|
||
case SEN_OV7620:
|
||
+ case SEN_OV7620AE:
|
||
hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
|
||
hwebase = 0x2f;
|
||
vwsbase = vwebase = 0x05;
|
||
break;
|
||
case SEN_OV7640:
|
||
+ case SEN_OV7648:
|
||
hwsbase = 0x1a;
|
||
hwebase = 0x1a;
|
||
vwsbase = vwebase = 0x03;
|
||
@@ -3893,6 +3974,12 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
setautobrightness(sd);
|
||
setfreq(sd);
|
||
|
||
+ /* Force clear snapshot state in case the snapshot button was
|
||
+ pressed while we weren't streaming */
|
||
+ sd->snapshot_needs_reset = 1;
|
||
+ sd_reset_snapshot(gspca_dev);
|
||
+ sd->snapshot_pressed = 0;
|
||
+
|
||
ret = ov51x_restart(sd);
|
||
if (ret < 0)
|
||
goto out;
|
||
@@ -3919,6 +4006,34 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
|
||
w9968cf_stop0(sd);
|
||
}
|
||
|
||
+static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ if (sd->snapshot_pressed != state) {
|
||
+#ifdef CONFIG_INPUT
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+#endif
|
||
+ if (state)
|
||
+ sd->snapshot_needs_reset = 1;
|
||
+
|
||
+ sd->snapshot_pressed = state;
|
||
+ } else {
|
||
+ /* On the ov511 / ov519 we need to reset the button state
|
||
+ multiple times, as resetting does not work as long as the
|
||
+ button stays pressed */
|
||
+ switch (sd->bridge) {
|
||
+ case BRIDGE_OV511:
|
||
+ case BRIDGE_OV511PLUS:
|
||
+ case BRIDGE_OV519:
|
||
+ if (state)
|
||
+ sd->snapshot_needs_reset = 1;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
|
||
u8 *in, /* isoc packet */
|
||
int len) /* iso packet length */
|
||
@@ -3940,6 +4055,7 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
|
||
*/
|
||
if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) &&
|
||
(in[8] & 0x08)) {
|
||
+ ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1);
|
||
if (in[8] & 0x80) {
|
||
/* Frame end */
|
||
if ((in[9] + 1) * 8 != gspca_dev->width ||
|
||
@@ -3977,6 +4093,7 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
|
||
/* A false positive here is likely, until OVT gives me
|
||
* the definitive SOF/EOF format */
|
||
if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
|
||
+ ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1);
|
||
gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
|
||
gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
|
||
sd->packet_nr = 0;
|
||
@@ -4024,6 +4141,9 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
|
||
if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
|
||
switch (data[3]) {
|
||
case 0x50: /* start of frame */
|
||
+ /* Don't check the button state here, as the state
|
||
+ usually (always ?) changes at EOF and checking it
|
||
+ here leads to unnecessary snapshot state resets. */
|
||
#define HDRSZ 16
|
||
data += HDRSZ;
|
||
len -= HDRSZ;
|
||
@@ -4035,6 +4155,7 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
|
||
gspca_dev->last_packet_type = DISCARD_PACKET;
|
||
return;
|
||
case 0x51: /* end of frame */
|
||
+ ov51x_handle_button(gspca_dev, data[11] & 1);
|
||
if (data[9] != 0)
|
||
gspca_dev->last_packet_type = DISCARD_PACKET;
|
||
gspca_frame_add(gspca_dev, LAST_PACKET,
|
||
@@ -4103,9 +4224,11 @@ static void setbrightness(struct gspca_dev *gspca_dev)
|
||
case SEN_OV6630:
|
||
case SEN_OV66308AF:
|
||
case SEN_OV7640:
|
||
+ case SEN_OV7648:
|
||
i2c_w(sd, OV7610_REG_BRT, val);
|
||
break;
|
||
case SEN_OV7620:
|
||
+ case SEN_OV7620AE:
|
||
/* 7620 doesn't like manual changes when in auto mode */
|
||
if (!sd->autobrightness)
|
||
i2c_w(sd, OV7610_REG_BRT, val);
|
||
@@ -4142,7 +4265,8 @@ static void setcontrast(struct gspca_dev *gspca_dev)
|
||
i2c_w(sd, 0x64, ctab[val >> 5]);
|
||
break;
|
||
}
|
||
- case SEN_OV7620: {
|
||
+ case SEN_OV7620:
|
||
+ case SEN_OV7620AE: {
|
||
static const __u8 ctab[] = {
|
||
0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
|
||
0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
|
||
@@ -4152,10 +4276,6 @@ static void setcontrast(struct gspca_dev *gspca_dev)
|
||
i2c_w(sd, 0x64, ctab[val >> 4]);
|
||
break;
|
||
}
|
||
- case SEN_OV7640:
|
||
- /* Use gain control instead. */
|
||
- i2c_w(sd, OV7610_REG_GAIN, val >> 2);
|
||
- break;
|
||
case SEN_OV7670:
|
||
/* check that this isn't just the same as ov7610 */
|
||
i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);
|
||
@@ -4179,6 +4299,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
|
||
i2c_w(sd, OV7610_REG_SAT, val);
|
||
break;
|
||
case SEN_OV7620:
|
||
+ case SEN_OV7620AE:
|
||
/* Use UV gamma control instead. Bits 0 & 7 are reserved. */
|
||
/* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);
|
||
if (rc < 0)
|
||
@@ -4186,6 +4307,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
|
||
i2c_w(sd, OV7610_REG_SAT, val);
|
||
break;
|
||
case SEN_OV7640:
|
||
+ case SEN_OV7648:
|
||
i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
|
||
break;
|
||
case SEN_OV7670:
|
||
@@ -4198,7 +4320,8 @@ static void setcolors(struct gspca_dev *gspca_dev)
|
||
|
||
static void setautobrightness(struct sd *sd)
|
||
{
|
||
- if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670 ||
|
||
+ if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648 ||
|
||
+ sd->sensor == SEN_OV7670 ||
|
||
sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610)
|
||
return;
|
||
|
||
@@ -4475,9 +4598,13 @@ static const struct sd_desc sd_desc = {
|
||
.stopN = sd_stopN,
|
||
.stop0 = sd_stop0,
|
||
.pkt_scan = sd_pkt_scan,
|
||
+ .dq_callback = sd_reset_snapshot,
|
||
.querymenu = sd_querymenu,
|
||
.get_jcomp = sd_get_jcomp,
|
||
.set_jcomp = sd_set_jcomp,
|
||
+#ifdef CONFIG_INPUT
|
||
+ .other_input = 1,
|
||
+#endif
|
||
};
|
||
|
||
/* -- module initialisation -- */
|
||
@@ -4494,7 +4621,8 @@ static const __devinitdata struct usb_device_id device_table[] = {
|
||
.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
|
||
{USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
|
||
{USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
|
||
- {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
|
||
+ {USB_DEVICE(0x054c, 0x0155),
|
||
+ .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
|
||
{USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
|
||
{USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
|
||
{USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
|
||
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c
|
||
index 0a6b8f0..957e05e 100644
|
||
--- a/drivers/media/video/gspca/ov534.c
|
||
+++ b/drivers/media/video/gspca/ov534.c
|
||
@@ -1,5 +1,5 @@
|
||
/*
|
||
- * ov534 gspca driver
|
||
+ * ov534-ov772x gspca driver
|
||
*
|
||
* Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
|
||
* Copyright (C) 2008 Jim Paris <jim@jtan.com>
|
||
@@ -68,12 +68,7 @@ struct sd {
|
||
s8 sharpness;
|
||
u8 hflip;
|
||
u8 vflip;
|
||
- u8 satur;
|
||
- u8 lightfreq;
|
||
|
||
- u8 sensor;
|
||
-#define SENSOR_OV772X 0
|
||
-#define SENSOR_OV965X 1
|
||
};
|
||
|
||
/* V4L2 controls supported by the driver */
|
||
@@ -101,12 +96,8 @@ 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);
|
||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||
-static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val);
|
||
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
|
||
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
|
||
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls_ov772x[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{ /* 0 */
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -115,8 +106,8 @@ static struct ctrl sd_ctrls_ov772x[] = {
|
||
.minimum = 0,
|
||
.maximum = 255,
|
||
.step = 1,
|
||
-#define BRIGHTNESS_77_DEF 20
|
||
- .default_value = BRIGHTNESS_77_DEF,
|
||
+#define BRIGHTNESS_DEF 20
|
||
+ .default_value = BRIGHTNESS_DEF,
|
||
},
|
||
.set = sd_setbrightness,
|
||
.get = sd_getbrightness,
|
||
@@ -129,8 +120,8 @@ static struct ctrl sd_ctrls_ov772x[] = {
|
||
.minimum = 0,
|
||
.maximum = 255,
|
||
.step = 1,
|
||
-#define CONTRAST_77_DEF 37
|
||
- .default_value = CONTRAST_77_DEF,
|
||
+#define CONTRAST_DEF 37
|
||
+ .default_value = CONTRAST_DEF,
|
||
},
|
||
.set = sd_setcontrast,
|
||
.get = sd_getcontrast,
|
||
@@ -157,8 +148,8 @@ static struct ctrl sd_ctrls_ov772x[] = {
|
||
.minimum = 0,
|
||
.maximum = 255,
|
||
.step = 1,
|
||
-#define EXPO_77_DEF 120
|
||
- .default_value = EXPO_77_DEF,
|
||
+#define EXPO_DEF 120
|
||
+ .default_value = EXPO_DEF,
|
||
},
|
||
.set = sd_setexposure,
|
||
.get = sd_getexposure,
|
||
@@ -213,13 +204,13 @@ static struct ctrl sd_ctrls_ov772x[] = {
|
||
.minimum = 0,
|
||
.maximum = 1,
|
||
.step = 1,
|
||
-#define AUTOGAIN_77_DEF 0
|
||
- .default_value = AUTOGAIN_77_DEF,
|
||
+#define AUTOGAIN_DEF 0
|
||
+ .default_value = AUTOGAIN_DEF,
|
||
},
|
||
.set = sd_setautogain,
|
||
.get = sd_getautogain,
|
||
},
|
||
-#define AWB_77_IDX 8
|
||
+#define AWB_IDX 8
|
||
{ /* 8 */
|
||
{
|
||
.id = V4L2_CID_AUTO_WHITE_BALANCE,
|
||
@@ -242,8 +233,8 @@ static struct ctrl sd_ctrls_ov772x[] = {
|
||
.minimum = 0,
|
||
.maximum = 63,
|
||
.step = 1,
|
||
-#define SHARPNESS_77_DEF 0
|
||
- .default_value = SHARPNESS_77_DEF,
|
||
+#define SHARPNESS_DEF 0
|
||
+ .default_value = SHARPNESS_DEF,
|
||
},
|
||
.set = sd_setsharpness,
|
||
.get = sd_getsharpness,
|
||
@@ -277,107 +268,6 @@ static struct ctrl sd_ctrls_ov772x[] = {
|
||
.get = sd_getvflip,
|
||
},
|
||
};
|
||
-static struct ctrl sd_ctrls_ov965x[] = {
|
||
- { /* 0 */
|
||
- {
|
||
- .id = V4L2_CID_BRIGHTNESS,
|
||
- .type = V4L2_CTRL_TYPE_INTEGER,
|
||
- .name = "Brightness",
|
||
- .minimum = 0,
|
||
- .maximum = 15,
|
||
- .step = 1,
|
||
-#define BRIGHTNESS_96_DEF 7
|
||
- .default_value = BRIGHTNESS_96_DEF,
|
||
- },
|
||
- .set = sd_setbrightness,
|
||
- .get = sd_getbrightness,
|
||
- },
|
||
- { /* 1 */
|
||
- {
|
||
- .id = V4L2_CID_CONTRAST,
|
||
- .type = V4L2_CTRL_TYPE_INTEGER,
|
||
- .name = "Contrast",
|
||
- .minimum = 0,
|
||
- .maximum = 15,
|
||
- .step = 1,
|
||
-#define CONTRAST_96_DEF 3
|
||
- .default_value = CONTRAST_96_DEF,
|
||
- },
|
||
- .set = sd_setcontrast,
|
||
- .get = sd_getcontrast,
|
||
- },
|
||
- { /* 2 */
|
||
- {
|
||
- .id = V4L2_CID_AUTOGAIN,
|
||
- .type = V4L2_CTRL_TYPE_BOOLEAN,
|
||
- .name = "Autogain",
|
||
- .minimum = 0,
|
||
- .maximum = 1,
|
||
- .step = 1,
|
||
-#define AUTOGAIN_96_DEF 1
|
||
- .default_value = AUTOGAIN_96_DEF,
|
||
- },
|
||
- .set = sd_setautogain,
|
||
- .get = sd_getautogain,
|
||
- },
|
||
-#define EXPO_96_IDX 3
|
||
- { /* 3 */
|
||
- {
|
||
- .id = V4L2_CID_EXPOSURE,
|
||
- .type = V4L2_CTRL_TYPE_INTEGER,
|
||
- .name = "Exposure",
|
||
- .minimum = 0,
|
||
- .maximum = 3,
|
||
- .step = 1,
|
||
-#define EXPO_96_DEF 0
|
||
- .default_value = EXPO_96_DEF,
|
||
- },
|
||
- .set = sd_setexposure,
|
||
- .get = sd_getexposure,
|
||
- },
|
||
- { /* 4 */
|
||
- {
|
||
- .id = V4L2_CID_SHARPNESS,
|
||
- .type = V4L2_CTRL_TYPE_INTEGER,
|
||
- .name = "Sharpness",
|
||
- .minimum = -1, /* -1 = auto */
|
||
- .maximum = 4,
|
||
- .step = 1,
|
||
-#define SHARPNESS_96_DEF -1
|
||
- .default_value = SHARPNESS_96_DEF,
|
||
- },
|
||
- .set = sd_setsharpness,
|
||
- .get = sd_getsharpness,
|
||
- },
|
||
- { /* 5 */
|
||
- {
|
||
- .id = V4L2_CID_SATURATION,
|
||
- .type = V4L2_CTRL_TYPE_INTEGER,
|
||
- .name = "Saturation",
|
||
- .minimum = 0,
|
||
- .maximum = 4,
|
||
- .step = 1,
|
||
-#define SATUR_DEF 2
|
||
- .default_value = SATUR_DEF,
|
||
- },
|
||
- .set = sd_setsatur,
|
||
- .get = sd_getsatur,
|
||
- },
|
||
- {
|
||
- {
|
||
- .id = V4L2_CID_POWER_LINE_FREQUENCY,
|
||
- .type = V4L2_CTRL_TYPE_MENU,
|
||
- .name = "Light frequency filter",
|
||
- .minimum = 0,
|
||
- .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
|
||
- .step = 1,
|
||
-#define FREQ_DEF 0
|
||
- .default_value = FREQ_DEF,
|
||
- },
|
||
- .set = sd_setfreq,
|
||
- .get = sd_getfreq,
|
||
- },
|
||
-};
|
||
|
||
static const struct v4l2_pix_format ov772x_mode[] = {
|
||
{320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
|
||
@@ -392,35 +282,21 @@ static const struct v4l2_pix_format ov772x_mode[] = {
|
||
.priv = 0},
|
||
};
|
||
|
||
-static const struct v4l2_pix_format ov965x_mode[] = {
|
||
- {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
- .bytesperline = 320,
|
||
- .sizeimage = 320 * 240 * 3 / 8 + 590,
|
||
- .colorspace = V4L2_COLORSPACE_JPEG,
|
||
- .priv = 4},
|
||
- {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
- .bytesperline = 640,
|
||
- .sizeimage = 640 * 480 * 3 / 8 + 590,
|
||
- .colorspace = V4L2_COLORSPACE_JPEG,
|
||
- .priv = 3},
|
||
- {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
- .bytesperline = 800,
|
||
- .sizeimage = 800 * 600 * 3 / 8 + 590,
|
||
- .colorspace = V4L2_COLORSPACE_JPEG,
|
||
- .priv = 2},
|
||
- {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
- .bytesperline = 1024,
|
||
- .sizeimage = 1024 * 768 * 3 / 8 + 590,
|
||
- .colorspace = V4L2_COLORSPACE_JPEG,
|
||
- .priv = 1},
|
||
- {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
- .bytesperline = 1280,
|
||
- .sizeimage = 1280 * 1024 * 3 / 8 + 590,
|
||
- .colorspace = V4L2_COLORSPACE_JPEG,
|
||
- .priv = 0},
|
||
+static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
|
||
+static const u8 vga_rates[] = {60, 50, 40, 30, 15};
|
||
+
|
||
+static const struct framerates ov772x_framerates[] = {
|
||
+ { /* 320x240 */
|
||
+ .rates = qvga_rates,
|
||
+ .nrates = ARRAY_SIZE(qvga_rates),
|
||
+ },
|
||
+ { /* 640x480 */
|
||
+ .rates = vga_rates,
|
||
+ .nrates = ARRAY_SIZE(vga_rates),
|
||
+ },
|
||
};
|
||
|
||
-static const u8 bridge_init_ov772x[][2] = {
|
||
+static const u8 bridge_init[][2] = {
|
||
{ 0xc2, 0x0c },
|
||
{ 0x88, 0xf8 },
|
||
{ 0xc3, 0x69 },
|
||
@@ -478,7 +354,7 @@ static const u8 bridge_init_ov772x[][2] = {
|
||
{ 0xc1, 0x3c },
|
||
{ 0xc2, 0x0c },
|
||
};
|
||
-static const u8 sensor_init_ov772x[][2] = {
|
||
+static const u8 sensor_init[][2] = {
|
||
{ 0x12, 0x80 },
|
||
{ 0x11, 0x01 },
|
||
/*fixme: better have a delay?*/
|
||
@@ -571,7 +447,7 @@ static const u8 sensor_init_ov772x[][2] = {
|
||
{ 0x8e, 0x00 }, /* De-noise threshold */
|
||
{ 0x0c, 0xd0 }
|
||
};
|
||
-static const u8 bridge_start_ov772x_vga[][2] = {
|
||
+static const u8 bridge_start_vga[][2] = {
|
||
{0x1c, 0x00},
|
||
{0x1d, 0x40},
|
||
{0x1d, 0x02},
|
||
@@ -582,7 +458,7 @@ static const u8 bridge_start_ov772x_vga[][2] = {
|
||
{0xc0, 0x50},
|
||
{0xc1, 0x3c},
|
||
};
|
||
-static const u8 sensor_start_ov772x_vga[][2] = {
|
||
+static const u8 sensor_start_vga[][2] = {
|
||
{0x12, 0x00},
|
||
{0x17, 0x26},
|
||
{0x18, 0xa0},
|
||
@@ -592,7 +468,7 @@ static const u8 sensor_start_ov772x_vga[][2] = {
|
||
{0x2c, 0xf0},
|
||
{0x65, 0x20},
|
||
};
|
||
-static const u8 bridge_start_ov772x_qvga[][2] = {
|
||
+static const u8 bridge_start_qvga[][2] = {
|
||
{0x1c, 0x00},
|
||
{0x1d, 0x40},
|
||
{0x1d, 0x02},
|
||
@@ -603,7 +479,7 @@ static const u8 bridge_start_ov772x_qvga[][2] = {
|
||
{0xc0, 0x28},
|
||
{0xc1, 0x1e},
|
||
};
|
||
-static const u8 sensor_start_ov772x_qvga[][2] = {
|
||
+static const u8 sensor_start_qvga[][2] = {
|
||
{0x12, 0x40},
|
||
{0x17, 0x3f},
|
||
{0x18, 0x50},
|
||
@@ -614,571 +490,6 @@ static const u8 sensor_start_ov772x_qvga[][2] = {
|
||
{0x65, 0x2f},
|
||
};
|
||
|
||
-static const u8 bridge_init_ov965x[][2] = {
|
||
- {0x88, 0xf8},
|
||
- {0x89, 0xff},
|
||
- {0x76, 0x03},
|
||
- {0x92, 0x03},
|
||
- {0x95, 0x10},
|
||
- {0xe2, 0x00},
|
||
- {0xe7, 0x3e},
|
||
- {0x8d, 0x1c},
|
||
- {0x8e, 0x00},
|
||
- {0x8f, 0x00},
|
||
- {0x1f, 0x00},
|
||
- {0xc3, 0xf9},
|
||
- {0x89, 0xff},
|
||
- {0x88, 0xf8},
|
||
- {0x76, 0x03},
|
||
- {0x92, 0x01},
|
||
- {0x93, 0x18},
|
||
- {0x1c, 0x0a},
|
||
- {0x1d, 0x48},
|
||
- {0xc0, 0x50},
|
||
- {0xc1, 0x3c},
|
||
- {0x34, 0x05},
|
||
- {0xc2, 0x0c},
|
||
- {0xc3, 0xf9},
|
||
- {0x34, 0x05},
|
||
- {0xe7, 0x2e},
|
||
- {0x31, 0xf9},
|
||
- {0x35, 0x02},
|
||
- {0xd9, 0x10},
|
||
- {0x25, 0x42},
|
||
- {0x94, 0x11},
|
||
-};
|
||
-
|
||
-static const u8 sensor_init_ov965x[][2] = {
|
||
- {0x12, 0x80}, /* com7 - SSCB reset */
|
||
- {0x00, 0x00}, /* gain */
|
||
- {0x01, 0x80}, /* blue */
|
||
- {0x02, 0x80}, /* red */
|
||
- {0x03, 0x1b}, /* vref */
|
||
- {0x04, 0x03}, /* com1 - exposure low bits */
|
||
- {0x0b, 0x57}, /* ver */
|
||
- {0x0e, 0x61}, /* com5 */
|
||
- {0x0f, 0x42}, /* com6 */
|
||
- {0x11, 0x00}, /* clkrc */
|
||
- {0x12, 0x02}, /* com7 - 15fps VGA YUYV */
|
||
- {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
- {0x14, 0x28}, /* com9 */
|
||
- {0x16, 0x24}, /* reg16 */
|
||
- {0x17, 0x1d}, /* hstart*/
|
||
- {0x18, 0xbd}, /* hstop */
|
||
- {0x19, 0x01}, /* vstrt */
|
||
- {0x1a, 0x81}, /* vstop*/
|
||
- {0x1e, 0x04}, /* mvfp */
|
||
- {0x24, 0x3c}, /* aew */
|
||
- {0x25, 0x36}, /* aeb */
|
||
- {0x26, 0x71}, /* vpt */
|
||
- {0x27, 0x08}, /* bbias */
|
||
- {0x28, 0x08}, /* gbbias */
|
||
- {0x29, 0x15}, /* gr com */
|
||
- {0x2a, 0x00}, /* exhch */
|
||
- {0x2b, 0x00}, /* exhcl */
|
||
- {0x2c, 0x08}, /* rbias */
|
||
- {0x32, 0xff}, /* href */
|
||
- {0x33, 0x00}, /* chlf */
|
||
- {0x34, 0x3f}, /* aref1 */
|
||
- {0x35, 0x00}, /* aref2 */
|
||
- {0x36, 0xf8}, /* aref3 */
|
||
- {0x38, 0x72}, /* adc2 */
|
||
- {0x39, 0x57}, /* aref4 */
|
||
- {0x3a, 0x80}, /* tslb - yuyv */
|
||
- {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
|
||
- {0x3d, 0x99}, /* com13 */
|
||
- {0x3f, 0xc1}, /* edge */
|
||
- {0x40, 0xc0}, /* com15 */
|
||
- {0x41, 0x40}, /* com16 */
|
||
- {0x42, 0xc0}, /* com17 */
|
||
- {0x43, 0x0a}, /* rsvd */
|
||
- {0x44, 0xf0},
|
||
- {0x45, 0x46},
|
||
- {0x46, 0x62},
|
||
- {0x47, 0x2a},
|
||
- {0x48, 0x3c},
|
||
- {0x4a, 0xfc},
|
||
- {0x4b, 0xfc},
|
||
- {0x4c, 0x7f},
|
||
- {0x4d, 0x7f},
|
||
- {0x4e, 0x7f},
|
||
- {0x4f, 0x98}, /* matrix */
|
||
- {0x50, 0x98},
|
||
- {0x51, 0x00},
|
||
- {0x52, 0x28},
|
||
- {0x53, 0x70},
|
||
- {0x54, 0x98},
|
||
- {0x58, 0x1a}, /* matrix coef sign */
|
||
- {0x59, 0x85}, /* AWB control */
|
||
- {0x5a, 0xa9},
|
||
- {0x5b, 0x64},
|
||
- {0x5c, 0x84},
|
||
- {0x5d, 0x53},
|
||
- {0x5e, 0x0e},
|
||
- {0x5f, 0xf0}, /* AWB blue limit */
|
||
- {0x60, 0xf0}, /* AWB red limit */
|
||
- {0x61, 0xf0}, /* AWB green limit */
|
||
- {0x62, 0x00}, /* lcc1 */
|
||
- {0x63, 0x00}, /* lcc2 */
|
||
- {0x64, 0x02}, /* lcc3 */
|
||
- {0x65, 0x16}, /* lcc4 */
|
||
- {0x66, 0x01}, /* lcc5 */
|
||
- {0x69, 0x02}, /* hv */
|
||
- {0x6b, 0x5a}, /* dbvl */
|
||
- {0x6c, 0x04},
|
||
- {0x6d, 0x55},
|
||
- {0x6e, 0x00},
|
||
- {0x6f, 0x9d},
|
||
- {0x70, 0x21}, /* dnsth */
|
||
- {0x71, 0x78},
|
||
- {0x72, 0x00}, /* poidx */
|
||
- {0x73, 0x01}, /* pckdv */
|
||
- {0x74, 0x3a}, /* xindx */
|
||
- {0x75, 0x35}, /* yindx */
|
||
- {0x76, 0x01},
|
||
- {0x77, 0x02},
|
||
- {0x7a, 0x12}, /* gamma curve */
|
||
- {0x7b, 0x08},
|
||
- {0x7c, 0x16},
|
||
- {0x7d, 0x30},
|
||
- {0x7e, 0x5e},
|
||
- {0x7f, 0x72},
|
||
- {0x80, 0x82},
|
||
- {0x81, 0x8e},
|
||
- {0x82, 0x9a},
|
||
- {0x83, 0xa4},
|
||
- {0x84, 0xac},
|
||
- {0x85, 0xb8},
|
||
- {0x86, 0xc3},
|
||
- {0x87, 0xd6},
|
||
- {0x88, 0xe6},
|
||
- {0x89, 0xf2},
|
||
- {0x8a, 0x03},
|
||
- {0x8c, 0x89}, /* com19 */
|
||
- {0x14, 0x28}, /* com9 */
|
||
- {0x90, 0x7d},
|
||
- {0x91, 0x7b},
|
||
- {0x9d, 0x03}, /* lcc6 */
|
||
- {0x9e, 0x04}, /* lcc7 */
|
||
- {0x9f, 0x7a},
|
||
- {0xa0, 0x79},
|
||
- {0xa1, 0x40}, /* aechm */
|
||
- {0xa4, 0x50}, /* com21 */
|
||
- {0xa5, 0x68}, /* com26 */
|
||
- {0xa6, 0x4a}, /* AWB green */
|
||
- {0xa8, 0xc1}, /* refa8 */
|
||
- {0xa9, 0xef}, /* refa9 */
|
||
- {0xaa, 0x92},
|
||
- {0xab, 0x04},
|
||
- {0xac, 0x80}, /* black level control */
|
||
- {0xad, 0x80},
|
||
- {0xae, 0x80},
|
||
- {0xaf, 0x80},
|
||
- {0xb2, 0xf2},
|
||
- {0xb3, 0x20},
|
||
- {0xb4, 0x20}, /* ctrlb4 */
|
||
- {0xb5, 0x00},
|
||
- {0xb6, 0xaf},
|
||
- {0xbb, 0xae},
|
||
- {0xbc, 0x7f}, /* ADC channel offsets */
|
||
- {0xdb, 0x7f},
|
||
- {0xbe, 0x7f},
|
||
- {0xbf, 0x7f},
|
||
- {0xc0, 0xe2},
|
||
- {0xc1, 0xc0},
|
||
- {0xc2, 0x01},
|
||
- {0xc3, 0x4e},
|
||
- {0xc6, 0x85},
|
||
- {0xc7, 0x80}, /* com24 */
|
||
- {0xc9, 0xe0},
|
||
- {0xca, 0xe8},
|
||
- {0xcb, 0xf0},
|
||
- {0xcc, 0xd8},
|
||
- {0xcd, 0xf1},
|
||
- {0x4f, 0x98}, /* matrix */
|
||
- {0x50, 0x98},
|
||
- {0x51, 0x00},
|
||
- {0x52, 0x28},
|
||
- {0x53, 0x70},
|
||
- {0x54, 0x98},
|
||
- {0x58, 0x1a},
|
||
- {0xff, 0x41}, /* read 41, write ff 00 */
|
||
- {0x41, 0x40}, /* com16 */
|
||
-
|
||
- {0xc5, 0x03}, /* 60 Hz banding filter */
|
||
- {0x6a, 0x02}, /* 50 Hz banding filter */
|
||
-
|
||
- {0x12, 0x62}, /* com7 - 30fps VGA YUV */
|
||
- {0x36, 0xfa}, /* aref3 */
|
||
- {0x69, 0x0a}, /* hv */
|
||
- {0x8c, 0x89}, /* com22 */
|
||
- {0x14, 0x28}, /* com9 */
|
||
- {0x3e, 0x0c},
|
||
- {0x41, 0x40}, /* com16 */
|
||
- {0x72, 0x00},
|
||
- {0x73, 0x00},
|
||
- {0x74, 0x3a},
|
||
- {0x75, 0x35},
|
||
- {0x76, 0x01},
|
||
- {0xc7, 0x80},
|
||
- {0x03, 0x12}, /* vref */
|
||
- {0x17, 0x16}, /* hstart */
|
||
- {0x18, 0x02}, /* hstop */
|
||
- {0x19, 0x01}, /* vstrt */
|
||
- {0x1a, 0x3d}, /* vstop */
|
||
- {0x32, 0xff}, /* href */
|
||
- {0xc0, 0xaa},
|
||
-};
|
||
-
|
||
-static const u8 bridge_init_ov965x_2[][2] = {
|
||
- {0x94, 0xaa},
|
||
- {0xf1, 0x60},
|
||
- {0xe5, 0x04},
|
||
- {0xc0, 0x50},
|
||
- {0xc1, 0x3c},
|
||
- {0x8c, 0x00},
|
||
- {0x8d, 0x1c},
|
||
- {0x34, 0x05},
|
||
-
|
||
- {0xc2, 0x0c},
|
||
- {0xc3, 0xf9},
|
||
- {0xda, 0x01},
|
||
- {0x50, 0x00},
|
||
- {0x51, 0xa0},
|
||
- {0x52, 0x3c},
|
||
- {0x53, 0x00},
|
||
- {0x54, 0x00},
|
||
- {0x55, 0x00},
|
||
- {0x57, 0x00},
|
||
- {0x5c, 0x00},
|
||
- {0x5a, 0xa0},
|
||
- {0x5b, 0x78},
|
||
- {0x35, 0x02},
|
||
- {0xd9, 0x10},
|
||
- {0x94, 0x11},
|
||
-};
|
||
-
|
||
-static const u8 sensor_init_ov965x_2[][2] = {
|
||
- {0x3b, 0xc4},
|
||
- {0x1e, 0x04}, /* mvfp */
|
||
- {0x13, 0xe0}, /* com8 */
|
||
- {0x00, 0x00}, /* gain */
|
||
- {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
- {0x11, 0x03}, /* clkrc */
|
||
- {0x6b, 0x5a}, /* dblv */
|
||
- {0x6a, 0x05},
|
||
- {0xc5, 0x07},
|
||
- {0xa2, 0x4b},
|
||
- {0xa3, 0x3e},
|
||
- {0x2d, 0x00},
|
||
- {0xff, 0x42}, /* read 42, write ff 00 */
|
||
- {0x42, 0xc0}, /* com17 */
|
||
- {0x2d, 0x00},
|
||
- {0xff, 0x42}, /* read 42, write ff 00 */
|
||
- {0x42, 0xc1}, /* com17 */
|
||
-/* sharpness */
|
||
- {0x3f, 0x01},
|
||
- {0xff, 0x42}, /* read 42, write ff 00 */
|
||
- {0x42, 0xc1}, /* com17 */
|
||
-/* saturation */
|
||
- {0x4f, 0x98}, /* matrix */
|
||
- {0x50, 0x98},
|
||
- {0x51, 0x00},
|
||
- {0x52, 0x28},
|
||
- {0x53, 0x70},
|
||
- {0x54, 0x98},
|
||
- {0x58, 0x1a},
|
||
- {0xff, 0x41}, /* read 41, write ff 00 */
|
||
- {0x41, 0x40}, /* com16 */
|
||
-/* contrast */
|
||
- {0x56, 0x40},
|
||
-/* brightness */
|
||
- {0x55, 0x8f},
|
||
-/* expo */
|
||
- {0x10, 0x25}, /* aech - exposure high bits */
|
||
- {0xff, 0x13}, /* read 13, write ff 00 */
|
||
- {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
-};
|
||
-
|
||
-static const u8 sensor_start_ov965x_1_vga[][2] = { /* same for qvga */
|
||
- {0x12, 0x62}, /* com7 - 30fps VGA YUV */
|
||
- {0x36, 0xfa}, /* aref3 */
|
||
- {0x69, 0x0a}, /* hv */
|
||
- {0x8c, 0x89}, /* com22 */
|
||
- {0x14, 0x28}, /* com9 */
|
||
- {0x3e, 0x0c}, /* com14 */
|
||
- {0x41, 0x40}, /* com16 */
|
||
- {0x72, 0x00},
|
||
- {0x73, 0x00},
|
||
- {0x74, 0x3a},
|
||
- {0x75, 0x35},
|
||
- {0x76, 0x01},
|
||
- {0xc7, 0x80}, /* com24 */
|
||
- {0x03, 0x12}, /* vref */
|
||
- {0x17, 0x16}, /* hstart */
|
||
- {0x18, 0x02}, /* hstop */
|
||
- {0x19, 0x01}, /* vstrt */
|
||
- {0x1a, 0x3d}, /* vstop */
|
||
- {0x32, 0xff}, /* href */
|
||
- {0xc0, 0xaa},
|
||
-};
|
||
-
|
||
-static const u8 sensor_start_ov965x_1_svga[][2] = {
|
||
- {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */
|
||
- {0x36, 0xf8}, /* aref3 */
|
||
- {0x69, 0x02}, /* hv */
|
||
- {0x8c, 0x0d}, /* com22 */
|
||
- {0x3e, 0x0c}, /* com14 */
|
||
- {0x41, 0x40}, /* com16 */
|
||
- {0x72, 0x00},
|
||
- {0x73, 0x01},
|
||
- {0x74, 0x3a},
|
||
- {0x75, 0x35},
|
||
- {0x76, 0x01},
|
||
- {0xc7, 0x80}, /* com24 */
|
||
- {0x03, 0x1b}, /* vref */
|
||
- {0x17, 0x1d}, /* hstart */
|
||
- {0x18, 0xbd}, /* hstop */
|
||
- {0x19, 0x01}, /* vstrt */
|
||
- {0x1a, 0x81}, /* vstop */
|
||
- {0x32, 0xff}, /* href */
|
||
- {0xc0, 0xe2},
|
||
-};
|
||
-
|
||
-static const u8 sensor_start_ov965x_1_xga[][2] = {
|
||
- {0x12, 0x02}, /* com7 */
|
||
- {0x36, 0xf8}, /* aref3 */
|
||
- {0x69, 0x02}, /* hv */
|
||
- {0x8c, 0x89}, /* com22 */
|
||
- {0x14, 0x28}, /* com9 */
|
||
- {0x3e, 0x0c}, /* com14 */
|
||
- {0x41, 0x40}, /* com16 */
|
||
- {0x72, 0x00},
|
||
- {0x73, 0x01},
|
||
- {0x74, 0x3a},
|
||
- {0x75, 0x35},
|
||
- {0x76, 0x01},
|
||
- {0xc7, 0x80}, /* com24 */
|
||
- {0x03, 0x1b}, /* vref */
|
||
- {0x17, 0x1d}, /* hstart */
|
||
- {0x18, 0xbd}, /* hstop */
|
||
- {0x19, 0x01}, /* vstrt */
|
||
- {0x1a, 0x81}, /* vstop */
|
||
- {0x32, 0xff}, /* href */
|
||
- {0xc0, 0xe2},
|
||
-};
|
||
-
|
||
-static const u8 sensor_start_ov965x_1_sxga[][2] = {
|
||
- {0x12, 0x02}, /* com7 */
|
||
- {0x36, 0xf8}, /* aref3 */
|
||
- {0x69, 0x02}, /* hv */
|
||
- {0x8c, 0x89}, /* com22 */
|
||
- {0x14, 0x28}, /* com9 */
|
||
- {0x3e, 0x0c}, /* com14 */
|
||
- {0x41, 0x40}, /* com16 */
|
||
- {0x72, 0x00},
|
||
- {0x73, 0x01},
|
||
- {0x74, 0x3a},
|
||
- {0x75, 0x35},
|
||
- {0x76, 0x01},
|
||
- {0xc7, 0x80}, /* com24 */
|
||
- {0x03, 0x1b}, /* vref */
|
||
- {0x17, 0x1d}, /* hstart */
|
||
- {0x18, 0x02}, /* hstop */
|
||
- {0x19, 0x01}, /* vstrt */
|
||
- {0x1a, 0x81}, /* vstop */
|
||
- {0x32, 0xff}, /* href */
|
||
- {0xc0, 0xe2},
|
||
-};
|
||
-
|
||
-static const u8 bridge_start_ov965x_qvga[][2] = {
|
||
- {0x94, 0xaa},
|
||
- {0xf1, 0x60},
|
||
- {0xe5, 0x04},
|
||
- {0xc0, 0x50},
|
||
- {0xc1, 0x3c},
|
||
- {0x8c, 0x00},
|
||
- {0x8d, 0x1c},
|
||
- {0x34, 0x05},
|
||
-
|
||
- {0xc2, 0x4c},
|
||
- {0xc3, 0xf9},
|
||
- {0xda, 0x00},
|
||
- {0x50, 0x00},
|
||
- {0x51, 0xa0},
|
||
- {0x52, 0x78},
|
||
- {0x53, 0x00},
|
||
- {0x54, 0x00},
|
||
- {0x55, 0x00},
|
||
- {0x57, 0x00},
|
||
- {0x5c, 0x00},
|
||
- {0x5a, 0x50},
|
||
- {0x5b, 0x3c},
|
||
- {0x35, 0x02},
|
||
- {0xd9, 0x10},
|
||
- {0x94, 0x11},
|
||
-};
|
||
-
|
||
-static const u8 bridge_start_ov965x_vga[][2] = {
|
||
- {0x94, 0xaa},
|
||
- {0xf1, 0x60},
|
||
- {0xe5, 0x04},
|
||
- {0xc0, 0x50},
|
||
- {0xc1, 0x3c},
|
||
- {0x8c, 0x00},
|
||
- {0x8d, 0x1c},
|
||
- {0x34, 0x05},
|
||
- {0xc2, 0x0c},
|
||
- {0xc3, 0xf9},
|
||
- {0xda, 0x01},
|
||
- {0x50, 0x00},
|
||
- {0x51, 0xa0},
|
||
- {0x52, 0x3c},
|
||
- {0x53, 0x00},
|
||
- {0x54, 0x00},
|
||
- {0x55, 0x00},
|
||
- {0x57, 0x00},
|
||
- {0x5c, 0x00},
|
||
- {0x5a, 0xa0},
|
||
- {0x5b, 0x78},
|
||
- {0x35, 0x02},
|
||
- {0xd9, 0x10},
|
||
- {0x94, 0x11},
|
||
-};
|
||
-
|
||
-static const u8 bridge_start_ov965x_svga[][2] = {
|
||
- {0x94, 0xaa},
|
||
- {0xf1, 0x60},
|
||
- {0xe5, 0x04},
|
||
- {0xc0, 0xa0},
|
||
- {0xc1, 0x80},
|
||
- {0x8c, 0x00},
|
||
- {0x8d, 0x1c},
|
||
- {0x34, 0x05},
|
||
- {0xc2, 0x4c},
|
||
- {0xc3, 0xf9},
|
||
- {0x50, 0x00},
|
||
- {0x51, 0x40},
|
||
- {0x52, 0x00},
|
||
- {0x53, 0x00},
|
||
- {0x54, 0x00},
|
||
- {0x55, 0x88},
|
||
- {0x57, 0x00},
|
||
- {0x5c, 0x00},
|
||
- {0x5a, 0xc8},
|
||
- {0x5b, 0x96},
|
||
- {0x35, 0x02},
|
||
- {0xd9, 0x10},
|
||
- {0xda, 0x00},
|
||
- {0x94, 0x11},
|
||
-};
|
||
-
|
||
-static const u8 bridge_start_ov965x_xga[][2] = {
|
||
- {0x94, 0xaa},
|
||
- {0xf1, 0x60},
|
||
- {0xe5, 0x04},
|
||
- {0xc0, 0xa0},
|
||
- {0xc1, 0x80},
|
||
- {0x8c, 0x00},
|
||
- {0x8d, 0x1c},
|
||
- {0x34, 0x05},
|
||
- {0xc2, 0x4c},
|
||
- {0xc3, 0xf9},
|
||
- {0x50, 0x00},
|
||
- {0x51, 0x40},
|
||
- {0x52, 0x00},
|
||
- {0x53, 0x00},
|
||
- {0x54, 0x00},
|
||
- {0x55, 0x88},
|
||
- {0x57, 0x00},
|
||
- {0x5c, 0x01},
|
||
- {0x5a, 0x00},
|
||
- {0x5b, 0xc0},
|
||
- {0x35, 0x02},
|
||
- {0xd9, 0x10},
|
||
- {0xda, 0x01},
|
||
- {0x94, 0x11},
|
||
-};
|
||
-
|
||
-static const u8 bridge_start_ov965x_sxga[][2] = {
|
||
- {0x94, 0xaa},
|
||
- {0xf1, 0x60},
|
||
- {0xe5, 0x04},
|
||
- {0xc0, 0xa0},
|
||
- {0xc1, 0x80},
|
||
- {0x8c, 0x00},
|
||
- {0x8d, 0x1c},
|
||
- {0x34, 0x05},
|
||
- {0xc2, 0x0c},
|
||
- {0xc3, 0xf9},
|
||
- {0xda, 0x00},
|
||
- {0x35, 0x02},
|
||
- {0xd9, 0x10},
|
||
- {0x94, 0x11},
|
||
-};
|
||
-
|
||
-static const u8 sensor_start_ov965x_2_qvga[][2] = {
|
||
- {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */
|
||
- {0x1e, 0x04}, /* mvfp */
|
||
- {0x13, 0xe0}, /* com8 */
|
||
- {0x00, 0x00},
|
||
- {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
- {0x11, 0x01}, /* clkrc */
|
||
- {0x6b, 0x5a}, /* dblv */
|
||
- {0x6a, 0x02}, /* 50 Hz banding filter */
|
||
- {0xc5, 0x03}, /* 60 Hz banding filter */
|
||
- {0xa2, 0x96}, /* bd50 */
|
||
- {0xa3, 0x7d}, /* bd60 */
|
||
-
|
||
- {0xff, 0x13}, /* read 13, write ff 00 */
|
||
- {0x13, 0xe7},
|
||
- {0x3a, 0x80}, /* tslb - yuyv */
|
||
-};
|
||
-
|
||
-static const u8 sensor_start_ov965x_2_vga[][2] = {
|
||
- {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
|
||
- {0x1e, 0x04}, /* mvfp */
|
||
- {0x13, 0xe0}, /* com8 */
|
||
- {0x00, 0x00},
|
||
- {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
- {0x11, 0x03}, /* clkrc */
|
||
- {0x6b, 0x5a}, /* dblv */
|
||
- {0x6a, 0x05}, /* 50 Hz banding filter */
|
||
- {0xc5, 0x07}, /* 60 Hz banding filter */
|
||
- {0xa2, 0x4b}, /* bd50 */
|
||
- {0xa3, 0x3e}, /* bd60 */
|
||
-
|
||
- {0x2d, 0x00}, /* advfl */
|
||
-};
|
||
-
|
||
-static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */
|
||
- {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
|
||
- {0x1e, 0x04}, /* mvfp */
|
||
- {0x13, 0xe0}, /* com8 */
|
||
- {0x00, 0x00},
|
||
- {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
- {0x11, 0x01}, /* clkrc */
|
||
- {0x6b, 0x5a}, /* dblv */
|
||
- {0x6a, 0x0c}, /* 50 Hz banding filter */
|
||
- {0xc5, 0x0f}, /* 60 Hz banding filter */
|
||
- {0xa2, 0x4e}, /* bd50 */
|
||
- {0xa3, 0x41}, /* bd60 */
|
||
-};
|
||
-
|
||
-static const u8 sensor_start_ov965x_2_sxga[][2] = {
|
||
- {0x13, 0xe0}, /* com8 */
|
||
- {0x00, 0x00},
|
||
- {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
- {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
|
||
- {0x1e, 0x04}, /* mvfp */
|
||
- {0x11, 0x01}, /* clkrc */
|
||
- {0x6b, 0x5a}, /* dblv */
|
||
- {0x6a, 0x0c}, /* 50 Hz banding filter */
|
||
- {0xc5, 0x0f}, /* 60 Hz banding filter */
|
||
- {0xa2, 0x4e}, /* bd50 */
|
||
- {0xa3, 0x41}, /* bd60 */
|
||
-};
|
||
-
|
||
static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
|
||
{
|
||
struct usb_device *udev = gspca_dev->dev;
|
||
@@ -1360,14 +671,14 @@ static void set_frame_rate(struct gspca_dev *gspca_dev)
|
||
PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
|
||
}
|
||
|
||
-static void setbrightness_77(struct gspca_dev *gspca_dev)
|
||
+static void setbrightness(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
|
||
sccb_reg_write(gspca_dev, 0x9B, sd->brightness);
|
||
}
|
||
|
||
-static void setcontrast_77(struct gspca_dev *gspca_dev)
|
||
+static void setcontrast(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
|
||
@@ -1401,7 +712,7 @@ static void setgain(struct gspca_dev *gspca_dev)
|
||
sccb_reg_write(gspca_dev, 0x00, val);
|
||
}
|
||
|
||
-static void setexposure_77(struct gspca_dev *gspca_dev)
|
||
+static void setexposure(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
u8 val;
|
||
@@ -1432,7 +743,7 @@ static void sethue(struct gspca_dev *gspca_dev)
|
||
sccb_reg_write(gspca_dev, 0x01, sd->hue);
|
||
}
|
||
|
||
-static void setautogain_77(struct gspca_dev *gspca_dev)
|
||
+static void setautogain(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
|
||
@@ -1457,7 +768,7 @@ static void setawb(struct gspca_dev *gspca_dev)
|
||
sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */
|
||
}
|
||
|
||
-static void setsharpness_77(struct gspca_dev *gspca_dev)
|
||
+static void setsharpness(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
u8 val;
|
||
@@ -1491,132 +802,6 @@ static void setvflip(struct gspca_dev *gspca_dev)
|
||
sccb_reg_read(gspca_dev, 0x0c) & 0x7f);
|
||
}
|
||
|
||
-/* ov965x specific controls */
|
||
-static void setbrightness_96(struct gspca_dev *gspca_dev)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
- u8 val;
|
||
-
|
||
- val = sd->brightness;
|
||
- if (val < 8)
|
||
- val = 15 - val; /* f .. 8 */
|
||
- else
|
||
- val = val - 8; /* 0 .. 7 */
|
||
- sccb_reg_write(gspca_dev, 0x55, /* brtn - brightness adjustment */
|
||
- 0x0f | (val << 4));
|
||
-}
|
||
-
|
||
-static void setcontrast_96(struct gspca_dev *gspca_dev)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
-
|
||
- sccb_reg_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */
|
||
- sd->contrast << 4);
|
||
-}
|
||
-
|
||
-static void setexposure_96(struct gspca_dev *gspca_dev)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
- u8 val;
|
||
- static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
|
||
-
|
||
- sccb_reg_write(gspca_dev, 0x10, /* aec[9:2] */
|
||
- expo[sd->exposure]);
|
||
- val = sccb_reg_read(gspca_dev, 0x13); /* com8 */
|
||
- sccb_reg_write(gspca_dev, 0xff, 0x00);
|
||
- sccb_reg_write(gspca_dev, 0x13, val);
|
||
- val = sccb_reg_read(gspca_dev, 0xa1); /* aech */
|
||
- sccb_reg_write(gspca_dev, 0xff, 0x00);
|
||
- sccb_reg_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */
|
||
-}
|
||
-
|
||
-static void setsharpness_96(struct gspca_dev *gspca_dev)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
- s8 val;
|
||
-
|
||
- val = sd->sharpness;
|
||
- if (val < 0) { /* auto */
|
||
- val = sccb_reg_read(gspca_dev, 0x42); /* com17 */
|
||
- sccb_reg_write(gspca_dev, 0xff, 0x00);
|
||
- sccb_reg_write(gspca_dev, 0x42, val | 0x40);
|
||
- /* Edge enhancement strength auto adjust */
|
||
- return;
|
||
- }
|
||
- if (val != 0)
|
||
- val = 1 << (val - 1);
|
||
- sccb_reg_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */
|
||
- val);
|
||
- val = sccb_reg_read(gspca_dev, 0x42); /* com17 */
|
||
- sccb_reg_write(gspca_dev, 0xff, 0x00);
|
||
- sccb_reg_write(gspca_dev, 0x42, val & 0xbf);
|
||
-}
|
||
-
|
||
-static void setautogain_96(struct gspca_dev *gspca_dev)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
- u8 val;
|
||
-
|
||
-/*fixme: should adjust agc/awb/aec by different controls */
|
||
- val = sd->autogain;
|
||
- val = sccb_reg_read(gspca_dev, 0x13); /* com8 */
|
||
- sccb_reg_write(gspca_dev, 0xff, 0x00);
|
||
- if (sd->autogain)
|
||
- val |= 0x05; /* agc & aec */
|
||
- else
|
||
- val &= 0xfa;
|
||
- sccb_reg_write(gspca_dev, 0x13, val);
|
||
-}
|
||
-
|
||
-static void setsatur(struct gspca_dev *gspca_dev)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
- u8 val1, val2, val3;
|
||
- static const u8 matrix[5][2] = {
|
||
- {0x14, 0x38},
|
||
- {0x1e, 0x54},
|
||
- {0x28, 0x70},
|
||
- {0x32, 0x8c},
|
||
- {0x48, 0x90}
|
||
- };
|
||
-
|
||
- val1 = matrix[sd->satur][0];
|
||
- val2 = matrix[sd->satur][1];
|
||
- val3 = val1 + val2;
|
||
- sccb_reg_write(gspca_dev, 0x4f, val3); /* matrix coeff */
|
||
- sccb_reg_write(gspca_dev, 0x50, val3);
|
||
- sccb_reg_write(gspca_dev, 0x51, 0x00);
|
||
- sccb_reg_write(gspca_dev, 0x52, val1);
|
||
- sccb_reg_write(gspca_dev, 0x53, val2);
|
||
- sccb_reg_write(gspca_dev, 0x54, val3);
|
||
- sccb_reg_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */
|
||
- val1 = sccb_reg_read(gspca_dev, 0x41); /* com16 */
|
||
- sccb_reg_write(gspca_dev, 0xff, 0x00);
|
||
- sccb_reg_write(gspca_dev, 0x41, val1);
|
||
-}
|
||
-
|
||
-static void setfreq(struct gspca_dev *gspca_dev)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
- u8 val;
|
||
-
|
||
- val = sccb_reg_read(gspca_dev, 0x13); /* com8 */
|
||
- sccb_reg_write(gspca_dev, 0xff, 0x00);
|
||
- if (sd->lightfreq == 0) {
|
||
- sccb_reg_write(gspca_dev, 0x13, val & 0xdf);
|
||
- return;
|
||
- }
|
||
- sccb_reg_write(gspca_dev, 0x13, val | 0x20);
|
||
-
|
||
- val = sccb_reg_read(gspca_dev, 0x42); /* com17 */
|
||
- sccb_reg_write(gspca_dev, 0xff, 0x00);
|
||
- if (sd->lightfreq == 1)
|
||
- val |= 0x01;
|
||
- else
|
||
- val &= 0xfe;
|
||
- sccb_reg_write(gspca_dev, 0x42, val);
|
||
-}
|
||
-
|
||
/* this function is called at probe time */
|
||
static int sd_config(struct gspca_dev *gspca_dev,
|
||
const struct usb_device_id *id)
|
||
@@ -1624,77 +809,50 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct cam *cam;
|
||
|
||
- sd->sensor = id->driver_info;
|
||
-
|
||
cam = &gspca_dev->cam;
|
||
|
||
- if (sd->sensor == SENSOR_OV772X) {
|
||
- cam->cam_mode = ov772x_mode;
|
||
- cam->nmodes = ARRAY_SIZE(ov772x_mode);
|
||
+ cam->cam_mode = ov772x_mode;
|
||
+ cam->nmodes = ARRAY_SIZE(ov772x_mode);
|
||
+ cam->mode_framerates = ov772x_framerates;
|
||
|
||
- cam->bulk = 1;
|
||
- cam->bulk_size = 16384;
|
||
- cam->bulk_nurbs = 2;
|
||
- } else { /* ov965x */
|
||
- cam->cam_mode = ov965x_mode;
|
||
- cam->nmodes = ARRAY_SIZE(ov965x_mode);
|
||
- }
|
||
+ cam->bulk = 1;
|
||
+ cam->bulk_size = 16384;
|
||
+ cam->bulk_nurbs = 2;
|
||
|
||
sd->frame_rate = 30;
|
||
|
||
- if (sd->sensor == SENSOR_OV772X) {
|
||
- sd->brightness = BRIGHTNESS_77_DEF;
|
||
- sd->contrast = CONTRAST_77_DEF;
|
||
- sd->gain = GAIN_DEF;
|
||
- sd->exposure = EXPO_77_DEF;
|
||
- sd->redblc = RED_BALANCE_DEF;
|
||
- sd->blueblc = BLUE_BALANCE_DEF;
|
||
- sd->hue = HUE_DEF;
|
||
-#if AUTOGAIN_77_DEF != 0
|
||
- sd->autogain = AUTOGAIN_77_DEF;
|
||
+ sd->brightness = BRIGHTNESS_DEF;
|
||
+ sd->contrast = CONTRAST_DEF;
|
||
+ sd->gain = GAIN_DEF;
|
||
+ sd->exposure = EXPO_DEF;
|
||
+ sd->redblc = RED_BALANCE_DEF;
|
||
+ sd->blueblc = BLUE_BALANCE_DEF;
|
||
+ sd->hue = HUE_DEF;
|
||
+#if AUTOGAIN_DEF != 0
|
||
+ sd->autogain = AUTOGAIN_DEF;
|
||
#else
|
||
- gspca_dev->ctrl_inac |= (1 << AWB_77_IDX);
|
||
+ gspca_dev->ctrl_inac |= (1 << AWB_IDX);
|
||
#endif
|
||
#if AWB_DEF != 0
|
||
- sd->awb = AWB_DEF
|
||
+ sd->awb = AWB_DEF
|
||
#endif
|
||
-#if SHARPNESS_77_DEF != 0
|
||
- sd->sharpness = SHARPNESS_77_DEF;
|
||
+#if SHARPNESS_DEF != 0
|
||
+ sd->sharpness = SHARPNESS_DEF;
|
||
#endif
|
||
#if HFLIP_DEF != 0
|
||
- sd->hflip = HFLIP_DEF;
|
||
+ sd->hflip = HFLIP_DEF;
|
||
#endif
|
||
#if VFLIP_DEF != 0
|
||
- sd->vflip = VFLIP_DEF;
|
||
-#endif
|
||
- } else {
|
||
- sd->brightness = BRIGHTNESS_96_DEF;
|
||
- sd->contrast = CONTRAST_96_DEF;
|
||
-#if AUTOGAIN_96_DEF != 0
|
||
- sd->autogain = AUTOGAIN_96_DEF;
|
||
- gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX);
|
||
+ sd->vflip = VFLIP_DEF;
|
||
#endif
|
||
-#if EXPO_96_DEF != 0
|
||
- sd->exposure = EXPO_96_DEF;
|
||
-#endif
|
||
-#if SHARPNESS_96_DEF != 0
|
||
- sd->sharpness = SHARPNESS_96_DEF;
|
||
-#endif
|
||
- sd->satur = SATUR_DEF;
|
||
- sd->lightfreq = FREQ_DEF;
|
||
- }
|
||
+
|
||
return 0;
|
||
}
|
||
|
||
/* this function is called at probe and resume time */
|
||
static int sd_init(struct gspca_dev *gspca_dev)
|
||
{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
u16 sensor_id;
|
||
- static const u8 sensor_addr[2] = {
|
||
- 0x42, /* 0 SENSOR_OV772X */
|
||
- 0x60, /* 1 SENSOR_OV965X */
|
||
- };
|
||
|
||
/* reset bridge */
|
||
ov534_reg_write(gspca_dev, 0xe7, 0x3a);
|
||
@@ -1702,8 +860,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||
msleep(100);
|
||
|
||
/* initialize the sensor address */
|
||
- ov534_reg_write(gspca_dev, OV534_REG_ADDRESS,
|
||
- sensor_addr[sd->sensor]);
|
||
+ ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42);
|
||
|
||
/* reset sensor */
|
||
sccb_reg_write(gspca_dev, 0x12, 0x80);
|
||
@@ -1717,64 +874,46 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||
PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
|
||
|
||
/* initialize */
|
||
- switch (sd->sensor) {
|
||
- case SENSOR_OV772X:
|
||
- reg_w_array(gspca_dev, bridge_init_ov772x,
|
||
- ARRAY_SIZE(bridge_init_ov772x));
|
||
- ov534_set_led(gspca_dev, 1);
|
||
- sccb_w_array(gspca_dev, sensor_init_ov772x,
|
||
- ARRAY_SIZE(sensor_init_ov772x));
|
||
- ov534_reg_write(gspca_dev, 0xe0, 0x09);
|
||
- ov534_set_led(gspca_dev, 0);
|
||
- set_frame_rate(gspca_dev);
|
||
- break;
|
||
- default:
|
||
-/* case SENSOR_OV965X: */
|
||
- reg_w_array(gspca_dev, bridge_init_ov965x,
|
||
- ARRAY_SIZE(bridge_init_ov965x));
|
||
- sccb_w_array(gspca_dev, sensor_init_ov965x,
|
||
- ARRAY_SIZE(sensor_init_ov965x));
|
||
- reg_w_array(gspca_dev, bridge_init_ov965x_2,
|
||
- ARRAY_SIZE(bridge_init_ov965x_2));
|
||
- sccb_w_array(gspca_dev, sensor_init_ov965x_2,
|
||
- ARRAY_SIZE(sensor_init_ov965x_2));
|
||
- ov534_reg_write(gspca_dev, 0xe0, 0x00);
|
||
- ov534_reg_write(gspca_dev, 0xe0, 0x01);
|
||
- ov534_set_led(gspca_dev, 0);
|
||
- ov534_reg_write(gspca_dev, 0xe0, 0x00);
|
||
- }
|
||
+ reg_w_array(gspca_dev, bridge_init,
|
||
+ ARRAY_SIZE(bridge_init));
|
||
+ ov534_set_led(gspca_dev, 1);
|
||
+ sccb_w_array(gspca_dev, sensor_init,
|
||
+ ARRAY_SIZE(sensor_init));
|
||
+ ov534_reg_write(gspca_dev, 0xe0, 0x09);
|
||
+ ov534_set_led(gspca_dev, 0);
|
||
+ set_frame_rate(gspca_dev);
|
||
|
||
return 0;
|
||
}
|
||
|
||
-static int sd_start_ov772x(struct gspca_dev *gspca_dev)
|
||
+static int sd_start(struct gspca_dev *gspca_dev)
|
||
{
|
||
int mode;
|
||
|
||
mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
|
||
if (mode != 0) { /* 320x240 */
|
||
- reg_w_array(gspca_dev, bridge_start_ov772x_qvga,
|
||
- ARRAY_SIZE(bridge_start_ov772x_qvga));
|
||
- sccb_w_array(gspca_dev, sensor_start_ov772x_qvga,
|
||
- ARRAY_SIZE(sensor_start_ov772x_qvga));
|
||
+ reg_w_array(gspca_dev, bridge_start_qvga,
|
||
+ ARRAY_SIZE(bridge_start_qvga));
|
||
+ sccb_w_array(gspca_dev, sensor_start_qvga,
|
||
+ ARRAY_SIZE(sensor_start_qvga));
|
||
} else { /* 640x480 */
|
||
- reg_w_array(gspca_dev, bridge_start_ov772x_vga,
|
||
- ARRAY_SIZE(bridge_start_ov772x_vga));
|
||
- sccb_w_array(gspca_dev, sensor_start_ov772x_vga,
|
||
- ARRAY_SIZE(sensor_start_ov772x_vga));
|
||
+ reg_w_array(gspca_dev, bridge_start_vga,
|
||
+ ARRAY_SIZE(bridge_start_vga));
|
||
+ sccb_w_array(gspca_dev, sensor_start_vga,
|
||
+ ARRAY_SIZE(sensor_start_vga));
|
||
}
|
||
set_frame_rate(gspca_dev);
|
||
|
||
- setautogain_77(gspca_dev);
|
||
+ setautogain(gspca_dev);
|
||
setawb(gspca_dev);
|
||
setgain(gspca_dev);
|
||
setredblc(gspca_dev);
|
||
setblueblc(gspca_dev);
|
||
sethue(gspca_dev);
|
||
- setexposure_77(gspca_dev);
|
||
- setbrightness_77(gspca_dev);
|
||
- setcontrast_77(gspca_dev);
|
||
- setsharpness_77(gspca_dev);
|
||
+ setexposure(gspca_dev);
|
||
+ setbrightness(gspca_dev);
|
||
+ setcontrast(gspca_dev);
|
||
+ setsharpness(gspca_dev);
|
||
setvflip(gspca_dev);
|
||
sethflip(gspca_dev);
|
||
|
||
@@ -1783,81 +922,12 @@ static int sd_start_ov772x(struct gspca_dev *gspca_dev)
|
||
return 0;
|
||
}
|
||
|
||
-static int sd_start_ov965x(struct gspca_dev *gspca_dev)
|
||
-{
|
||
- int mode;
|
||
-
|
||
- mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
|
||
- switch (mode) {
|
||
- default:
|
||
-/* case 4: * 320x240 */
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_1_vga));
|
||
- reg_w_array(gspca_dev, bridge_start_ov965x_qvga,
|
||
- ARRAY_SIZE(bridge_start_ov965x_qvga));
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_2_qvga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_2_qvga));
|
||
- break;
|
||
- case 3: /* 640x480 */
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_1_vga));
|
||
- reg_w_array(gspca_dev, bridge_start_ov965x_vga,
|
||
- ARRAY_SIZE(bridge_start_ov965x_vga));
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_2_vga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_2_vga));
|
||
- break;
|
||
- case 2: /* 800x600 */
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_1_svga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_1_svga));
|
||
- reg_w_array(gspca_dev, bridge_start_ov965x_svga,
|
||
- ARRAY_SIZE(bridge_start_ov965x_svga));
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_2_svga));
|
||
- break;
|
||
- case 1: /* 1024x768 */
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_1_xga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_1_xga));
|
||
- reg_w_array(gspca_dev, bridge_start_ov965x_xga,
|
||
- ARRAY_SIZE(bridge_start_ov965x_xga));
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_2_svga));
|
||
- break;
|
||
- case 0: /* 1280x1024 */
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_1_sxga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_1_sxga));
|
||
- reg_w_array(gspca_dev, bridge_start_ov965x_sxga,
|
||
- ARRAY_SIZE(bridge_start_ov965x_sxga));
|
||
- sccb_w_array(gspca_dev, sensor_start_ov965x_2_sxga,
|
||
- ARRAY_SIZE(sensor_start_ov965x_2_sxga));
|
||
- break;
|
||
- }
|
||
- setfreq(gspca_dev);
|
||
- setautogain_96(gspca_dev);
|
||
- setbrightness_96(gspca_dev);
|
||
- setcontrast_96(gspca_dev);
|
||
- setexposure_96(gspca_dev);
|
||
- setsharpness_96(gspca_dev);
|
||
- setsatur(gspca_dev);
|
||
-
|
||
- ov534_reg_write(gspca_dev, 0xe0, 0x00);
|
||
- ov534_reg_write(gspca_dev, 0xe0, 0x00);
|
||
- ov534_set_led(gspca_dev, 1);
|
||
- return 0;
|
||
-}
|
||
-
|
||
-static void sd_stopN_ov772x(struct gspca_dev *gspca_dev)
|
||
+static void sd_stopN(struct gspca_dev *gspca_dev)
|
||
{
|
||
ov534_reg_write(gspca_dev, 0xe0, 0x09);
|
||
ov534_set_led(gspca_dev, 0);
|
||
}
|
||
|
||
-static void sd_stopN_ov965x(struct gspca_dev *gspca_dev)
|
||
-{
|
||
- ov534_reg_write(gspca_dev, 0xe0, 0x01);
|
||
- ov534_set_led(gspca_dev, 0);
|
||
- ov534_reg_write(gspca_dev, 0xe0, 0x00);
|
||
-}
|
||
-
|
||
/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
|
||
#define UVC_STREAM_EOH (1 << 7)
|
||
#define UVC_STREAM_ERR (1 << 6)
|
||
@@ -1875,11 +945,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||
__u32 this_pts;
|
||
u16 this_fid;
|
||
int remaining_len = len;
|
||
- int payload_len;
|
||
|
||
- payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
|
||
do {
|
||
- len = min(remaining_len, payload_len);
|
||
+ len = min(remaining_len, 2048);
|
||
|
||
/* Payloads are prefixed with a UVC-style header. We
|
||
consider a frame to start when the FID toggles, or the PTS
|
||
@@ -1918,7 +986,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||
data + 12, len - 12);
|
||
/* If this packet is marked as EOF, end the frame */
|
||
} else if (data[1] & UVC_STREAM_EOF) {
|
||
+ struct gspca_frame *frame;
|
||
+
|
||
sd->last_pts = 0;
|
||
+ frame = gspca_get_i_frame(gspca_dev);
|
||
+ if (frame == NULL)
|
||
+ goto discard;
|
||
+ if (frame->data_end - frame->data + (len - 12) !=
|
||
+ gspca_dev->width * gspca_dev->height * 2) {
|
||
+ PDEBUG(D_PACK, "wrong sized frame");
|
||
+ goto discard;
|
||
+ }
|
||
gspca_frame_add(gspca_dev, LAST_PACKET,
|
||
data + 12, len - 12);
|
||
} else {
|
||
@@ -1965,12 +1043,8 @@ 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) {
|
||
- if (sd->sensor == SENSOR_OV772X)
|
||
- setexposure_77(gspca_dev);
|
||
- else
|
||
- setexposure_96(gspca_dev);
|
||
- }
|
||
+ if (gspca_dev->streaming)
|
||
+ setexposure(gspca_dev);
|
||
return 0;
|
||
}
|
||
|
||
@@ -1987,12 +1061,8 @@ 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) {
|
||
- if (sd->sensor == SENSOR_OV772X)
|
||
- setbrightness_77(gspca_dev);
|
||
- else
|
||
- setbrightness_96(gspca_dev);
|
||
- }
|
||
+ if (gspca_dev->streaming)
|
||
+ setbrightness(gspca_dev);
|
||
return 0;
|
||
}
|
||
|
||
@@ -2009,12 +1079,8 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
|
||
sd->contrast = val;
|
||
- if (gspca_dev->streaming) {
|
||
- if (sd->sensor == SENSOR_OV772X)
|
||
- setcontrast_77(gspca_dev);
|
||
- else
|
||
- setcontrast_96(gspca_dev);
|
||
- }
|
||
+ if (gspca_dev->streaming)
|
||
+ setcontrast(gspca_dev);
|
||
return 0;
|
||
}
|
||
|
||
@@ -2026,41 +1092,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||
return 0;
|
||
}
|
||
|
||
-static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
-
|
||
- sd->satur = val;
|
||
- if (gspca_dev->streaming)
|
||
- setsatur(gspca_dev);
|
||
- return 0;
|
||
-}
|
||
-
|
||
-static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
-
|
||
- *val = sd->satur;
|
||
- return 0;
|
||
-}
|
||
-static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
-
|
||
- sd->lightfreq = val;
|
||
- if (gspca_dev->streaming)
|
||
- setfreq(gspca_dev);
|
||
- return 0;
|
||
-}
|
||
-
|
||
-static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
|
||
-{
|
||
- struct sd *sd = (struct sd *) gspca_dev;
|
||
-
|
||
- *val = sd->lightfreq;
|
||
- return 0;
|
||
-}
|
||
-
|
||
static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
@@ -2122,22 +1153,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->autogain = val;
|
||
|
||
if (gspca_dev->streaming) {
|
||
- if (sd->sensor == SENSOR_OV772X) {
|
||
-
|
||
- /* the auto white balance control works only
|
||
- * when auto gain is set */
|
||
- if (val)
|
||
- gspca_dev->ctrl_inac &= ~(1 << AWB_77_IDX);
|
||
- else
|
||
- gspca_dev->ctrl_inac |= (1 << AWB_77_IDX);
|
||
- setautogain_77(gspca_dev);
|
||
- } else {
|
||
- if (val)
|
||
- gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX);
|
||
- else
|
||
- gspca_dev->ctrl_inac &= ~(1 << EXPO_96_IDX);
|
||
- setautogain_96(gspca_dev);
|
||
- }
|
||
+
|
||
+ /* the auto white balance control works only
|
||
+ * when auto gain is set */
|
||
+ if (val)
|
||
+ gspca_dev->ctrl_inac &= ~(1 << AWB_IDX);
|
||
+ else
|
||
+ gspca_dev->ctrl_inac |= (1 << AWB_IDX);
|
||
+ setautogain(gspca_dev);
|
||
}
|
||
return 0;
|
||
}
|
||
@@ -2173,12 +1196,8 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
|
||
sd->sharpness = val;
|
||
- if (gspca_dev->streaming) {
|
||
- if (sd->sensor == SENSOR_OV772X)
|
||
- setsharpness_77(gspca_dev);
|
||
- else
|
||
- setsharpness_96(gspca_dev);
|
||
- }
|
||
+ if (gspca_dev->streaming)
|
||
+ setsharpness(gspca_dev);
|
||
return 0;
|
||
}
|
||
|
||
@@ -2257,7 +1276,7 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev,
|
||
|
||
/* Set requested framerate */
|
||
sd->frame_rate = tpf->denominator / tpf->numerator;
|
||
- if (gspca_dev->streaming && sd->sensor == SENSOR_OV772X)
|
||
+ if (gspca_dev->streaming)
|
||
set_frame_rate(gspca_dev);
|
||
|
||
/* Return the actual framerate */
|
||
@@ -2267,57 +1286,23 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev,
|
||
return 0;
|
||
}
|
||
|
||
-static int sd_querymenu(struct gspca_dev *gspca_dev,
|
||
- struct v4l2_querymenu *menu)
|
||
-{
|
||
- switch (menu->id) {
|
||
- case V4L2_CID_POWER_LINE_FREQUENCY:
|
||
- switch (menu->index) {
|
||
- case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
|
||
- strcpy((char *) menu->name, "NoFliker");
|
||
- return 0;
|
||
- case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
|
||
- strcpy((char *) menu->name, "50 Hz");
|
||
- return 0;
|
||
- case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
|
||
- strcpy((char *) menu->name, "60 Hz");
|
||
- return 0;
|
||
- }
|
||
- break;
|
||
- }
|
||
- return -EINVAL;
|
||
-}
|
||
-
|
||
/* sub-driver description */
|
||
-static const struct sd_desc sd_desc_ov772x = {
|
||
+static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
- .ctrls = sd_ctrls_ov772x,
|
||
- .nctrls = ARRAY_SIZE(sd_ctrls_ov772x),
|
||
+ .ctrls = sd_ctrls,
|
||
+ .nctrls = ARRAY_SIZE(sd_ctrls),
|
||
.config = sd_config,
|
||
.init = sd_init,
|
||
- .start = sd_start_ov772x,
|
||
- .stopN = sd_stopN_ov772x,
|
||
+ .start = sd_start,
|
||
+ .stopN = sd_stopN,
|
||
.pkt_scan = sd_pkt_scan,
|
||
.get_streamparm = sd_get_streamparm,
|
||
.set_streamparm = sd_set_streamparm,
|
||
};
|
||
|
||
-static const struct sd_desc sd_desc_ov965x = {
|
||
- .name = MODULE_NAME,
|
||
- .ctrls = sd_ctrls_ov965x,
|
||
- .nctrls = ARRAY_SIZE(sd_ctrls_ov965x),
|
||
- .config = sd_config,
|
||
- .init = sd_init,
|
||
- .start = sd_start_ov965x,
|
||
- .stopN = sd_stopN_ov965x,
|
||
- .pkt_scan = sd_pkt_scan,
|
||
- .querymenu = sd_querymenu,
|
||
-};
|
||
-
|
||
/* -- module initialisation -- */
|
||
static const __devinitdata struct usb_device_id device_table[] = {
|
||
- {USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X},
|
||
- {USB_DEVICE(0x1415, 0x2000), .driver_info = SENSOR_OV772X},
|
||
+ {USB_DEVICE(0x1415, 0x2000)},
|
||
{}
|
||
};
|
||
|
||
@@ -2326,11 +1311,7 @@ MODULE_DEVICE_TABLE(usb, device_table);
|
||
/* -- device connect -- */
|
||
static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||
{
|
||
- return gspca_dev_probe(intf, id,
|
||
- id->driver_info == SENSOR_OV772X
|
||
- ? &sd_desc_ov772x
|
||
- : &sd_desc_ov965x,
|
||
- sizeof(struct sd),
|
||
+ return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
|
||
THIS_MODULE);
|
||
}
|
||
|
||
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c
|
||
new file mode 100644
|
||
index 0000000..bbe5a03
|
||
--- /dev/null
|
||
+++ b/drivers/media/video/gspca/ov534_9.c
|
||
@@ -0,0 +1,1477 @@
|
||
+/*
|
||
+ * ov534-ov965x gspca driver
|
||
+ *
|
||
+ * Copyright (C) 2009-2010 Jean-Francois Moine http://moinejf.free.fr
|
||
+ * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
|
||
+ * Copyright (C) 2008 Jim Paris <jim@jtan.com>
|
||
+ *
|
||
+ * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
|
||
+ * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
|
||
+ * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
|
||
+ *
|
||
+ * 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 "ov534_9"
|
||
+
|
||
+#include "gspca.h"
|
||
+
|
||
+#define OV534_REG_ADDRESS 0xf1 /* sensor address */
|
||
+#define OV534_REG_SUBADDR 0xf2
|
||
+#define OV534_REG_WRITE 0xf3
|
||
+#define OV534_REG_READ 0xf4
|
||
+#define OV534_REG_OPERATION 0xf5
|
||
+#define OV534_REG_STATUS 0xf6
|
||
+
|
||
+#define OV534_OP_WRITE_3 0x37
|
||
+#define OV534_OP_WRITE_2 0x33
|
||
+#define OV534_OP_READ_2 0xf9
|
||
+
|
||
+#define CTRL_TIMEOUT 500
|
||
+
|
||
+MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
|
||
+MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
|
||
+MODULE_LICENSE("GPL");
|
||
+
|
||
+/* specific webcam descriptor */
|
||
+struct sd {
|
||
+ struct gspca_dev gspca_dev; /* !! must be the first item */
|
||
+ __u32 last_pts;
|
||
+ u8 last_fid;
|
||
+
|
||
+ u8 brightness;
|
||
+ u8 contrast;
|
||
+ u8 autogain;
|
||
+ u8 exposure;
|
||
+ s8 sharpness;
|
||
+ u8 satur;
|
||
+ u8 freq;
|
||
+};
|
||
+
|
||
+/* V4L2 controls supported by the driver */
|
||
+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);
|
||
+static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int sd_getautogain(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_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
+ { /* 0 */
|
||
+ {
|
||
+ .id = V4L2_CID_BRIGHTNESS,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Brightness",
|
||
+ .minimum = 0,
|
||
+ .maximum = 15,
|
||
+ .step = 1,
|
||
+#define BRIGHTNESS_DEF 7
|
||
+ .default_value = BRIGHTNESS_DEF,
|
||
+ },
|
||
+ .set = sd_setbrightness,
|
||
+ .get = sd_getbrightness,
|
||
+ },
|
||
+ { /* 1 */
|
||
+ {
|
||
+ .id = V4L2_CID_CONTRAST,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Contrast",
|
||
+ .minimum = 0,
|
||
+ .maximum = 15,
|
||
+ .step = 1,
|
||
+#define CONTRAST_DEF 3
|
||
+ .default_value = CONTRAST_DEF,
|
||
+ },
|
||
+ .set = sd_setcontrast,
|
||
+ .get = sd_getcontrast,
|
||
+ },
|
||
+ { /* 2 */
|
||
+ {
|
||
+ .id = V4L2_CID_AUTOGAIN,
|
||
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
|
||
+ .name = "Autogain",
|
||
+ .minimum = 0,
|
||
+ .maximum = 1,
|
||
+ .step = 1,
|
||
+#define AUTOGAIN_DEF 1
|
||
+ .default_value = AUTOGAIN_DEF,
|
||
+ },
|
||
+ .set = sd_setautogain,
|
||
+ .get = sd_getautogain,
|
||
+ },
|
||
+#define EXPO_IDX 3
|
||
+ { /* 3 */
|
||
+ {
|
||
+ .id = V4L2_CID_EXPOSURE,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Exposure",
|
||
+ .minimum = 0,
|
||
+ .maximum = 3,
|
||
+ .step = 1,
|
||
+#define EXPO_DEF 0
|
||
+ .default_value = EXPO_DEF,
|
||
+ },
|
||
+ .set = sd_setexposure,
|
||
+ .get = sd_getexposure,
|
||
+ },
|
||
+ { /* 4 */
|
||
+ {
|
||
+ .id = V4L2_CID_SHARPNESS,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Sharpness",
|
||
+ .minimum = -1, /* -1 = auto */
|
||
+ .maximum = 4,
|
||
+ .step = 1,
|
||
+#define SHARPNESS_DEF -1
|
||
+ .default_value = SHARPNESS_DEF,
|
||
+ },
|
||
+ .set = sd_setsharpness,
|
||
+ .get = sd_getsharpness,
|
||
+ },
|
||
+ { /* 5 */
|
||
+ {
|
||
+ .id = V4L2_CID_SATURATION,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Saturation",
|
||
+ .minimum = 0,
|
||
+ .maximum = 4,
|
||
+ .step = 1,
|
||
+#define SATUR_DEF 2
|
||
+ .default_value = SATUR_DEF,
|
||
+ },
|
||
+ .set = sd_setsatur,
|
||
+ .get = sd_getsatur,
|
||
+ },
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_POWER_LINE_FREQUENCY,
|
||
+ .type = V4L2_CTRL_TYPE_MENU,
|
||
+ .name = "Light frequency filter",
|
||
+ .minimum = 0,
|
||
+ .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
|
||
+ .step = 1,
|
||
+#define FREQ_DEF 0
|
||
+ .default_value = FREQ_DEF,
|
||
+ },
|
||
+ .set = sd_setfreq,
|
||
+ .get = sd_getfreq,
|
||
+ },
|
||
+};
|
||
+
|
||
+static const struct v4l2_pix_format ov965x_mode[] = {
|
||
+#define QVGA_MODE 0
|
||
+ {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 320,
|
||
+ .sizeimage = 320 * 240 * 3 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG},
|
||
+#define VGA_MODE 1
|
||
+ {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 640,
|
||
+ .sizeimage = 640 * 480 * 3 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG},
|
||
+#define SVGA_MODE 2
|
||
+ {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 800,
|
||
+ .sizeimage = 800 * 600 * 3 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG},
|
||
+#define XGA_MODE 3
|
||
+ {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 1024,
|
||
+ .sizeimage = 1024 * 768 * 3 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG},
|
||
+#define SXGA_MODE 4
|
||
+ {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 1280,
|
||
+ .sizeimage = 1280 * 1024 * 3 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG},
|
||
+};
|
||
+
|
||
+static const u8 bridge_init[][2] = {
|
||
+ {0x88, 0xf8},
|
||
+ {0x89, 0xff},
|
||
+ {0x76, 0x03},
|
||
+ {0x92, 0x03},
|
||
+ {0x95, 0x10},
|
||
+ {0xe2, 0x00},
|
||
+ {0xe7, 0x3e},
|
||
+ {0x8d, 0x1c},
|
||
+ {0x8e, 0x00},
|
||
+ {0x8f, 0x00},
|
||
+ {0x1f, 0x00},
|
||
+ {0xc3, 0xf9},
|
||
+ {0x89, 0xff},
|
||
+ {0x88, 0xf8},
|
||
+ {0x76, 0x03},
|
||
+ {0x92, 0x01},
|
||
+ {0x93, 0x18},
|
||
+ {0x1c, 0x0a},
|
||
+ {0x1d, 0x48},
|
||
+ {0xc0, 0x50},
|
||
+ {0xc1, 0x3c},
|
||
+ {0x34, 0x05},
|
||
+ {0xc2, 0x0c},
|
||
+ {0xc3, 0xf9},
|
||
+ {0x34, 0x05},
|
||
+ {0xe7, 0x2e},
|
||
+ {0x31, 0xf9},
|
||
+ {0x35, 0x02},
|
||
+ {0xd9, 0x10},
|
||
+ {0x25, 0x42},
|
||
+ {0x94, 0x11},
|
||
+};
|
||
+
|
||
+static const u8 sensor_init[][2] = {
|
||
+ {0x12, 0x80}, /* com7 - SSCB reset */
|
||
+ {0x00, 0x00}, /* gain */
|
||
+ {0x01, 0x80}, /* blue */
|
||
+ {0x02, 0x80}, /* red */
|
||
+ {0x03, 0x1b}, /* vref */
|
||
+ {0x04, 0x03}, /* com1 - exposure low bits */
|
||
+ {0x0b, 0x57}, /* ver */
|
||
+ {0x0e, 0x61}, /* com5 */
|
||
+ {0x0f, 0x42}, /* com6 */
|
||
+ {0x11, 0x00}, /* clkrc */
|
||
+ {0x12, 0x02}, /* com7 - 15fps VGA YUYV */
|
||
+ {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
+ {0x14, 0x28}, /* com9 */
|
||
+ {0x16, 0x24}, /* reg16 */
|
||
+ {0x17, 0x1d}, /* hstart*/
|
||
+ {0x18, 0xbd}, /* hstop */
|
||
+ {0x19, 0x01}, /* vstrt */
|
||
+ {0x1a, 0x81}, /* vstop*/
|
||
+ {0x1e, 0x04}, /* mvfp */
|
||
+ {0x24, 0x3c}, /* aew */
|
||
+ {0x25, 0x36}, /* aeb */
|
||
+ {0x26, 0x71}, /* vpt */
|
||
+ {0x27, 0x08}, /* bbias */
|
||
+ {0x28, 0x08}, /* gbbias */
|
||
+ {0x29, 0x15}, /* gr com */
|
||
+ {0x2a, 0x00}, /* exhch */
|
||
+ {0x2b, 0x00}, /* exhcl */
|
||
+ {0x2c, 0x08}, /* rbias */
|
||
+ {0x32, 0xff}, /* href */
|
||
+ {0x33, 0x00}, /* chlf */
|
||
+ {0x34, 0x3f}, /* aref1 */
|
||
+ {0x35, 0x00}, /* aref2 */
|
||
+ {0x36, 0xf8}, /* aref3 */
|
||
+ {0x38, 0x72}, /* adc2 */
|
||
+ {0x39, 0x57}, /* aref4 */
|
||
+ {0x3a, 0x80}, /* tslb - yuyv */
|
||
+ {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
|
||
+ {0x3d, 0x99}, /* com13 */
|
||
+ {0x3f, 0xc1}, /* edge */
|
||
+ {0x40, 0xc0}, /* com15 */
|
||
+ {0x41, 0x40}, /* com16 */
|
||
+ {0x42, 0xc0}, /* com17 */
|
||
+ {0x43, 0x0a}, /* rsvd */
|
||
+ {0x44, 0xf0},
|
||
+ {0x45, 0x46},
|
||
+ {0x46, 0x62},
|
||
+ {0x47, 0x2a},
|
||
+ {0x48, 0x3c},
|
||
+ {0x4a, 0xfc},
|
||
+ {0x4b, 0xfc},
|
||
+ {0x4c, 0x7f},
|
||
+ {0x4d, 0x7f},
|
||
+ {0x4e, 0x7f},
|
||
+ {0x4f, 0x98}, /* matrix */
|
||
+ {0x50, 0x98},
|
||
+ {0x51, 0x00},
|
||
+ {0x52, 0x28},
|
||
+ {0x53, 0x70},
|
||
+ {0x54, 0x98},
|
||
+ {0x58, 0x1a}, /* matrix coef sign */
|
||
+ {0x59, 0x85}, /* AWB control */
|
||
+ {0x5a, 0xa9},
|
||
+ {0x5b, 0x64},
|
||
+ {0x5c, 0x84},
|
||
+ {0x5d, 0x53},
|
||
+ {0x5e, 0x0e},
|
||
+ {0x5f, 0xf0}, /* AWB blue limit */
|
||
+ {0x60, 0xf0}, /* AWB red limit */
|
||
+ {0x61, 0xf0}, /* AWB green limit */
|
||
+ {0x62, 0x00}, /* lcc1 */
|
||
+ {0x63, 0x00}, /* lcc2 */
|
||
+ {0x64, 0x02}, /* lcc3 */
|
||
+ {0x65, 0x16}, /* lcc4 */
|
||
+ {0x66, 0x01}, /* lcc5 */
|
||
+ {0x69, 0x02}, /* hv */
|
||
+ {0x6b, 0x5a}, /* dbvl */
|
||
+ {0x6c, 0x04},
|
||
+ {0x6d, 0x55},
|
||
+ {0x6e, 0x00},
|
||
+ {0x6f, 0x9d},
|
||
+ {0x70, 0x21}, /* dnsth */
|
||
+ {0x71, 0x78},
|
||
+ {0x72, 0x00}, /* poidx */
|
||
+ {0x73, 0x01}, /* pckdv */
|
||
+ {0x74, 0x3a}, /* xindx */
|
||
+ {0x75, 0x35}, /* yindx */
|
||
+ {0x76, 0x01},
|
||
+ {0x77, 0x02},
|
||
+ {0x7a, 0x12}, /* gamma curve */
|
||
+ {0x7b, 0x08},
|
||
+ {0x7c, 0x16},
|
||
+ {0x7d, 0x30},
|
||
+ {0x7e, 0x5e},
|
||
+ {0x7f, 0x72},
|
||
+ {0x80, 0x82},
|
||
+ {0x81, 0x8e},
|
||
+ {0x82, 0x9a},
|
||
+ {0x83, 0xa4},
|
||
+ {0x84, 0xac},
|
||
+ {0x85, 0xb8},
|
||
+ {0x86, 0xc3},
|
||
+ {0x87, 0xd6},
|
||
+ {0x88, 0xe6},
|
||
+ {0x89, 0xf2},
|
||
+ {0x8a, 0x03},
|
||
+ {0x8c, 0x89}, /* com19 */
|
||
+ {0x14, 0x28}, /* com9 */
|
||
+ {0x90, 0x7d},
|
||
+ {0x91, 0x7b},
|
||
+ {0x9d, 0x03}, /* lcc6 */
|
||
+ {0x9e, 0x04}, /* lcc7 */
|
||
+ {0x9f, 0x7a},
|
||
+ {0xa0, 0x79},
|
||
+ {0xa1, 0x40}, /* aechm */
|
||
+ {0xa4, 0x50}, /* com21 */
|
||
+ {0xa5, 0x68}, /* com26 */
|
||
+ {0xa6, 0x4a}, /* AWB green */
|
||
+ {0xa8, 0xc1}, /* refa8 */
|
||
+ {0xa9, 0xef}, /* refa9 */
|
||
+ {0xaa, 0x92},
|
||
+ {0xab, 0x04},
|
||
+ {0xac, 0x80}, /* black level control */
|
||
+ {0xad, 0x80},
|
||
+ {0xae, 0x80},
|
||
+ {0xaf, 0x80},
|
||
+ {0xb2, 0xf2},
|
||
+ {0xb3, 0x20},
|
||
+ {0xb4, 0x20}, /* ctrlb4 */
|
||
+ {0xb5, 0x00},
|
||
+ {0xb6, 0xaf},
|
||
+ {0xbb, 0xae},
|
||
+ {0xbc, 0x7f}, /* ADC channel offsets */
|
||
+ {0xdb, 0x7f},
|
||
+ {0xbe, 0x7f},
|
||
+ {0xbf, 0x7f},
|
||
+ {0xc0, 0xe2},
|
||
+ {0xc1, 0xc0},
|
||
+ {0xc2, 0x01},
|
||
+ {0xc3, 0x4e},
|
||
+ {0xc6, 0x85},
|
||
+ {0xc7, 0x80}, /* com24 */
|
||
+ {0xc9, 0xe0},
|
||
+ {0xca, 0xe8},
|
||
+ {0xcb, 0xf0},
|
||
+ {0xcc, 0xd8},
|
||
+ {0xcd, 0xf1},
|
||
+ {0x4f, 0x98}, /* matrix */
|
||
+ {0x50, 0x98},
|
||
+ {0x51, 0x00},
|
||
+ {0x52, 0x28},
|
||
+ {0x53, 0x70},
|
||
+ {0x54, 0x98},
|
||
+ {0x58, 0x1a},
|
||
+ {0xff, 0x41}, /* read 41, write ff 00 */
|
||
+ {0x41, 0x40}, /* com16 */
|
||
+
|
||
+ {0xc5, 0x03}, /* 60 Hz banding filter */
|
||
+ {0x6a, 0x02}, /* 50 Hz banding filter */
|
||
+
|
||
+ {0x12, 0x62}, /* com7 - 30fps VGA YUV */
|
||
+ {0x36, 0xfa}, /* aref3 */
|
||
+ {0x69, 0x0a}, /* hv */
|
||
+ {0x8c, 0x89}, /* com22 */
|
||
+ {0x14, 0x28}, /* com9 */
|
||
+ {0x3e, 0x0c},
|
||
+ {0x41, 0x40}, /* com16 */
|
||
+ {0x72, 0x00},
|
||
+ {0x73, 0x00},
|
||
+ {0x74, 0x3a},
|
||
+ {0x75, 0x35},
|
||
+ {0x76, 0x01},
|
||
+ {0xc7, 0x80},
|
||
+ {0x03, 0x12}, /* vref */
|
||
+ {0x17, 0x16}, /* hstart */
|
||
+ {0x18, 0x02}, /* hstop */
|
||
+ {0x19, 0x01}, /* vstrt */
|
||
+ {0x1a, 0x3d}, /* vstop */
|
||
+ {0x32, 0xff}, /* href */
|
||
+ {0xc0, 0xaa},
|
||
+};
|
||
+
|
||
+static const u8 bridge_init_2[][2] = {
|
||
+ {0x94, 0xaa},
|
||
+ {0xf1, 0x60},
|
||
+ {0xe5, 0x04},
|
||
+ {0xc0, 0x50},
|
||
+ {0xc1, 0x3c},
|
||
+ {0x8c, 0x00},
|
||
+ {0x8d, 0x1c},
|
||
+ {0x34, 0x05},
|
||
+
|
||
+ {0xc2, 0x0c},
|
||
+ {0xc3, 0xf9},
|
||
+ {0xda, 0x01},
|
||
+ {0x50, 0x00},
|
||
+ {0x51, 0xa0},
|
||
+ {0x52, 0x3c},
|
||
+ {0x53, 0x00},
|
||
+ {0x54, 0x00},
|
||
+ {0x55, 0x00},
|
||
+ {0x57, 0x00},
|
||
+ {0x5c, 0x00},
|
||
+ {0x5a, 0xa0},
|
||
+ {0x5b, 0x78},
|
||
+ {0x35, 0x02},
|
||
+ {0xd9, 0x10},
|
||
+ {0x94, 0x11},
|
||
+};
|
||
+
|
||
+static const u8 sensor_init_2[][2] = {
|
||
+ {0x3b, 0xc4},
|
||
+ {0x1e, 0x04}, /* mvfp */
|
||
+ {0x13, 0xe0}, /* com8 */
|
||
+ {0x00, 0x00}, /* gain */
|
||
+ {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
+ {0x11, 0x03}, /* clkrc */
|
||
+ {0x6b, 0x5a}, /* dblv */
|
||
+ {0x6a, 0x05},
|
||
+ {0xc5, 0x07},
|
||
+ {0xa2, 0x4b},
|
||
+ {0xa3, 0x3e},
|
||
+ {0x2d, 0x00},
|
||
+ {0xff, 0x42}, /* read 42, write ff 00 */
|
||
+ {0x42, 0xc0}, /* com17 */
|
||
+ {0x2d, 0x00},
|
||
+ {0xff, 0x42}, /* read 42, write ff 00 */
|
||
+ {0x42, 0xc1}, /* com17 */
|
||
+/* sharpness */
|
||
+ {0x3f, 0x01},
|
||
+ {0xff, 0x42}, /* read 42, write ff 00 */
|
||
+ {0x42, 0xc1}, /* com17 */
|
||
+/* saturation */
|
||
+ {0x4f, 0x98}, /* matrix */
|
||
+ {0x50, 0x98},
|
||
+ {0x51, 0x00},
|
||
+ {0x52, 0x28},
|
||
+ {0x53, 0x70},
|
||
+ {0x54, 0x98},
|
||
+ {0x58, 0x1a},
|
||
+ {0xff, 0x41}, /* read 41, write ff 00 */
|
||
+ {0x41, 0x40}, /* com16 */
|
||
+/* contrast */
|
||
+ {0x56, 0x40},
|
||
+/* brightness */
|
||
+ {0x55, 0x8f},
|
||
+/* expo */
|
||
+ {0x10, 0x25}, /* aech - exposure high bits */
|
||
+ {0xff, 0x13}, /* read 13, write ff 00 */
|
||
+ {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
+};
|
||
+
|
||
+static const u8 sensor_start_1_vga[][2] = { /* same for qvga */
|
||
+ {0x12, 0x62}, /* com7 - 30fps VGA YUV */
|
||
+ {0x36, 0xfa}, /* aref3 */
|
||
+ {0x69, 0x0a}, /* hv */
|
||
+ {0x8c, 0x89}, /* com22 */
|
||
+ {0x14, 0x28}, /* com9 */
|
||
+ {0x3e, 0x0c}, /* com14 */
|
||
+ {0x41, 0x40}, /* com16 */
|
||
+ {0x72, 0x00},
|
||
+ {0x73, 0x00},
|
||
+ {0x74, 0x3a},
|
||
+ {0x75, 0x35},
|
||
+ {0x76, 0x01},
|
||
+ {0xc7, 0x80}, /* com24 */
|
||
+ {0x03, 0x12}, /* vref */
|
||
+ {0x17, 0x16}, /* hstart */
|
||
+ {0x18, 0x02}, /* hstop */
|
||
+ {0x19, 0x01}, /* vstrt */
|
||
+ {0x1a, 0x3d}, /* vstop */
|
||
+ {0x32, 0xff}, /* href */
|
||
+ {0xc0, 0xaa},
|
||
+};
|
||
+
|
||
+static const u8 sensor_start_1_svga[][2] = {
|
||
+ {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */
|
||
+ {0x36, 0xf8}, /* aref3 */
|
||
+ {0x69, 0x02}, /* hv */
|
||
+ {0x8c, 0x0d}, /* com22 */
|
||
+ {0x3e, 0x0c}, /* com14 */
|
||
+ {0x41, 0x40}, /* com16 */
|
||
+ {0x72, 0x00},
|
||
+ {0x73, 0x01},
|
||
+ {0x74, 0x3a},
|
||
+ {0x75, 0x35},
|
||
+ {0x76, 0x01},
|
||
+ {0xc7, 0x80}, /* com24 */
|
||
+ {0x03, 0x1b}, /* vref */
|
||
+ {0x17, 0x1d}, /* hstart */
|
||
+ {0x18, 0xbd}, /* hstop */
|
||
+ {0x19, 0x01}, /* vstrt */
|
||
+ {0x1a, 0x81}, /* vstop */
|
||
+ {0x32, 0xff}, /* href */
|
||
+ {0xc0, 0xe2},
|
||
+};
|
||
+
|
||
+static const u8 sensor_start_1_xga[][2] = {
|
||
+ {0x12, 0x02}, /* com7 */
|
||
+ {0x36, 0xf8}, /* aref3 */
|
||
+ {0x69, 0x02}, /* hv */
|
||
+ {0x8c, 0x89}, /* com22 */
|
||
+ {0x14, 0x28}, /* com9 */
|
||
+ {0x3e, 0x0c}, /* com14 */
|
||
+ {0x41, 0x40}, /* com16 */
|
||
+ {0x72, 0x00},
|
||
+ {0x73, 0x01},
|
||
+ {0x74, 0x3a},
|
||
+ {0x75, 0x35},
|
||
+ {0x76, 0x01},
|
||
+ {0xc7, 0x80}, /* com24 */
|
||
+ {0x03, 0x1b}, /* vref */
|
||
+ {0x17, 0x1d}, /* hstart */
|
||
+ {0x18, 0xbd}, /* hstop */
|
||
+ {0x19, 0x01}, /* vstrt */
|
||
+ {0x1a, 0x81}, /* vstop */
|
||
+ {0x32, 0xff}, /* href */
|
||
+ {0xc0, 0xe2},
|
||
+};
|
||
+
|
||
+static const u8 sensor_start_1_sxga[][2] = {
|
||
+ {0x12, 0x02}, /* com7 */
|
||
+ {0x36, 0xf8}, /* aref3 */
|
||
+ {0x69, 0x02}, /* hv */
|
||
+ {0x8c, 0x89}, /* com22 */
|
||
+ {0x14, 0x28}, /* com9 */
|
||
+ {0x3e, 0x0c}, /* com14 */
|
||
+ {0x41, 0x40}, /* com16 */
|
||
+ {0x72, 0x00},
|
||
+ {0x73, 0x01},
|
||
+ {0x74, 0x3a},
|
||
+ {0x75, 0x35},
|
||
+ {0x76, 0x01},
|
||
+ {0xc7, 0x80}, /* com24 */
|
||
+ {0x03, 0x1b}, /* vref */
|
||
+ {0x17, 0x1d}, /* hstart */
|
||
+ {0x18, 0x02}, /* hstop */
|
||
+ {0x19, 0x01}, /* vstrt */
|
||
+ {0x1a, 0x81}, /* vstop */
|
||
+ {0x32, 0xff}, /* href */
|
||
+ {0xc0, 0xe2},
|
||
+};
|
||
+
|
||
+static const u8 bridge_start_qvga[][2] = {
|
||
+ {0x94, 0xaa},
|
||
+ {0xf1, 0x60},
|
||
+ {0xe5, 0x04},
|
||
+ {0xc0, 0x50},
|
||
+ {0xc1, 0x3c},
|
||
+ {0x8c, 0x00},
|
||
+ {0x8d, 0x1c},
|
||
+ {0x34, 0x05},
|
||
+
|
||
+ {0xc2, 0x4c},
|
||
+ {0xc3, 0xf9},
|
||
+ {0xda, 0x00},
|
||
+ {0x50, 0x00},
|
||
+ {0x51, 0xa0},
|
||
+ {0x52, 0x78},
|
||
+ {0x53, 0x00},
|
||
+ {0x54, 0x00},
|
||
+ {0x55, 0x00},
|
||
+ {0x57, 0x00},
|
||
+ {0x5c, 0x00},
|
||
+ {0x5a, 0x50},
|
||
+ {0x5b, 0x3c},
|
||
+ {0x35, 0x02},
|
||
+ {0xd9, 0x10},
|
||
+ {0x94, 0x11},
|
||
+};
|
||
+
|
||
+static const u8 bridge_start_vga[][2] = {
|
||
+ {0x94, 0xaa},
|
||
+ {0xf1, 0x60},
|
||
+ {0xe5, 0x04},
|
||
+ {0xc0, 0x50},
|
||
+ {0xc1, 0x3c},
|
||
+ {0x8c, 0x00},
|
||
+ {0x8d, 0x1c},
|
||
+ {0x34, 0x05},
|
||
+ {0xc2, 0x0c},
|
||
+ {0xc3, 0xf9},
|
||
+ {0xda, 0x01},
|
||
+ {0x50, 0x00},
|
||
+ {0x51, 0xa0},
|
||
+ {0x52, 0x3c},
|
||
+ {0x53, 0x00},
|
||
+ {0x54, 0x00},
|
||
+ {0x55, 0x00},
|
||
+ {0x57, 0x00},
|
||
+ {0x5c, 0x00},
|
||
+ {0x5a, 0xa0},
|
||
+ {0x5b, 0x78},
|
||
+ {0x35, 0x02},
|
||
+ {0xd9, 0x10},
|
||
+ {0x94, 0x11},
|
||
+};
|
||
+
|
||
+static const u8 bridge_start_svga[][2] = {
|
||
+ {0x94, 0xaa},
|
||
+ {0xf1, 0x60},
|
||
+ {0xe5, 0x04},
|
||
+ {0xc0, 0xa0},
|
||
+ {0xc1, 0x80},
|
||
+ {0x8c, 0x00},
|
||
+ {0x8d, 0x1c},
|
||
+ {0x34, 0x05},
|
||
+ {0xc2, 0x4c},
|
||
+ {0xc3, 0xf9},
|
||
+ {0x50, 0x00},
|
||
+ {0x51, 0x40},
|
||
+ {0x52, 0x00},
|
||
+ {0x53, 0x00},
|
||
+ {0x54, 0x00},
|
||
+ {0x55, 0x88},
|
||
+ {0x57, 0x00},
|
||
+ {0x5c, 0x00},
|
||
+ {0x5a, 0xc8},
|
||
+ {0x5b, 0x96},
|
||
+ {0x35, 0x02},
|
||
+ {0xd9, 0x10},
|
||
+ {0xda, 0x00},
|
||
+ {0x94, 0x11},
|
||
+};
|
||
+
|
||
+static const u8 bridge_start_xga[][2] = {
|
||
+ {0x94, 0xaa},
|
||
+ {0xf1, 0x60},
|
||
+ {0xe5, 0x04},
|
||
+ {0xc0, 0xa0},
|
||
+ {0xc1, 0x80},
|
||
+ {0x8c, 0x00},
|
||
+ {0x8d, 0x1c},
|
||
+ {0x34, 0x05},
|
||
+ {0xc2, 0x4c},
|
||
+ {0xc3, 0xf9},
|
||
+ {0x50, 0x00},
|
||
+ {0x51, 0x40},
|
||
+ {0x52, 0x00},
|
||
+ {0x53, 0x00},
|
||
+ {0x54, 0x00},
|
||
+ {0x55, 0x88},
|
||
+ {0x57, 0x00},
|
||
+ {0x5c, 0x01},
|
||
+ {0x5a, 0x00},
|
||
+ {0x5b, 0xc0},
|
||
+ {0x35, 0x02},
|
||
+ {0xd9, 0x10},
|
||
+ {0xda, 0x01},
|
||
+ {0x94, 0x11},
|
||
+};
|
||
+
|
||
+static const u8 bridge_start_sxga[][2] = {
|
||
+ {0x94, 0xaa},
|
||
+ {0xf1, 0x60},
|
||
+ {0xe5, 0x04},
|
||
+ {0xc0, 0xa0},
|
||
+ {0xc1, 0x80},
|
||
+ {0x8c, 0x00},
|
||
+ {0x8d, 0x1c},
|
||
+ {0x34, 0x05},
|
||
+ {0xc2, 0x0c},
|
||
+ {0xc3, 0xf9},
|
||
+ {0xda, 0x00},
|
||
+ {0x35, 0x02},
|
||
+ {0xd9, 0x10},
|
||
+ {0x94, 0x11},
|
||
+};
|
||
+
|
||
+static const u8 sensor_start_2_qvga[][2] = {
|
||
+ {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */
|
||
+ {0x1e, 0x04}, /* mvfp */
|
||
+ {0x13, 0xe0}, /* com8 */
|
||
+ {0x00, 0x00},
|
||
+ {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
+ {0x11, 0x01}, /* clkrc */
|
||
+ {0x6b, 0x5a}, /* dblv */
|
||
+ {0x6a, 0x02}, /* 50 Hz banding filter */
|
||
+ {0xc5, 0x03}, /* 60 Hz banding filter */
|
||
+ {0xa2, 0x96}, /* bd50 */
|
||
+ {0xa3, 0x7d}, /* bd60 */
|
||
+
|
||
+ {0xff, 0x13}, /* read 13, write ff 00 */
|
||
+ {0x13, 0xe7},
|
||
+ {0x3a, 0x80}, /* tslb - yuyv */
|
||
+};
|
||
+
|
||
+static const u8 sensor_start_2_vga[][2] = {
|
||
+ {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
|
||
+ {0x1e, 0x04}, /* mvfp */
|
||
+ {0x13, 0xe0}, /* com8 */
|
||
+ {0x00, 0x00},
|
||
+ {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
+ {0x11, 0x03}, /* clkrc */
|
||
+ {0x6b, 0x5a}, /* dblv */
|
||
+ {0x6a, 0x05}, /* 50 Hz banding filter */
|
||
+ {0xc5, 0x07}, /* 60 Hz banding filter */
|
||
+ {0xa2, 0x4b}, /* bd50 */
|
||
+ {0xa3, 0x3e}, /* bd60 */
|
||
+
|
||
+ {0x2d, 0x00}, /* advfl */
|
||
+};
|
||
+
|
||
+static const u8 sensor_start_2_svga[][2] = { /* same for xga */
|
||
+ {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
|
||
+ {0x1e, 0x04}, /* mvfp */
|
||
+ {0x13, 0xe0}, /* com8 */
|
||
+ {0x00, 0x00},
|
||
+ {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
+ {0x11, 0x01}, /* clkrc */
|
||
+ {0x6b, 0x5a}, /* dblv */
|
||
+ {0x6a, 0x0c}, /* 50 Hz banding filter */
|
||
+ {0xc5, 0x0f}, /* 60 Hz banding filter */
|
||
+ {0xa2, 0x4e}, /* bd50 */
|
||
+ {0xa3, 0x41}, /* bd60 */
|
||
+};
|
||
+
|
||
+static const u8 sensor_start_2_sxga[][2] = {
|
||
+ {0x13, 0xe0}, /* com8 */
|
||
+ {0x00, 0x00},
|
||
+ {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
|
||
+ {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
|
||
+ {0x1e, 0x04}, /* mvfp */
|
||
+ {0x11, 0x01}, /* clkrc */
|
||
+ {0x6b, 0x5a}, /* dblv */
|
||
+ {0x6a, 0x0c}, /* 50 Hz banding filter */
|
||
+ {0xc5, 0x0f}, /* 60 Hz banding filter */
|
||
+ {0xa2, 0x4e}, /* bd50 */
|
||
+ {0xa3, 0x41}, /* bd60 */
|
||
+};
|
||
+
|
||
+static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
|
||
+{
|
||
+ struct usb_device *udev = gspca_dev->dev;
|
||
+ int ret;
|
||
+
|
||
+ if (gspca_dev->usb_err < 0)
|
||
+ return;
|
||
+ gspca_dev->usb_buf[0] = val;
|
||
+ ret = usb_control_msg(udev,
|
||
+ usb_sndctrlpipe(udev, 0),
|
||
+ 0x01,
|
||
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||
+ 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "reg_w failed %d", ret);
|
||
+ gspca_dev->usb_err = ret;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)
|
||
+{
|
||
+ PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val);
|
||
+ reg_w_i(gspca_dev, reg, val);
|
||
+}
|
||
+
|
||
+static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
|
||
+{
|
||
+ struct usb_device *udev = gspca_dev->dev;
|
||
+ int ret;
|
||
+
|
||
+ if (gspca_dev->usb_err < 0)
|
||
+ return 0;
|
||
+ ret = usb_control_msg(udev,
|
||
+ usb_rcvctrlpipe(udev, 0),
|
||
+ 0x01,
|
||
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||
+ 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
|
||
+ PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "reg_r err %d", ret);
|
||
+ gspca_dev->usb_err = ret;
|
||
+ }
|
||
+ return gspca_dev->usb_buf[0];
|
||
+}
|
||
+
|
||
+static int sccb_check_status(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ u8 data;
|
||
+ int i;
|
||
+
|
||
+ for (i = 0; i < 5; i++) {
|
||
+ data = reg_r(gspca_dev, OV534_REG_STATUS);
|
||
+
|
||
+ switch (data) {
|
||
+ case 0x00:
|
||
+ return 1;
|
||
+ case 0x04:
|
||
+ return 0;
|
||
+ case 0x03:
|
||
+ break;
|
||
+ default:
|
||
+ PDEBUG(D_USBI|D_USBO,
|
||
+ "sccb status 0x%02x, attempt %d/5",
|
||
+ data, i + 1);
|
||
+ }
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
|
||
+{
|
||
+ PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val);
|
||
+ reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);
|
||
+ reg_w_i(gspca_dev, OV534_REG_WRITE, val);
|
||
+ reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
|
||
+
|
||
+ if (!sccb_check_status(gspca_dev))
|
||
+ PDEBUG(D_ERR, "sccb_write failed");
|
||
+}
|
||
+
|
||
+static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
|
||
+{
|
||
+ reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
|
||
+ reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
|
||
+ if (!sccb_check_status(gspca_dev))
|
||
+ PDEBUG(D_ERR, "sccb_read failed 1");
|
||
+
|
||
+ reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
|
||
+ if (!sccb_check_status(gspca_dev))
|
||
+ PDEBUG(D_ERR, "sccb_read failed 2");
|
||
+
|
||
+ return reg_r(gspca_dev, OV534_REG_READ);
|
||
+}
|
||
+
|
||
+/* output a bridge sequence (reg - val) */
|
||
+static void reg_w_array(struct gspca_dev *gspca_dev,
|
||
+ const u8 (*data)[2], int len)
|
||
+{
|
||
+ while (--len >= 0) {
|
||
+ reg_w(gspca_dev, (*data)[0], (*data)[1]);
|
||
+ data++;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* output a sensor sequence (reg - val) */
|
||
+static void sccb_w_array(struct gspca_dev *gspca_dev,
|
||
+ const u8 (*data)[2], int len)
|
||
+{
|
||
+ while (--len >= 0) {
|
||
+ if ((*data)[0] != 0xff) {
|
||
+ sccb_write(gspca_dev, (*data)[0], (*data)[1]);
|
||
+ } else {
|
||
+ sccb_read(gspca_dev, (*data)[1]);
|
||
+ sccb_write(gspca_dev, 0xff, 0x00);
|
||
+ }
|
||
+ data++;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
|
||
+ * (direction and output)? */
|
||
+static void set_led(struct gspca_dev *gspca_dev, int status)
|
||
+{
|
||
+ u8 data;
|
||
+
|
||
+ PDEBUG(D_CONF, "led status: %d", status);
|
||
+
|
||
+ data = reg_r(gspca_dev, 0x21);
|
||
+ data |= 0x80;
|
||
+ reg_w(gspca_dev, 0x21, data);
|
||
+
|
||
+ data = reg_r(gspca_dev, 0x23);
|
||
+ if (status)
|
||
+ data |= 0x80;
|
||
+ else
|
||
+ data &= ~0x80;
|
||
+
|
||
+ reg_w(gspca_dev, 0x23, data);
|
||
+
|
||
+ if (!status) {
|
||
+ data = reg_r(gspca_dev, 0x21);
|
||
+ data &= ~0x80;
|
||
+ reg_w(gspca_dev, 0x21, data);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void setbrightness(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ u8 val;
|
||
+
|
||
+ val = sd->brightness;
|
||
+ if (val < 8)
|
||
+ val = 15 - val; /* f .. 8 */
|
||
+ else
|
||
+ val = val - 8; /* 0 .. 7 */
|
||
+ sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */
|
||
+ 0x0f | (val << 4));
|
||
+}
|
||
+
|
||
+static void setcontrast(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */
|
||
+ sd->contrast << 4);
|
||
+}
|
||
+
|
||
+static void setautogain(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ u8 val;
|
||
+
|
||
+/*fixme: should adjust agc/awb/aec by different controls */
|
||
+ val = sd->autogain;
|
||
+ val = sccb_read(gspca_dev, 0x13); /* com8 */
|
||
+ sccb_write(gspca_dev, 0xff, 0x00);
|
||
+ if (sd->autogain)
|
||
+ val |= 0x05; /* agc & aec */
|
||
+ else
|
||
+ val &= 0xfa;
|
||
+ sccb_write(gspca_dev, 0x13, val);
|
||
+}
|
||
+
|
||
+static void setexposure(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ u8 val;
|
||
+ static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
|
||
+
|
||
+ sccb_write(gspca_dev, 0x10, /* aec[9:2] */
|
||
+ expo[sd->exposure]);
|
||
+
|
||
+ val = sccb_read(gspca_dev, 0x13); /* com8 */
|
||
+ sccb_write(gspca_dev, 0xff, 0x00);
|
||
+ sccb_write(gspca_dev, 0x13, val);
|
||
+
|
||
+ val = sccb_read(gspca_dev, 0xa1); /* aech */
|
||
+ sccb_write(gspca_dev, 0xff, 0x00);
|
||
+ sccb_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */
|
||
+}
|
||
+
|
||
+static void setsharpness(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ s8 val;
|
||
+
|
||
+ val = sd->sharpness;
|
||
+ if (val < 0) { /* auto */
|
||
+ val = sccb_read(gspca_dev, 0x42); /* com17 */
|
||
+ sccb_write(gspca_dev, 0xff, 0x00);
|
||
+ sccb_write(gspca_dev, 0x42, val | 0x40);
|
||
+ /* Edge enhancement strength auto adjust */
|
||
+ return;
|
||
+ }
|
||
+ if (val != 0)
|
||
+ val = 1 << (val - 1);
|
||
+ sccb_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */
|
||
+ val);
|
||
+ val = sccb_read(gspca_dev, 0x42); /* com17 */
|
||
+ sccb_write(gspca_dev, 0xff, 0x00);
|
||
+ sccb_write(gspca_dev, 0x42, val & 0xbf);
|
||
+}
|
||
+
|
||
+static void setsatur(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ u8 val1, val2, val3;
|
||
+ static const u8 matrix[5][2] = {
|
||
+ {0x14, 0x38},
|
||
+ {0x1e, 0x54},
|
||
+ {0x28, 0x70},
|
||
+ {0x32, 0x8c},
|
||
+ {0x48, 0x90}
|
||
+ };
|
||
+
|
||
+ val1 = matrix[sd->satur][0];
|
||
+ val2 = matrix[sd->satur][1];
|
||
+ val3 = val1 + val2;
|
||
+ sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */
|
||
+ sccb_write(gspca_dev, 0x50, val3);
|
||
+ sccb_write(gspca_dev, 0x51, 0x00);
|
||
+ sccb_write(gspca_dev, 0x52, val1);
|
||
+ sccb_write(gspca_dev, 0x53, val2);
|
||
+ sccb_write(gspca_dev, 0x54, val3);
|
||
+ sccb_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */
|
||
+
|
||
+ val1 = sccb_read(gspca_dev, 0x41); /* com16 */
|
||
+ sccb_write(gspca_dev, 0xff, 0x00);
|
||
+ sccb_write(gspca_dev, 0x41, val1);
|
||
+}
|
||
+
|
||
+static void setfreq(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ u8 val;
|
||
+
|
||
+ val = sccb_read(gspca_dev, 0x13); /* com8 */
|
||
+ sccb_write(gspca_dev, 0xff, 0x00);
|
||
+ if (sd->freq == 0) {
|
||
+ sccb_write(gspca_dev, 0x13, val & 0xdf);
|
||
+ return;
|
||
+ }
|
||
+ sccb_write(gspca_dev, 0x13, val | 0x20);
|
||
+
|
||
+ val = sccb_read(gspca_dev, 0x42); /* com17 */
|
||
+ sccb_write(gspca_dev, 0xff, 0x00);
|
||
+ if (sd->freq == 1)
|
||
+ val |= 0x01;
|
||
+ else
|
||
+ val &= 0xfe;
|
||
+ sccb_write(gspca_dev, 0x42, val);
|
||
+}
|
||
+
|
||
+/* 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;
|
||
+
|
||
+ cam = &gspca_dev->cam;
|
||
+
|
||
+ cam->cam_mode = ov965x_mode;
|
||
+ cam->nmodes = ARRAY_SIZE(ov965x_mode);
|
||
+
|
||
+ sd->brightness = BRIGHTNESS_DEF;
|
||
+ sd->contrast = CONTRAST_DEF;
|
||
+#if AUTOGAIN_DEF != 0
|
||
+ sd->autogain = AUTOGAIN_DEF;
|
||
+ gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
|
||
+#endif
|
||
+#if EXPO_DEF != 0
|
||
+ sd->exposure = EXPO_DEF;
|
||
+#endif
|
||
+#if SHARPNESS_DEF != 0
|
||
+ sd->sharpness = SHARPNESS_DEF;
|
||
+#endif
|
||
+ sd->satur = SATUR_DEF;
|
||
+ sd->freq = FREQ_DEF;
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* this function is called at probe and resume time */
|
||
+static int sd_init(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ u16 sensor_id;
|
||
+
|
||
+ /* reset bridge */
|
||
+ reg_w(gspca_dev, 0xe7, 0x3a);
|
||
+ reg_w(gspca_dev, 0xe0, 0x08);
|
||
+ msleep(100);
|
||
+
|
||
+ /* initialize the sensor address */
|
||
+ reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);
|
||
+
|
||
+ /* reset sensor */
|
||
+ sccb_write(gspca_dev, 0x12, 0x80);
|
||
+ msleep(10);
|
||
+
|
||
+ /* probe the sensor */
|
||
+ sccb_read(gspca_dev, 0x0a);
|
||
+ sensor_id = sccb_read(gspca_dev, 0x0a) << 8;
|
||
+ sccb_read(gspca_dev, 0x0b);
|
||
+ sensor_id |= sccb_read(gspca_dev, 0x0b);
|
||
+ PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
|
||
+
|
||
+ /* initialize */
|
||
+ reg_w_array(gspca_dev, bridge_init,
|
||
+ ARRAY_SIZE(bridge_init));
|
||
+ sccb_w_array(gspca_dev, sensor_init,
|
||
+ ARRAY_SIZE(sensor_init));
|
||
+ reg_w_array(gspca_dev, bridge_init_2,
|
||
+ ARRAY_SIZE(bridge_init_2));
|
||
+ sccb_w_array(gspca_dev, sensor_init_2,
|
||
+ ARRAY_SIZE(sensor_init_2));
|
||
+ reg_w(gspca_dev, 0xe0, 0x00);
|
||
+ reg_w(gspca_dev, 0xe0, 0x01);
|
||
+ set_led(gspca_dev, 0);
|
||
+ reg_w(gspca_dev, 0xe0, 0x00);
|
||
+
|
||
+ return gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+static int sd_start(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ switch (gspca_dev->curr_mode) {
|
||
+ case QVGA_MODE: /* 320x240 */
|
||
+ sccb_w_array(gspca_dev, sensor_start_1_vga,
|
||
+ ARRAY_SIZE(sensor_start_1_vga));
|
||
+ reg_w_array(gspca_dev, bridge_start_qvga,
|
||
+ ARRAY_SIZE(bridge_start_qvga));
|
||
+ sccb_w_array(gspca_dev, sensor_start_2_qvga,
|
||
+ ARRAY_SIZE(sensor_start_2_qvga));
|
||
+ break;
|
||
+ case VGA_MODE: /* 640x480 */
|
||
+ sccb_w_array(gspca_dev, sensor_start_1_vga,
|
||
+ ARRAY_SIZE(sensor_start_1_vga));
|
||
+ reg_w_array(gspca_dev, bridge_start_vga,
|
||
+ ARRAY_SIZE(bridge_start_vga));
|
||
+ sccb_w_array(gspca_dev, sensor_start_2_vga,
|
||
+ ARRAY_SIZE(sensor_start_2_vga));
|
||
+ break;
|
||
+ case SVGA_MODE: /* 800x600 */
|
||
+ sccb_w_array(gspca_dev, sensor_start_1_svga,
|
||
+ ARRAY_SIZE(sensor_start_1_svga));
|
||
+ reg_w_array(gspca_dev, bridge_start_svga,
|
||
+ ARRAY_SIZE(bridge_start_svga));
|
||
+ sccb_w_array(gspca_dev, sensor_start_2_svga,
|
||
+ ARRAY_SIZE(sensor_start_2_svga));
|
||
+ break;
|
||
+ case XGA_MODE: /* 1024x768 */
|
||
+ sccb_w_array(gspca_dev, sensor_start_1_xga,
|
||
+ ARRAY_SIZE(sensor_start_1_xga));
|
||
+ reg_w_array(gspca_dev, bridge_start_xga,
|
||
+ ARRAY_SIZE(bridge_start_xga));
|
||
+ sccb_w_array(gspca_dev, sensor_start_2_svga,
|
||
+ ARRAY_SIZE(sensor_start_2_svga));
|
||
+ break;
|
||
+ default:
|
||
+/* case SXGA_MODE: * 1280x1024 */
|
||
+ sccb_w_array(gspca_dev, sensor_start_1_sxga,
|
||
+ ARRAY_SIZE(sensor_start_1_sxga));
|
||
+ reg_w_array(gspca_dev, bridge_start_sxga,
|
||
+ ARRAY_SIZE(bridge_start_sxga));
|
||
+ sccb_w_array(gspca_dev, sensor_start_2_sxga,
|
||
+ ARRAY_SIZE(sensor_start_2_sxga));
|
||
+ break;
|
||
+ }
|
||
+ setfreq(gspca_dev);
|
||
+ setautogain(gspca_dev);
|
||
+ setbrightness(gspca_dev);
|
||
+ setcontrast(gspca_dev);
|
||
+ setexposure(gspca_dev);
|
||
+ setsharpness(gspca_dev);
|
||
+ setsatur(gspca_dev);
|
||
+
|
||
+ reg_w(gspca_dev, 0xe0, 0x00);
|
||
+ reg_w(gspca_dev, 0xe0, 0x00);
|
||
+ set_led(gspca_dev, 1);
|
||
+ return gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+static void sd_stopN(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ reg_w(gspca_dev, 0xe0, 0x01);
|
||
+ set_led(gspca_dev, 0);
|
||
+ reg_w(gspca_dev, 0xe0, 0x00);
|
||
+}
|
||
+
|
||
+/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
|
||
+#define UVC_STREAM_EOH (1 << 7)
|
||
+#define UVC_STREAM_ERR (1 << 6)
|
||
+#define UVC_STREAM_STI (1 << 5)
|
||
+#define UVC_STREAM_RES (1 << 4)
|
||
+#define UVC_STREAM_SCR (1 << 3)
|
||
+#define UVC_STREAM_PTS (1 << 2)
|
||
+#define UVC_STREAM_EOF (1 << 1)
|
||
+#define UVC_STREAM_FID (1 << 0)
|
||
+
|
||
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data, int len)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ __u32 this_pts;
|
||
+ u8 this_fid;
|
||
+ int remaining_len = len;
|
||
+
|
||
+ do {
|
||
+ len = min(remaining_len, 2040);
|
||
+
|
||
+ /* Payloads are prefixed with a UVC-style header. We
|
||
+ consider a frame to start when the FID toggles, or the PTS
|
||
+ changes. A frame ends when EOF is set, and we've received
|
||
+ the correct number of bytes. */
|
||
+
|
||
+ /* Verify UVC header. Header length is always 12 */
|
||
+ if (data[0] != 12 || len < 12) {
|
||
+ PDEBUG(D_PACK, "bad header");
|
||
+ goto discard;
|
||
+ }
|
||
+
|
||
+ /* Check errors */
|
||
+ if (data[1] & UVC_STREAM_ERR) {
|
||
+ PDEBUG(D_PACK, "payload error");
|
||
+ goto discard;
|
||
+ }
|
||
+
|
||
+ /* Extract PTS and FID */
|
||
+ if (!(data[1] & UVC_STREAM_PTS)) {
|
||
+ PDEBUG(D_PACK, "PTS not present");
|
||
+ goto discard;
|
||
+ }
|
||
+ this_pts = (data[5] << 24) | (data[4] << 16)
|
||
+ | (data[3] << 8) | data[2];
|
||
+ this_fid = data[1] & UVC_STREAM_FID;
|
||
+
|
||
+ /* If PTS or FID has changed, start a new frame. */
|
||
+ if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
|
||
+ if (gspca_dev->last_packet_type == INTER_PACKET)
|
||
+ gspca_frame_add(gspca_dev, LAST_PACKET,
|
||
+ NULL, 0);
|
||
+ sd->last_pts = this_pts;
|
||
+ sd->last_fid = this_fid;
|
||
+ gspca_frame_add(gspca_dev, FIRST_PACKET,
|
||
+ data + 12, len - 12);
|
||
+ /* If this packet is marked as EOF, end the frame */
|
||
+ } else if (data[1] & UVC_STREAM_EOF) {
|
||
+ sd->last_pts = 0;
|
||
+ gspca_frame_add(gspca_dev, LAST_PACKET,
|
||
+ data + 12, len - 12);
|
||
+ } else {
|
||
+
|
||
+ /* Add the data from this payload */
|
||
+ gspca_frame_add(gspca_dev, INTER_PACKET,
|
||
+ data + 12, len - 12);
|
||
+ }
|
||
+
|
||
+ /* Done this payload */
|
||
+ goto scan_next;
|
||
+
|
||
+discard:
|
||
+ /* Discard data until a new frame starts. */
|
||
+ gspca_dev->last_packet_type = DISCARD_PACKET;
|
||
+
|
||
+scan_next:
|
||
+ remaining_len -= len;
|
||
+ data += len;
|
||
+ } while (remaining_len > 0);
|
||
+}
|
||
+
|
||
+/* controls */
|
||
+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 gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+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_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->contrast = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ setcontrast(gspca_dev);
|
||
+ return gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->contrast;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->autogain = val;
|
||
+
|
||
+ if (gspca_dev->streaming) {
|
||
+ if (val)
|
||
+ gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
|
||
+ else
|
||
+ gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX);
|
||
+ setautogain(gspca_dev);
|
||
+ }
|
||
+ return gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->autogain;
|
||
+ 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 gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+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_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->sharpness = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ setsharpness(gspca_dev);
|
||
+ return gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->sharpness;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->satur = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ setsatur(gspca_dev);
|
||
+ return gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->satur;
|
||
+ return 0;
|
||
+}
|
||
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->freq = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ setfreq(gspca_dev);
|
||
+ return gspca_dev->usb_err;
|
||
+}
|
||
+
|
||
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->freq;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_querymenu(struct gspca_dev *gspca_dev,
|
||
+ struct v4l2_querymenu *menu)
|
||
+{
|
||
+ switch (menu->id) {
|
||
+ case V4L2_CID_POWER_LINE_FREQUENCY:
|
||
+ switch (menu->index) {
|
||
+ case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
|
||
+ strcpy((char *) menu->name, "NoFliker");
|
||
+ return 0;
|
||
+ case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
|
||
+ strcpy((char *) menu->name, "50 Hz");
|
||
+ return 0;
|
||
+ case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
|
||
+ strcpy((char *) menu->name, "60 Hz");
|
||
+ return 0;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ return -EINVAL;
|
||
+}
|
||
+
|
||
+/* sub-driver description */
|
||
+static const struct sd_desc sd_desc = {
|
||
+ .name = MODULE_NAME,
|
||
+ .ctrls = sd_ctrls,
|
||
+ .nctrls = ARRAY_SIZE(sd_ctrls),
|
||
+ .config = sd_config,
|
||
+ .init = sd_init,
|
||
+ .start = sd_start,
|
||
+ .stopN = sd_stopN,
|
||
+ .pkt_scan = sd_pkt_scan,
|
||
+ .querymenu = sd_querymenu,
|
||
+};
|
||
+
|
||
+/* -- module initialisation -- */
|
||
+static const __devinitdata struct usb_device_id device_table[] = {
|
||
+ {USB_DEVICE(0x06f8, 0x3003)},
|
||
+ {}
|
||
+};
|
||
+
|
||
+MODULE_DEVICE_TABLE(usb, device_table);
|
||
+
|
||
+/* -- 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/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
|
||
index 4706a82..0c87c34 100644
|
||
--- a/drivers/media/video/gspca/pac207.c
|
||
+++ b/drivers/media/video/gspca/pac207.c
|
||
@@ -25,6 +25,7 @@
|
||
|
||
#define MODULE_NAME "pac207"
|
||
|
||
+#include <linux/input.h>
|
||
#include "gspca.h"
|
||
|
||
MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>");
|
||
@@ -77,7 +78,7 @@ static int sd_getautogain(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 struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
#define SD_BRIGHTNESS 0
|
||
{
|
||
{
|
||
@@ -495,6 +496,25 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
return 0;
|
||
}
|
||
|
||
+#ifdef CONFIG_INPUT
|
||
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data, /* interrupt packet data */
|
||
+ int len) /* interrput packet length */
|
||
+{
|
||
+ int ret = -EINVAL;
|
||
+
|
||
+ if (len == 2 && data[0] == 0x5a && data[1] == 0x5a) {
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ ret = 0;
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+#endif
|
||
+
|
||
/* sub-driver description */
|
||
static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
@@ -506,6 +526,9 @@ static const struct sd_desc sd_desc = {
|
||
.stopN = sd_stopN,
|
||
.dq_callback = pac207_do_auto_gain,
|
||
.pkt_scan = sd_pkt_scan,
|
||
+#ifdef CONFIG_INPUT
|
||
+ .int_pkt_scan = sd_int_pkt_scan,
|
||
+#endif
|
||
};
|
||
|
||
/* -- module initialisation -- */
|
||
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c
|
||
index de0b66c..7722f7a 100644
|
||
--- a/drivers/media/video/gspca/pac7302.c
|
||
+++ b/drivers/media/video/gspca/pac7302.c
|
||
@@ -4,7 +4,9 @@
|
||
*
|
||
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
|
||
*
|
||
- * Separated from Pixart PAC7311 library by M<>rton N<>meth <nm127@freemail.hu>
|
||
+ * Separated from Pixart PAC7311 library by Márton Németh
|
||
+ * Camera button input handling by Márton Németh <nm127@freemail.hu>
|
||
+ * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
|
||
*
|
||
* 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
|
||
@@ -22,33 +24,26 @@
|
||
*/
|
||
|
||
/* Some documentation about various registers as determined by trial and error.
|
||
- When the register addresses differ between the 7202 and the 7311 the 2
|
||
- different addresses are written as 7302addr/7311addr, when one of the 2
|
||
- addresses is a - sign that register description is not valid for the
|
||
- matching IC.
|
||
|
||
Register page 1:
|
||
|
||
Address Description
|
||
- -/0x08 Unknown compressor related, must always be 8 except when not
|
||
- in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
|
||
- -/0x1b Auto white balance related, bit 0 is AWB enable (inverted)
|
||
- bits 345 seem to toggle per color gains on/off (inverted)
|
||
0x78 Global control, bit 6 controls the LED (inverted)
|
||
- -/0x80 JPEG compression ratio ? Best not touched
|
||
|
||
- Register page 3/4:
|
||
+ Register page 3:
|
||
|
||
Address Description
|
||
- 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
|
||
+ 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
|
||
the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
|
||
- -/0x0f Master gain 1-245, low value = high gain
|
||
- 0x10/- Master gain 0-31
|
||
- -/0x10 Another gain 0-15, limited influence (1-2x gain I guess)
|
||
+ 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
|
||
+ 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
|
||
+ 63 -> ~27 fps, the 2 msb's must always be 1 !!
|
||
+ 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
|
||
+ 1 -> ~30 fps, 2 -> ~20 fps
|
||
+ 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time
|
||
+ 0x0f Exposure bit 8, 0-448, 448 = no exposure at all
|
||
+ 0x10 Master gain 0-31
|
||
0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
|
||
- -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
|
||
- completely disable the analog amplification block. Set to 0x68
|
||
- for max gain, 0x14 for minimal gain.
|
||
|
||
The registers are accessed in the following functions:
|
||
|
||
@@ -68,6 +63,7 @@
|
||
|
||
#define MODULE_NAME "pac7302"
|
||
|
||
+#include <linux/input.h>
|
||
#include <media/v4l2-chip-ident.h>
|
||
#include "gspca.h"
|
||
|
||
@@ -86,8 +82,8 @@ struct sd {
|
||
unsigned char red_balance;
|
||
unsigned char blue_balance;
|
||
unsigned char gain;
|
||
- unsigned char exposure;
|
||
unsigned char autogain;
|
||
+ unsigned short exposure;
|
||
__u8 hflip;
|
||
__u8 vflip;
|
||
u8 flags;
|
||
@@ -124,8 +120,7 @@ static int sd_getgain(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 struct ctrl sd_ctrls[] = {
|
||
-/* This control is pac7302 only */
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -141,7 +136,6 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_setbrightness,
|
||
.get = sd_getbrightness,
|
||
},
|
||
-/* This control is for both the 7302 and the 7311 */
|
||
{
|
||
{
|
||
.id = V4L2_CID_CONTRAST,
|
||
@@ -157,7 +151,6 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_setcontrast,
|
||
.get = sd_getcontrast,
|
||
},
|
||
-/* This control is pac7302 only */
|
||
{
|
||
{
|
||
.id = V4L2_CID_SATURATION,
|
||
@@ -215,7 +208,6 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_setbluebalance,
|
||
.get = sd_getbluebalance,
|
||
},
|
||
-/* All controls below are for both the 7302 and the 7311 */
|
||
{
|
||
{
|
||
.id = V4L2_CID_GAIN,
|
||
@@ -238,11 +230,10 @@ static struct ctrl sd_ctrls[] = {
|
||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||
.name = "Exposure",
|
||
.minimum = 0,
|
||
-#define EXPOSURE_MAX 255
|
||
- .maximum = EXPOSURE_MAX,
|
||
+ .maximum = 1023,
|
||
.step = 1,
|
||
-#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
|
||
-#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
|
||
+#define EXPOSURE_DEF 66 /* 33 ms / 30 fps */
|
||
+#define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
|
||
.default_value = EXPOSURE_DEF,
|
||
},
|
||
.set = sd_setexposure,
|
||
@@ -301,7 +292,6 @@ static const struct v4l2_pix_format vga_mode[] = {
|
||
};
|
||
|
||
#define LOAD_PAGE3 255
|
||
-#define LOAD_PAGE4 254
|
||
#define END_OF_SEQUENCE 0
|
||
|
||
/* pac 7302 */
|
||
@@ -379,7 +369,7 @@ static const __u8 start_7302[] = {
|
||
#define SKIP 0xaa
|
||
/* page 3 - the value SKIP says skip the index - see reg_w_page() */
|
||
static const __u8 page3_7302[] = {
|
||
- 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
|
||
+ 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
|
||
0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
|
||
0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
|
||
@@ -388,7 +378,7 @@ static const __u8 page3_7302[] = {
|
||
0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
|
||
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
|
||
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
|
||
+ SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
|
||
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
@@ -401,12 +391,14 @@ static const __u8 page3_7302[] = {
|
||
0x00
|
||
};
|
||
|
||
-static int reg_w_buf(struct gspca_dev *gspca_dev,
|
||
+static void reg_w_buf(struct gspca_dev *gspca_dev,
|
||
__u8 index,
|
||
const char *buffer, int len)
|
||
{
|
||
int ret;
|
||
|
||
+ if (gspca_dev->usb_err < 0)
|
||
+ return;
|
||
memcpy(gspca_dev->usb_buf, buffer, len);
|
||
ret = usb_control_msg(gspca_dev->dev,
|
||
usb_sndctrlpipe(gspca_dev->dev, 0),
|
||
@@ -415,20 +407,44 @@ static int reg_w_buf(struct gspca_dev *gspca_dev,
|
||
0, /* value */
|
||
index, gspca_dev->usb_buf, len,
|
||
500);
|
||
- if (ret < 0)
|
||
+ if (ret < 0) {
|
||
PDEBUG(D_ERR, "reg_w_buf(): "
|
||
"Failed to write registers to index 0x%x, error %i",
|
||
index, ret);
|
||
- return ret;
|
||
+ gspca_dev->usb_err = ret;
|
||
+ }
|
||
}
|
||
|
||
+#if 0 /* not used */
|
||
+static __u8 reg_r(struct gspca_dev *gspca_dev,
|
||
+ __u8 index)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = usb_control_msg(gspca_dev->dev,
|
||
+ usb_rcvctrlpipe(gspca_dev->dev, 0),
|
||
+ 0, /* request */
|
||
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||
+ 0, /* value */
|
||
+ index, gspca_dev->usb_buf, 1,
|
||
+ 500);
|
||
+ if (ret < 0)
|
||
+ PDEBUG(D_ERR, "reg_r(): "
|
||
+ "Failed to read register from index 0x%x, error %i",
|
||
+ index, ret);
|
||
+
|
||
+ return gspca_dev->usb_buf[0];
|
||
+}
|
||
+#endif
|
||
|
||
-static int reg_w(struct gspca_dev *gspca_dev,
|
||
+static void reg_w(struct gspca_dev *gspca_dev,
|
||
__u8 index,
|
||
__u8 value)
|
||
{
|
||
int ret;
|
||
|
||
+ if (gspca_dev->usb_err < 0)
|
||
+ return;
|
||
gspca_dev->usb_buf[0] = value;
|
||
ret = usb_control_msg(gspca_dev->dev,
|
||
usb_sndctrlpipe(gspca_dev->dev, 0),
|
||
@@ -436,32 +452,32 @@ static int reg_w(struct gspca_dev *gspca_dev,
|
||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||
0, index, gspca_dev->usb_buf, 1,
|
||
500);
|
||
- if (ret < 0)
|
||
+ if (ret < 0) {
|
||
PDEBUG(D_ERR, "reg_w(): "
|
||
"Failed to write register to index 0x%x, value 0x%x, error %i",
|
||
index, value, ret);
|
||
- return ret;
|
||
+ gspca_dev->usb_err = ret;
|
||
+ }
|
||
}
|
||
|
||
-static int reg_w_seq(struct gspca_dev *gspca_dev,
|
||
+static void reg_w_seq(struct gspca_dev *gspca_dev,
|
||
const __u8 *seq, int len)
|
||
{
|
||
- int ret = 0;
|
||
while (--len >= 0) {
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, seq[0], seq[1]);
|
||
+ reg_w(gspca_dev, seq[0], seq[1]);
|
||
seq += 2;
|
||
}
|
||
- return ret;
|
||
}
|
||
|
||
/* load the beginning of a page */
|
||
-static int reg_w_page(struct gspca_dev *gspca_dev,
|
||
+static void reg_w_page(struct gspca_dev *gspca_dev,
|
||
const __u8 *page, int len)
|
||
{
|
||
int index;
|
||
int ret = 0;
|
||
|
||
+ if (gspca_dev->usb_err < 0)
|
||
+ return;
|
||
for (index = 0; index < len; index++) {
|
||
if (page[index] == SKIP) /* skip this index */
|
||
continue;
|
||
@@ -477,56 +493,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev,
|
||
"Failed to write register to index 0x%x, "
|
||
"value 0x%x, error %i",
|
||
index, page[index], ret);
|
||
+ gspca_dev->usb_err = ret;
|
||
break;
|
||
}
|
||
}
|
||
- return ret;
|
||
}
|
||
|
||
/* output a variable sequence */
|
||
-static int reg_w_var(struct gspca_dev *gspca_dev,
|
||
+static void reg_w_var(struct gspca_dev *gspca_dev,
|
||
const __u8 *seq,
|
||
- const __u8 *page3, unsigned int page3_len,
|
||
- const __u8 *page4, unsigned int page4_len)
|
||
+ const __u8 *page3, unsigned int page3_len)
|
||
{
|
||
int index, len;
|
||
- int ret = 0;
|
||
|
||
for (;;) {
|
||
index = *seq++;
|
||
len = *seq++;
|
||
switch (len) {
|
||
case END_OF_SEQUENCE:
|
||
- return ret;
|
||
- case LOAD_PAGE4:
|
||
- ret = reg_w_page(gspca_dev, page4, page4_len);
|
||
- break;
|
||
+ return;
|
||
case LOAD_PAGE3:
|
||
- ret = reg_w_page(gspca_dev, page3, page3_len);
|
||
+ reg_w_page(gspca_dev, page3, page3_len);
|
||
break;
|
||
default:
|
||
if (len > USB_BUF_SZ) {
|
||
PDEBUG(D_ERR|D_STREAM,
|
||
"Incorrect variable sequence");
|
||
- return -EINVAL;
|
||
+ return;
|
||
}
|
||
while (len > 0) {
|
||
if (len < 8) {
|
||
- ret = reg_w_buf(gspca_dev,
|
||
+ reg_w_buf(gspca_dev,
|
||
index, seq, len);
|
||
- if (ret < 0)
|
||
- return ret;
|
||
seq += len;
|
||
break;
|
||
}
|
||
- ret = reg_w_buf(gspca_dev, index, seq, 8);
|
||
+ reg_w_buf(gspca_dev, index, seq, 8);
|
||
seq += 8;
|
||
index += 8;
|
||
len -= 8;
|
||
}
|
||
}
|
||
- if (ret < 0)
|
||
- return ret;
|
||
}
|
||
/* not reached */
|
||
}
|
||
@@ -560,11 +567,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
}
|
||
|
||
/* This function is used by pac7302 only */
|
||
-static int setbrightcont(struct gspca_dev *gspca_dev)
|
||
+static void setbrightcont(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
int i, v;
|
||
- int ret;
|
||
static const __u8 max[10] =
|
||
{0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
|
||
0xd4, 0xec};
|
||
@@ -572,7 +578,7 @@ static int setbrightcont(struct gspca_dev *gspca_dev)
|
||
{0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
|
||
0x11, 0x0b};
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
for (i = 0; i < 10; i++) {
|
||
v = max[i];
|
||
v += (sd->brightness - BRIGHTNESS_MAX)
|
||
@@ -582,136 +588,121 @@ static int setbrightcont(struct gspca_dev *gspca_dev)
|
||
v = 0;
|
||
else if (v > 0xff)
|
||
v = 0xff;
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xa2 + i, v);
|
||
+ reg_w(gspca_dev, 0xa2 + i, v);
|
||
}
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xdc, 0x01);
|
||
- return ret;
|
||
+ reg_w(gspca_dev, 0xdc, 0x01);
|
||
}
|
||
|
||
/* This function is used by pac7302 only */
|
||
-static int setcolors(struct gspca_dev *gspca_dev)
|
||
+static void setcolors(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
int i, v;
|
||
- int ret;
|
||
static const int a[9] =
|
||
{217, -212, 0, -101, 170, -67, -38, -315, 355};
|
||
static const int b[9] =
|
||
{19, 106, 0, 19, 106, 1, 19, 106, 1};
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x11, 0x01);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
|
||
+ reg_w(gspca_dev, 0x11, 0x01);
|
||
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
for (i = 0; i < 9; i++) {
|
||
v = a[i] * sd->colors / COLOR_MAX + b[i];
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
|
||
+ reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
|
||
+ reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
|
||
}
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xdc, 0x01);
|
||
+ reg_w(gspca_dev, 0xdc, 0x01);
|
||
PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
|
||
- return ret;
|
||
}
|
||
|
||
-static int setwhitebalance(struct gspca_dev *gspca_dev)
|
||
+static void setwhitebalance(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xc6, sd->white_balance);
|
||
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
+ reg_w(gspca_dev, 0xc6, sd->white_balance);
|
||
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xdc, 0x01);
|
||
+ reg_w(gspca_dev, 0xdc, 0x01);
|
||
PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance);
|
||
- return ret;
|
||
}
|
||
|
||
-static int setredbalance(struct gspca_dev *gspca_dev)
|
||
+static void setredbalance(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xc5, sd->red_balance);
|
||
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
+ reg_w(gspca_dev, 0xc5, sd->red_balance);
|
||
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xdc, 0x01);
|
||
+ reg_w(gspca_dev, 0xdc, 0x01);
|
||
PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
|
||
- return ret;
|
||
}
|
||
|
||
-static int setbluebalance(struct gspca_dev *gspca_dev)
|
||
+static void setbluebalance(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xc7, sd->blue_balance);
|
||
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
+ reg_w(gspca_dev, 0xc7, sd->blue_balance);
|
||
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xdc, 0x01);
|
||
+ reg_w(gspca_dev, 0xdc, 0x01);
|
||
PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
|
||
- return ret;
|
||
}
|
||
|
||
-static int setgain(struct gspca_dev *gspca_dev)
|
||
+static void setgain(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x10, sd->gain >> 3);
|
||
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
|
||
+ reg_w(gspca_dev, 0x10, sd->gain >> 3);
|
||
|
||
/* load registers to sensor (Bit 0, auto clear) */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x11, 0x01);
|
||
- return ret;
|
||
+ reg_w(gspca_dev, 0x11, 0x01);
|
||
}
|
||
|
||
-static int setexposure(struct gspca_dev *gspca_dev)
|
||
+static void setexposure(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
- __u8 reg;
|
||
-
|
||
- /* register 2 of frame 3/4 contains the clock divider configuring the
|
||
- no fps according to the formula: 60 / reg. sd->exposure is the
|
||
- desired exposure time in ms. */
|
||
- reg = 120 * sd->exposure / 1000;
|
||
- if (reg < 2)
|
||
- reg = 2;
|
||
- else if (reg > 63)
|
||
- reg = 63;
|
||
-
|
||
- /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
|
||
- the nearest multiple of 3, except when between 6 and 12? */
|
||
- if (reg < 6 || reg > 12)
|
||
- reg = ((reg + 1) / 3) * 3;
|
||
- ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x02, reg);
|
||
+ __u8 clockdiv;
|
||
+ __u16 exposure;
|
||
+
|
||
+ /* register 2 of frame 3 contains the clock divider configuring the
|
||
+ no fps according to the formula: 90 / reg. sd->exposure is the
|
||
+ desired exposure time in 0.5 ms. */
|
||
+ clockdiv = (90 * sd->exposure + 1999) / 2000;
|
||
+
|
||
+ /* Note clockdiv = 3 also works, but when running at 30 fps, depending
|
||
+ on the scene being recorded, the camera switches to another
|
||
+ quantization table for certain JPEG blocks, and we don't know how
|
||
+ to decompress these blocks. So we cap the framerate at 15 fps */
|
||
+ if (clockdiv < 6)
|
||
+ clockdiv = 6;
|
||
+ else if (clockdiv > 63)
|
||
+ clockdiv = 63;
|
||
+
|
||
+ /* reg2 MUST be a multiple of 3, except when between 6 and 12?
|
||
+ Always round up, otherwise we cannot get the desired frametime
|
||
+ using the partial frame time exposure control */
|
||
+ if (clockdiv < 6 || clockdiv > 12)
|
||
+ clockdiv = ((clockdiv + 2) / 3) * 3;
|
||
+
|
||
+ /* frame exposure time in ms = 1000 * clockdiv / 90 ->
|
||
+ exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */
|
||
+ exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv);
|
||
+ /* 0 = use full frametime, 448 = no exposure, reverse it */
|
||
+ exposure = 448 - exposure;
|
||
+
|
||
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
|
||
+ reg_w(gspca_dev, 0x02, clockdiv);
|
||
+ reg_w(gspca_dev, 0x0e, exposure & 0xff);
|
||
+ reg_w(gspca_dev, 0x0f, exposure >> 8);
|
||
|
||
/* load registers to sensor (Bit 0, auto clear) */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x11, 0x01);
|
||
- return ret;
|
||
+ reg_w(gspca_dev, 0x11, 0x01);
|
||
}
|
||
|
||
-static int sethvflip(struct gspca_dev *gspca_dev)
|
||
+static void sethvflip(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
u8 data, hflip, vflip;
|
||
|
||
hflip = sd->hflip;
|
||
@@ -721,48 +712,37 @@ static int sethvflip(struct gspca_dev *gspca_dev)
|
||
if (sd->flags & FL_VFLIP)
|
||
vflip = !vflip;
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
|
||
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
|
||
data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x21, data);
|
||
+ reg_w(gspca_dev, 0x21, data);
|
||
+
|
||
/* load registers to sensor (Bit 0, auto clear) */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x11, 0x01);
|
||
- return ret;
|
||
+ reg_w(gspca_dev, 0x11, 0x01);
|
||
}
|
||
|
||
/* this function is called at probe and resume time for pac7302 */
|
||
static int sd_init(struct gspca_dev *gspca_dev)
|
||
{
|
||
- return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
|
||
+ reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_start(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret = 0;
|
||
|
||
sd->sof_read = 0;
|
||
|
||
- ret = reg_w_var(gspca_dev, start_7302,
|
||
- page3_7302, sizeof(page3_7302),
|
||
- NULL, 0);
|
||
- if (0 <= ret)
|
||
- ret = setbrightcont(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = setcolors(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = setwhitebalance(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = setredbalance(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = setbluebalance(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = setgain(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = setexposure(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = sethvflip(gspca_dev);
|
||
+ reg_w_var(gspca_dev, start_7302,
|
||
+ page3_7302, sizeof(page3_7302));
|
||
+ setbrightcont(gspca_dev);
|
||
+ setcolors(gspca_dev);
|
||
+ setwhitebalance(gspca_dev);
|
||
+ setredbalance(gspca_dev);
|
||
+ setbluebalance(gspca_dev);
|
||
+ setgain(gspca_dev);
|
||
+ setexposure(gspca_dev);
|
||
+ sethvflip(gspca_dev);
|
||
|
||
/* only resolution 640x480 is supported for pac7302 */
|
||
|
||
@@ -771,34 +751,27 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
atomic_set(&sd->avg_lum, -1);
|
||
|
||
/* start stream */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xff, 0x01);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x78, 0x01);
|
||
+ reg_w(gspca_dev, 0xff, 0x01);
|
||
+ reg_w(gspca_dev, 0x78, 0x01);
|
||
|
||
- return ret;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||
{
|
||
- int ret;
|
||
|
||
/* stop stream */
|
||
- ret = reg_w(gspca_dev, 0xff, 0x01);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x78, 0x00);
|
||
+ reg_w(gspca_dev, 0xff, 0x01);
|
||
+ reg_w(gspca_dev, 0x78, 0x00);
|
||
}
|
||
|
||
/* called on streamoff with alt 0 and on disconnect for pac7302 */
|
||
static void sd_stop0(struct gspca_dev *gspca_dev)
|
||
{
|
||
- int ret;
|
||
-
|
||
if (!gspca_dev->present)
|
||
return;
|
||
- ret = reg_w(gspca_dev, 0xff, 0x01);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x78, 0x40);
|
||
+ reg_w(gspca_dev, 0xff, 0x01);
|
||
+ reg_w(gspca_dev, 0x78, 0x40);
|
||
}
|
||
|
||
/* Include pac common sof detection functions */
|
||
@@ -808,22 +781,13 @@ static void do_autogain(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
int avg_lum = atomic_read(&sd->avg_lum);
|
||
- int desired_lum, deadzone;
|
||
+ int desired_lum;
|
||
+ const int deadzone = 30;
|
||
|
||
if (avg_lum == -1)
|
||
return;
|
||
|
||
- desired_lum = 270 + sd->brightness * 4;
|
||
- /* Hack hack, with the 7202 the first exposure step is
|
||
- pretty large, so if we're about to make the first
|
||
- exposure increase make the deadzone large to avoid
|
||
- oscilating */
|
||
- if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
|
||
- sd->exposure > EXPOSURE_DEF &&
|
||
- sd->exposure < 42)
|
||
- deadzone = 90;
|
||
- else
|
||
- deadzone = 30;
|
||
+ desired_lum = 270 + sd->brightness;
|
||
|
||
if (sd->autogain_ignore_frames > 0)
|
||
sd->autogain_ignore_frames--;
|
||
@@ -947,7 +911,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->brightness = val;
|
||
if (gspca_dev->streaming)
|
||
setbrightcont(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -966,7 +930,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||
if (gspca_dev->streaming) {
|
||
setbrightcont(gspca_dev);
|
||
}
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -984,7 +948,7 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->colors = val;
|
||
if (gspca_dev->streaming)
|
||
setcolors(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -998,14 +962,11 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
|
||
static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret = 0;
|
||
|
||
sd->white_balance = val;
|
||
if (gspca_dev->streaming)
|
||
- ret = setwhitebalance(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = 0;
|
||
- return ret;
|
||
+ setwhitebalance(gspca_dev);
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -1019,14 +980,11 @@ static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
|
||
static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret = 0;
|
||
|
||
sd->red_balance = val;
|
||
if (gspca_dev->streaming)
|
||
- ret = setredbalance(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = 0;
|
||
- return ret;
|
||
+ setredbalance(gspca_dev);
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -1040,14 +998,11 @@ static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
|
||
static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret = 0;
|
||
|
||
sd->blue_balance = val;
|
||
if (gspca_dev->streaming)
|
||
- ret = setbluebalance(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = 0;
|
||
- return ret;
|
||
+ setbluebalance(gspca_dev);
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -1065,7 +1020,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->gain = val;
|
||
if (gspca_dev->streaming)
|
||
setgain(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -1083,7 +1038,7 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->exposure = val;
|
||
if (gspca_dev->streaming)
|
||
setexposure(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -1114,7 +1069,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
|
||
}
|
||
}
|
||
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -1132,7 +1087,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->hflip = val;
|
||
if (gspca_dev->streaming)
|
||
sethvflip(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -1150,7 +1105,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->vflip = val;
|
||
if (gspca_dev->streaming)
|
||
sethvflip(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -1165,7 +1120,6 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
|
||
static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
|
||
struct v4l2_dbg_register *reg)
|
||
{
|
||
- int ret = -EINVAL;
|
||
__u8 index;
|
||
__u8 value;
|
||
|
||
@@ -1185,14 +1139,12 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
|
||
/* Note that there shall be no access to other page
|
||
by any other function between the page swith and
|
||
the actual register write */
|
||
- ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, index, value);
|
||
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
|
||
+ reg_w(gspca_dev, index, value);
|
||
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xdc, 0x01);
|
||
+ reg_w(gspca_dev, 0xdc, 0x01);
|
||
}
|
||
- return ret;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_chip_ident(struct gspca_dev *gspca_dev,
|
||
@@ -1210,8 +1162,39 @@ static int sd_chip_ident(struct gspca_dev *gspca_dev,
|
||
}
|
||
#endif
|
||
|
||
+#ifdef CONFIG_INPUT
|
||
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data, /* interrupt packet data */
|
||
+ int len) /* interrput packet length */
|
||
+{
|
||
+ int ret = -EINVAL;
|
||
+ u8 data0, data1;
|
||
+
|
||
+ if (len == 2) {
|
||
+ data0 = data[0];
|
||
+ data1 = data[1];
|
||
+ if ((data0 == 0x00 && data1 == 0x11) ||
|
||
+ (data0 == 0x22 && data1 == 0x33) ||
|
||
+ (data0 == 0x44 && data1 == 0x55) ||
|
||
+ (data0 == 0x66 && data1 == 0x77) ||
|
||
+ (data0 == 0x88 && data1 == 0x99) ||
|
||
+ (data0 == 0xaa && data1 == 0xbb) ||
|
||
+ (data0 == 0xcc && data1 == 0xdd) ||
|
||
+ (data0 == 0xee && data1 == 0xff)) {
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ ret = 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+#endif
|
||
+
|
||
/* sub-driver description for pac7302 */
|
||
-static struct sd_desc sd_desc = {
|
||
+static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls,
|
||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||
@@ -1226,6 +1209,9 @@ static struct sd_desc sd_desc = {
|
||
.set_register = sd_dbg_s_register,
|
||
.get_chip_ident = sd_chip_ident,
|
||
#endif
|
||
+#ifdef CONFIG_INPUT
|
||
+ .int_pkt_scan = sd_int_pkt_scan,
|
||
+#endif
|
||
};
|
||
|
||
/* -- module initialisation -- */
|
||
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
|
||
index 42cfcdf..322140d 100644
|
||
--- a/drivers/media/video/gspca/pac7311.c
|
||
+++ b/drivers/media/video/gspca/pac7311.c
|
||
@@ -51,6 +51,7 @@
|
||
|
||
#define MODULE_NAME "pac7311"
|
||
|
||
+#include <linux/input.h>
|
||
#include "gspca.h"
|
||
|
||
MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
|
||
@@ -88,7 +89,7 @@ static int sd_getgain(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 struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
/* This control is for both the 7302 and the 7311 */
|
||
{
|
||
{
|
||
@@ -200,7 +201,6 @@ static const struct v4l2_pix_format vga_mode[] = {
|
||
.priv = 0},
|
||
};
|
||
|
||
-#define LOAD_PAGE3 255
|
||
#define LOAD_PAGE4 254
|
||
#define END_OF_SEQUENCE 0
|
||
|
||
@@ -259,12 +259,14 @@ static const __u8 page4_7311[] = {
|
||
0x23, 0x28, 0x04, 0x11, 0x00, 0x00
|
||
};
|
||
|
||
-static int reg_w_buf(struct gspca_dev *gspca_dev,
|
||
+static void reg_w_buf(struct gspca_dev *gspca_dev,
|
||
__u8 index,
|
||
const char *buffer, int len)
|
||
{
|
||
int ret;
|
||
|
||
+ if (gspca_dev->usb_err < 0)
|
||
+ return;
|
||
memcpy(gspca_dev->usb_buf, buffer, len);
|
||
ret = usb_control_msg(gspca_dev->dev,
|
||
usb_sndctrlpipe(gspca_dev->dev, 0),
|
||
@@ -273,20 +275,44 @@ static int reg_w_buf(struct gspca_dev *gspca_dev,
|
||
0, /* value */
|
||
index, gspca_dev->usb_buf, len,
|
||
500);
|
||
- if (ret < 0)
|
||
+ if (ret < 0) {
|
||
PDEBUG(D_ERR, "reg_w_buf(): "
|
||
"Failed to write registers to index 0x%x, error %i",
|
||
index, ret);
|
||
- return ret;
|
||
+ gspca_dev->usb_err = ret;
|
||
+ }
|
||
}
|
||
|
||
+#if 0 /* not used */
|
||
+static __u8 reg_r(struct gspca_dev *gspca_dev,
|
||
+ __u8 index)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = usb_control_msg(gspca_dev->dev,
|
||
+ usb_rcvctrlpipe(gspca_dev->dev, 0),
|
||
+ 0, /* request */
|
||
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||
+ 0, /* value */
|
||
+ index, gspca_dev->usb_buf, 1,
|
||
+ 500);
|
||
+ if (ret < 0)
|
||
+ PDEBUG(D_ERR, "reg_r(): "
|
||
+ "Failed to read register from index 0x%x, error %i",
|
||
+ index, ret);
|
||
|
||
-static int reg_w(struct gspca_dev *gspca_dev,
|
||
+ return gspca_dev->usb_buf[0];
|
||
+}
|
||
+#endif
|
||
+
|
||
+static void reg_w(struct gspca_dev *gspca_dev,
|
||
__u8 index,
|
||
__u8 value)
|
||
{
|
||
int ret;
|
||
|
||
+ if (gspca_dev->usb_err < 0)
|
||
+ return;
|
||
gspca_dev->usb_buf[0] = value;
|
||
ret = usb_control_msg(gspca_dev->dev,
|
||
usb_sndctrlpipe(gspca_dev->dev, 0),
|
||
@@ -294,32 +320,32 @@ static int reg_w(struct gspca_dev *gspca_dev,
|
||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||
0, index, gspca_dev->usb_buf, 1,
|
||
500);
|
||
- if (ret < 0)
|
||
+ if (ret < 0) {
|
||
PDEBUG(D_ERR, "reg_w(): "
|
||
"Failed to write register to index 0x%x, value 0x%x, error %i",
|
||
index, value, ret);
|
||
- return ret;
|
||
+ gspca_dev->usb_err = ret;
|
||
+ }
|
||
}
|
||
|
||
-static int reg_w_seq(struct gspca_dev *gspca_dev,
|
||
+static void reg_w_seq(struct gspca_dev *gspca_dev,
|
||
const __u8 *seq, int len)
|
||
{
|
||
- int ret = 0;
|
||
while (--len >= 0) {
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, seq[0], seq[1]);
|
||
+ reg_w(gspca_dev, seq[0], seq[1]);
|
||
seq += 2;
|
||
}
|
||
- return ret;
|
||
}
|
||
|
||
/* load the beginning of a page */
|
||
-static int reg_w_page(struct gspca_dev *gspca_dev,
|
||
+static void reg_w_page(struct gspca_dev *gspca_dev,
|
||
const __u8 *page, int len)
|
||
{
|
||
int index;
|
||
int ret = 0;
|
||
|
||
+ if (gspca_dev->usb_err < 0)
|
||
+ return;
|
||
for (index = 0; index < len; index++) {
|
||
if (page[index] == SKIP) /* skip this index */
|
||
continue;
|
||
@@ -335,56 +361,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev,
|
||
"Failed to write register to index 0x%x, "
|
||
"value 0x%x, error %i",
|
||
index, page[index], ret);
|
||
+ gspca_dev->usb_err = ret;
|
||
break;
|
||
}
|
||
}
|
||
- return ret;
|
||
}
|
||
|
||
/* output a variable sequence */
|
||
-static int reg_w_var(struct gspca_dev *gspca_dev,
|
||
+static void reg_w_var(struct gspca_dev *gspca_dev,
|
||
const __u8 *seq,
|
||
- const __u8 *page3, unsigned int page3_len,
|
||
const __u8 *page4, unsigned int page4_len)
|
||
{
|
||
int index, len;
|
||
- int ret = 0;
|
||
|
||
for (;;) {
|
||
index = *seq++;
|
||
len = *seq++;
|
||
switch (len) {
|
||
case END_OF_SEQUENCE:
|
||
- return ret;
|
||
+ return;
|
||
case LOAD_PAGE4:
|
||
- ret = reg_w_page(gspca_dev, page4, page4_len);
|
||
- break;
|
||
- case LOAD_PAGE3:
|
||
- ret = reg_w_page(gspca_dev, page3, page3_len);
|
||
+ reg_w_page(gspca_dev, page4, page4_len);
|
||
break;
|
||
default:
|
||
if (len > USB_BUF_SZ) {
|
||
PDEBUG(D_ERR|D_STREAM,
|
||
"Incorrect variable sequence");
|
||
- return -EINVAL;
|
||
+ return;
|
||
}
|
||
while (len > 0) {
|
||
if (len < 8) {
|
||
- ret = reg_w_buf(gspca_dev,
|
||
+ reg_w_buf(gspca_dev,
|
||
index, seq, len);
|
||
- if (ret < 0)
|
||
- return ret;
|
||
seq += len;
|
||
break;
|
||
}
|
||
- ret = reg_w_buf(gspca_dev, index, seq, 8);
|
||
+ reg_w_buf(gspca_dev, index, seq, 8);
|
||
seq += 8;
|
||
index += 8;
|
||
len -= 8;
|
||
}
|
||
}
|
||
- if (ret < 0)
|
||
- return ret;
|
||
}
|
||
/* not reached */
|
||
}
|
||
@@ -412,46 +429,36 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
}
|
||
|
||
/* This function is used by pac7311 only */
|
||
-static int setcontrast(struct gspca_dev *gspca_dev)
|
||
+static void setcontrast(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x04);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4);
|
||
+ reg_w(gspca_dev, 0xff, 0x04);
|
||
+ reg_w(gspca_dev, 0x10, sd->contrast >> 4);
|
||
/* load registers to sensor (Bit 0, auto clear) */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x11, 0x01);
|
||
- return ret;
|
||
+ reg_w(gspca_dev, 0x11, 0x01);
|
||
}
|
||
|
||
-static int setgain(struct gspca_dev *gspca_dev)
|
||
+static void setgain(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
int gain = GAIN_MAX - sd->gain;
|
||
- int ret;
|
||
|
||
if (gain < 1)
|
||
gain = 1;
|
||
else if (gain > 245)
|
||
gain = 245;
|
||
- ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x0e, 0x00);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x0f, gain);
|
||
+ reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||
+ reg_w(gspca_dev, 0x0e, 0x00);
|
||
+ reg_w(gspca_dev, 0x0f, gain);
|
||
|
||
/* load registers to sensor (Bit 0, auto clear) */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x11, 0x01);
|
||
- return ret;
|
||
+ reg_w(gspca_dev, 0x11, 0x01);
|
||
}
|
||
|
||
-static int setexposure(struct gspca_dev *gspca_dev)
|
||
+static void setexposure(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
__u8 reg;
|
||
|
||
/* register 2 of frame 3/4 contains the clock divider configuring the
|
||
@@ -463,94 +470,72 @@ static int setexposure(struct gspca_dev *gspca_dev)
|
||
else if (reg > 63)
|
||
reg = 63;
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x02, reg);
|
||
+ reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||
+ reg_w(gspca_dev, 0x02, reg);
|
||
+
|
||
/* Page 1 register 8 must always be 0x08 except when not in
|
||
640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xff, 0x01);
|
||
+ reg_w(gspca_dev, 0xff, 0x01);
|
||
if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
|
||
reg <= 3) {
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x08, 0x09);
|
||
+ reg_w(gspca_dev, 0x08, 0x09);
|
||
} else {
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x08, 0x08);
|
||
+ reg_w(gspca_dev, 0x08, 0x08);
|
||
}
|
||
|
||
/* load registers to sensor (Bit 0, auto clear) */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x11, 0x01);
|
||
- return ret;
|
||
+ reg_w(gspca_dev, 0x11, 0x01);
|
||
}
|
||
|
||
-static int sethvflip(struct gspca_dev *gspca_dev)
|
||
+static void sethvflip(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
__u8 data;
|
||
|
||
- ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||
+ reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||
data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x21, data);
|
||
+ reg_w(gspca_dev, 0x21, data);
|
||
+
|
||
/* load registers to sensor (Bit 0, auto clear) */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x11, 0x01);
|
||
- return ret;
|
||
+ reg_w(gspca_dev, 0x11, 0x01);
|
||
}
|
||
|
||
/* this function is called at probe and resume time for pac7311 */
|
||
static int sd_init(struct gspca_dev *gspca_dev)
|
||
{
|
||
- return reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
|
||
+ reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_start(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int ret;
|
||
|
||
sd->sof_read = 0;
|
||
|
||
- ret = reg_w_var(gspca_dev, start_7311,
|
||
- NULL, 0,
|
||
+ reg_w_var(gspca_dev, start_7311,
|
||
page4_7311, sizeof(page4_7311));
|
||
- if (0 <= ret)
|
||
- ret = setcontrast(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = setgain(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = setexposure(gspca_dev);
|
||
- if (0 <= ret)
|
||
- ret = sethvflip(gspca_dev);
|
||
+ setcontrast(gspca_dev);
|
||
+ setgain(gspca_dev);
|
||
+ setexposure(gspca_dev);
|
||
+ sethvflip(gspca_dev);
|
||
|
||
/* set correct resolution */
|
||
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
|
||
case 2: /* 160x120 pac7311 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xff, 0x01);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x17, 0x20);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x87, 0x10);
|
||
+ reg_w(gspca_dev, 0xff, 0x01);
|
||
+ reg_w(gspca_dev, 0x17, 0x20);
|
||
+ reg_w(gspca_dev, 0x87, 0x10);
|
||
break;
|
||
case 1: /* 320x240 pac7311 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xff, 0x01);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x17, 0x30);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x87, 0x11);
|
||
+ reg_w(gspca_dev, 0xff, 0x01);
|
||
+ reg_w(gspca_dev, 0x17, 0x30);
|
||
+ reg_w(gspca_dev, 0x87, 0x11);
|
||
break;
|
||
case 0: /* 640x480 */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xff, 0x01);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x17, 0x00);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x87, 0x12);
|
||
+ reg_w(gspca_dev, 0xff, 0x01);
|
||
+ reg_w(gspca_dev, 0x17, 0x00);
|
||
+ reg_w(gspca_dev, 0x87, 0x12);
|
||
break;
|
||
}
|
||
|
||
@@ -559,37 +544,24 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
atomic_set(&sd->avg_lum, -1);
|
||
|
||
/* start stream */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xff, 0x01);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x78, 0x05);
|
||
+ reg_w(gspca_dev, 0xff, 0x01);
|
||
+ reg_w(gspca_dev, 0x78, 0x05);
|
||
|
||
- return ret;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||
{
|
||
- int ret;
|
||
-
|
||
- ret = reg_w(gspca_dev, 0xff, 0x04);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x27, 0x80);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x28, 0xca);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x29, 0x53);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x2a, 0x0e);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0xff, 0x01);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x3e, 0x20);
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
|
||
- if (0 <= ret)
|
||
- ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
|
||
+ reg_w(gspca_dev, 0xff, 0x04);
|
||
+ reg_w(gspca_dev, 0x27, 0x80);
|
||
+ reg_w(gspca_dev, 0x28, 0xca);
|
||
+ reg_w(gspca_dev, 0x29, 0x53);
|
||
+ reg_w(gspca_dev, 0x2a, 0x0e);
|
||
+ reg_w(gspca_dev, 0xff, 0x01);
|
||
+ reg_w(gspca_dev, 0x3e, 0x20);
|
||
+ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
|
||
+ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
|
||
+ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
|
||
}
|
||
|
||
/* called on streamoff with alt 0 and on disconnect for 7311 */
|
||
@@ -734,7 +706,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||
if (gspca_dev->streaming) {
|
||
setcontrast(gspca_dev);
|
||
}
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -752,7 +724,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->gain = val;
|
||
if (gspca_dev->streaming)
|
||
setgain(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -770,7 +742,7 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->exposure = val;
|
||
if (gspca_dev->streaming)
|
||
setexposure(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -801,7 +773,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
|
||
}
|
||
}
|
||
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -819,7 +791,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->hflip = val;
|
||
if (gspca_dev->streaming)
|
||
sethvflip(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -837,7 +809,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
|
||
sd->vflip = val;
|
||
if (gspca_dev->streaming)
|
||
sethvflip(gspca_dev);
|
||
- return 0;
|
||
+ return gspca_dev->usb_err;
|
||
}
|
||
|
||
static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
|
||
@@ -848,8 +820,39 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
|
||
return 0;
|
||
}
|
||
|
||
+#ifdef CONFIG_INPUT
|
||
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data, /* interrupt packet data */
|
||
+ int len) /* interrupt packet length */
|
||
+{
|
||
+ int ret = -EINVAL;
|
||
+ u8 data0, data1;
|
||
+
|
||
+ if (len == 2) {
|
||
+ data0 = data[0];
|
||
+ data1 = data[1];
|
||
+ if ((data0 == 0x00 && data1 == 0x11) ||
|
||
+ (data0 == 0x22 && data1 == 0x33) ||
|
||
+ (data0 == 0x44 && data1 == 0x55) ||
|
||
+ (data0 == 0x66 && data1 == 0x77) ||
|
||
+ (data0 == 0x88 && data1 == 0x99) ||
|
||
+ (data0 == 0xaa && data1 == 0xbb) ||
|
||
+ (data0 == 0xcc && data1 == 0xdd) ||
|
||
+ (data0 == 0xee && data1 == 0xff)) {
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ ret = 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+#endif
|
||
+
|
||
/* sub-driver description for pac7311 */
|
||
-static struct sd_desc sd_desc = {
|
||
+static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls,
|
||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||
@@ -860,6 +863,9 @@ static struct sd_desc sd_desc = {
|
||
.stop0 = sd_stop0,
|
||
.pkt_scan = sd_pkt_scan,
|
||
.dq_callback = do_autogain,
|
||
+#ifdef CONFIG_INPUT
|
||
+ .int_pkt_scan = sd_int_pkt_scan,
|
||
+#endif
|
||
};
|
||
|
||
/* -- module initialisation -- */
|
||
diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h
|
||
index 20f67d9..8462a7c 100644
|
||
--- a/drivers/media/video/gspca/pac_common.h
|
||
+++ b/drivers/media/video/gspca/pac_common.h
|
||
@@ -24,11 +24,10 @@
|
||
*/
|
||
|
||
/* We calculate the autogain at the end of the transfer of a frame, at this
|
||
- moment a frame with the old settings is being transmitted, and a frame is
|
||
- being captured with the old settings. So if we adjust the autogain we must
|
||
- ignore atleast the 2 next frames for the new settings to come into effect
|
||
- before doing any other adjustments */
|
||
-#define PAC_AUTOGAIN_IGNORE_FRAMES 3
|
||
+ moment a frame with the old settings is being captured and transmitted. So
|
||
+ if we adjust the gain or exposure we must ignore atleast the next frame for
|
||
+ the new settings to come into effect before doing any other adjustments. */
|
||
+#define PAC_AUTOGAIN_IGNORE_FRAMES 2
|
||
|
||
static const unsigned char pac_sof_marker[5] =
|
||
{ 0xff, 0xff, 0x00, 0xff, 0x96 };
|
||
diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c
|
||
new file mode 100644
|
||
index 0000000..dda5fd4
|
||
--- /dev/null
|
||
+++ b/drivers/media/video/gspca/sn9c2028.c
|
||
@@ -0,0 +1,757 @@
|
||
+/*
|
||
+ * SN9C2028 library
|
||
+ *
|
||
+ * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
|
||
+ *
|
||
+ * 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 "sn9c2028"
|
||
+
|
||
+#include "gspca.h"
|
||
+
|
||
+MODULE_AUTHOR("Theodore Kilgore");
|
||
+MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver");
|
||
+MODULE_LICENSE("GPL");
|
||
+
|
||
+/* specific webcam descriptor */
|
||
+struct sd {
|
||
+ struct gspca_dev gspca_dev; /* !! must be the first item */
|
||
+ u8 sof_read;
|
||
+ u16 model;
|
||
+};
|
||
+
|
||
+struct init_command {
|
||
+ unsigned char instruction[6];
|
||
+ unsigned char to_read; /* length to read. 0 means no reply requested */
|
||
+};
|
||
+
|
||
+/* V4L2 controls supported by the driver */
|
||
+static struct ctrl sd_ctrls[] = {
|
||
+};
|
||
+
|
||
+/* How to change the resolution of any of the VGA cams is unknown */
|
||
+static const struct v4l2_pix_format vga_mode[] = {
|
||
+ {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 640,
|
||
+ .sizeimage = 640 * 480 * 3 / 4,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = 0},
|
||
+};
|
||
+
|
||
+/* No way to change the resolution of the CIF cams is known */
|
||
+static const struct v4l2_pix_format cif_mode[] = {
|
||
+ {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 352,
|
||
+ .sizeimage = 352 * 288 * 3 / 4,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = 0},
|
||
+};
|
||
+
|
||
+/* the bytes to write are in gspca_dev->usb_buf */
|
||
+static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
|
||
+{
|
||
+ int rc;
|
||
+
|
||
+ PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0],
|
||
+ command[1], command[2], command[3], command[4], command[5]);
|
||
+
|
||
+ memcpy(gspca_dev->usb_buf, command, 6);
|
||
+ rc = usb_control_msg(gspca_dev->dev,
|
||
+ usb_sndctrlpipe(gspca_dev->dev, 0),
|
||
+ USB_REQ_GET_CONFIGURATION,
|
||
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||
+ 2, 0, gspca_dev->usb_buf, 6, 500);
|
||
+ if (rc < 0) {
|
||
+ PDEBUG(D_ERR, "command write [%02x] error %d",
|
||
+ gspca_dev->usb_buf[0], rc);
|
||
+ return rc;
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sn9c2028_read1(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ int rc;
|
||
+
|
||
+ rc = usb_control_msg(gspca_dev->dev,
|
||
+ usb_rcvctrlpipe(gspca_dev->dev, 0),
|
||
+ USB_REQ_GET_STATUS,
|
||
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||
+ 1, 0, gspca_dev->usb_buf, 1, 500);
|
||
+ if (rc != 1) {
|
||
+ PDEBUG(D_ERR, "read1 error %d", rc);
|
||
+ return (rc < 0) ? rc : -EIO;
|
||
+ }
|
||
+ PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
|
||
+ return gspca_dev->usb_buf[0];
|
||
+}
|
||
+
|
||
+static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
|
||
+{
|
||
+ int rc;
|
||
+ rc = usb_control_msg(gspca_dev->dev,
|
||
+ usb_rcvctrlpipe(gspca_dev->dev, 0),
|
||
+ USB_REQ_GET_STATUS,
|
||
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||
+ 4, 0, gspca_dev->usb_buf, 4, 500);
|
||
+ if (rc != 4) {
|
||
+ PDEBUG(D_ERR, "read4 error %d", rc);
|
||
+ return (rc < 0) ? rc : -EIO;
|
||
+ }
|
||
+ memcpy(reading, gspca_dev->usb_buf, 4);
|
||
+ PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0],
|
||
+ reading[1], reading[2], reading[3]);
|
||
+ return rc;
|
||
+}
|
||
+
|
||
+static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
|
||
+{
|
||
+ int i, status;
|
||
+ __u8 reading[4];
|
||
+
|
||
+ status = sn9c2028_command(gspca_dev, command);
|
||
+ if (status < 0)
|
||
+ return status;
|
||
+
|
||
+ status = -1;
|
||
+ for (i = 0; i < 256 && status < 2; i++)
|
||
+ status = sn9c2028_read1(gspca_dev);
|
||
+ if (status != 2) {
|
||
+ PDEBUG(D_ERR, "long command status read error %d", status);
|
||
+ return (status < 0) ? status : -EIO;
|
||
+ }
|
||
+
|
||
+ memset(reading, 0, 4);
|
||
+ status = sn9c2028_read4(gspca_dev, reading);
|
||
+ if (status < 0)
|
||
+ return status;
|
||
+
|
||
+ /* in general, the first byte of the response is the first byte of
|
||
+ * the command, or'ed with 8 */
|
||
+ status = sn9c2028_read1(gspca_dev);
|
||
+ if (status < 0)
|
||
+ return status;
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
|
||
+{
|
||
+ int err_code;
|
||
+
|
||
+ err_code = sn9c2028_command(gspca_dev, command);
|
||
+ if (err_code < 0)
|
||
+ return err_code;
|
||
+
|
||
+ err_code = sn9c2028_read1(gspca_dev);
|
||
+ if (err_code < 0)
|
||
+ return err_code;
|
||
+
|
||
+ return 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 = &gspca_dev->cam;
|
||
+
|
||
+ PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)",
|
||
+ id->idVendor, id->idProduct);
|
||
+
|
||
+ sd->model = id->idProduct;
|
||
+
|
||
+ switch (sd->model) {
|
||
+ case 0x7005:
|
||
+ PDEBUG(D_PROBE, "Genius Smart 300 camera");
|
||
+ break;
|
||
+ case 0x8000:
|
||
+ PDEBUG(D_PROBE, "DC31VC");
|
||
+ break;
|
||
+ case 0x8001:
|
||
+ PDEBUG(D_PROBE, "Spy camera");
|
||
+ break;
|
||
+ case 0x8003:
|
||
+ PDEBUG(D_PROBE, "CIF camera");
|
||
+ break;
|
||
+ case 0x8008:
|
||
+ PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera");
|
||
+ break;
|
||
+ case 0x800a:
|
||
+ PDEBUG(D_PROBE, "Vivitar 3350b type camera");
|
||
+ cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ switch (sd->model) {
|
||
+ case 0x8000:
|
||
+ case 0x8001:
|
||
+ case 0x8003:
|
||
+ cam->cam_mode = cif_mode;
|
||
+ cam->nmodes = ARRAY_SIZE(cif_mode);
|
||
+ break;
|
||
+ default:
|
||
+ cam->cam_mode = vga_mode;
|
||
+ cam->nmodes = ARRAY_SIZE(vga_mode);
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* this function is called at probe and resume time */
|
||
+static int sd_init(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ int status = -1;
|
||
+
|
||
+ sn9c2028_read1(gspca_dev);
|
||
+ sn9c2028_read1(gspca_dev);
|
||
+ status = sn9c2028_read1(gspca_dev);
|
||
+
|
||
+ return (status < 0) ? status : 0;
|
||
+}
|
||
+
|
||
+static int run_start_commands(struct gspca_dev *gspca_dev,
|
||
+ struct init_command *cam_commands, int n)
|
||
+{
|
||
+ int i, err_code = -1;
|
||
+
|
||
+ for (i = 0; i < n; i++) {
|
||
+ switch (cam_commands[i].to_read) {
|
||
+ case 4:
|
||
+ err_code = sn9c2028_long_command(gspca_dev,
|
||
+ cam_commands[i].instruction);
|
||
+ break;
|
||
+ case 1:
|
||
+ err_code = sn9c2028_short_command(gspca_dev,
|
||
+ cam_commands[i].instruction);
|
||
+ break;
|
||
+ case 0:
|
||
+ err_code = sn9c2028_command(gspca_dev,
|
||
+ cam_commands[i].instruction);
|
||
+ break;
|
||
+ }
|
||
+ if (err_code < 0)
|
||
+ return err_code;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int start_spy_cam(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct init_command spy_start_commands[] = {
|
||
+ {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width 352 */
|
||
+ {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
|
||
+ /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
|
||
+ {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
|
||
+ /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
|
||
+ {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
|
||
+ {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
|
||
+ {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
|
||
+ {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
|
||
+ {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
|
||
+ /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
|
||
+ {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
|
||
+ /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
|
||
+ {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
|
||
+ {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
|
||
+ {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
|
||
+ {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
|
||
+ /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
|
||
+ /* brightness or gain. 0 is default. 4 is good
|
||
+ * indoors at night with incandescent lighting */
|
||
+ {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
|
||
+ {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
|
||
+ {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
|
||
+ /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
|
||
+ {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
|
||
+ /* Camera should start to capture now. */
|
||
+ };
|
||
+
|
||
+ return run_start_commands(gspca_dev, spy_start_commands,
|
||
+ ARRAY_SIZE(spy_start_commands));
|
||
+}
|
||
+
|
||
+static int start_cif_cam(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct init_command cif_start_commands[] = {
|
||
+ {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ /* The entire sequence below seems redundant */
|
||
+ /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
|
||
+ {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
|
||
+ {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
|
||
+ {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
|
||
+ {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
|
||
+ {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
|
||
+ {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
|
||
+ /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
|
||
+ * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
|
||
+ * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
|
||
+ /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
|
||
+ * causes subsampling
|
||
+ * but not a change in the resolution setting! */
|
||
+ {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
|
||
+ /* Camera should start to capture now. */
|
||
+ };
|
||
+
|
||
+ return run_start_commands(gspca_dev, cif_start_commands,
|
||
+ ARRAY_SIZE(cif_start_commands));
|
||
+}
|
||
+
|
||
+static int start_ms350_cam(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct init_command ms350_start_commands[] = {
|
||
+ {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
|
||
+ {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width */
|
||
+ {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
|
||
+ {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
|
||
+ {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
|
||
+ {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
|
||
+ {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
|
||
+ /* Camera should start to capture now. */
|
||
+ };
|
||
+
|
||
+ return run_start_commands(gspca_dev, ms350_start_commands,
|
||
+ ARRAY_SIZE(ms350_start_commands));
|
||
+}
|
||
+
|
||
+static int start_genius_cam(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct init_command genius_start_commands[] = {
|
||
+ {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
|
||
+ /* "preliminary" width and height settings */
|
||
+ {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
|
||
+ {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
|
||
+ {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
|
||
+ {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
|
||
+ {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
|
||
+ /* Camera should start to capture now. */
|
||
+ };
|
||
+
|
||
+ return run_start_commands(gspca_dev, genius_start_commands,
|
||
+ ARRAY_SIZE(genius_start_commands));
|
||
+}
|
||
+
|
||
+static int start_vivitar_cam(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct init_command vivitar_start_commands[] = {
|
||
+ {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
|
||
+ /*
|
||
+ * Above is changed from OEM 0x0b. Fixes Bayer tiling.
|
||
+ * Presumably gives a vertical shift of one row.
|
||
+ */
|
||
+ {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
|
||
+ /* Above seems to do horizontal shift. */
|
||
+ {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
|
||
+ /* Above three commands seem to relate to brightness. */
|
||
+ {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
|
||
+ /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
|
||
+ {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
|
||
+ {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
|
||
+ /* Above is brightness; OEM driver setting is 0x10 */
|
||
+ {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
|
||
+ {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
|
||
+ {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
|
||
+ };
|
||
+
|
||
+ return run_start_commands(gspca_dev, vivitar_start_commands,
|
||
+ ARRAY_SIZE(vivitar_start_commands));
|
||
+}
|
||
+
|
||
+static int sd_start(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int err_code;
|
||
+
|
||
+ sd->sof_read = 0;
|
||
+
|
||
+ switch (sd->model) {
|
||
+ case 0x7005:
|
||
+ err_code = start_genius_cam(gspca_dev);
|
||
+ break;
|
||
+ case 0x8001:
|
||
+ err_code = start_spy_cam(gspca_dev);
|
||
+ break;
|
||
+ case 0x8003:
|
||
+ err_code = start_cif_cam(gspca_dev);
|
||
+ break;
|
||
+ case 0x8008:
|
||
+ err_code = start_ms350_cam(gspca_dev);
|
||
+ break;
|
||
+ case 0x800a:
|
||
+ err_code = start_vivitar_cam(gspca_dev);
|
||
+ break;
|
||
+ default:
|
||
+ PDEBUG(D_ERR, "Starting unknown camera, please report this");
|
||
+ return -ENXIO;
|
||
+ }
|
||
+
|
||
+ return err_code;
|
||
+}
|
||
+
|
||
+static void sd_stopN(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ int result;
|
||
+ __u8 data[6];
|
||
+
|
||
+ result = sn9c2028_read1(gspca_dev);
|
||
+ if (result < 0)
|
||
+ PDEBUG(D_ERR, "Camera Stop read failed");
|
||
+
|
||
+ memset(data, 0, 6);
|
||
+ data[0] = 0x14;
|
||
+ result = sn9c2028_command(gspca_dev, data);
|
||
+ if (result < 0)
|
||
+ PDEBUG(D_ERR, "Camera Stop command failed");
|
||
+}
|
||
+
|
||
+/* Include sn9c2028 sof detection functions */
|
||
+#include "sn9c2028.h"
|
||
+
|
||
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ __u8 *data, /* isoc packet */
|
||
+ int len) /* iso packet length */
|
||
+{
|
||
+ unsigned char *sof;
|
||
+
|
||
+ sof = sn9c2028_find_sof(gspca_dev, data, len);
|
||
+ if (sof) {
|
||
+ int n;
|
||
+
|
||
+ /* finish decoding current frame */
|
||
+ n = sof - data;
|
||
+ if (n > sizeof sn9c2028_sof_marker)
|
||
+ n -= sizeof sn9c2028_sof_marker;
|
||
+ else
|
||
+ n = 0;
|
||
+ gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
|
||
+ /* Start next frame. */
|
||
+ gspca_frame_add(gspca_dev, FIRST_PACKET,
|
||
+ sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
|
||
+ len -= sof - data;
|
||
+ data = sof;
|
||
+ }
|
||
+ gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
|
||
+}
|
||
+
|
||
+/* sub-driver description */
|
||
+static const struct sd_desc sd_desc = {
|
||
+ .name = MODULE_NAME,
|
||
+ .ctrls = sd_ctrls,
|
||
+ .nctrls = ARRAY_SIZE(sd_ctrls),
|
||
+ .config = sd_config,
|
||
+ .init = sd_init,
|
||
+ .start = sd_start,
|
||
+ .stopN = sd_stopN,
|
||
+ .pkt_scan = sd_pkt_scan,
|
||
+};
|
||
+
|
||
+/* -- module initialisation -- */
|
||
+static const __devinitdata struct usb_device_id device_table[] = {
|
||
+ {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
|
||
+ /* The Genius Smart is untested. I can't find an owner ! */
|
||
+ /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
|
||
+ {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
|
||
+ {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
|
||
+ /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
|
||
+ {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
|
||
+ {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
|
||
+ {}
|
||
+};
|
||
+MODULE_DEVICE_TABLE(usb, device_table);
|
||
+
|
||
+/* -- 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/drivers/media/video/gspca/sn9c2028.h b/drivers/media/video/gspca/sn9c2028.h
|
||
new file mode 100644
|
||
index 0000000..8fd1d3e
|
||
--- /dev/null
|
||
+++ b/drivers/media/video/gspca/sn9c2028.h
|
||
@@ -0,0 +1,51 @@
|
||
+/*
|
||
+ * SN9C2028 common functions
|
||
+ *
|
||
+ * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn,edu>
|
||
+ *
|
||
+ * Based closely upon the file gspca/pac_common.h
|
||
+ *
|
||
+ * 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
|
||
+ * (at your option) 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
|
||
+ *
|
||
+ */
|
||
+
|
||
+static const unsigned char sn9c2028_sof_marker[5] =
|
||
+ { 0xff, 0xff, 0x00, 0xc4, 0xc4 };
|
||
+
|
||
+static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev,
|
||
+ unsigned char *m, int len)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ int i;
|
||
+
|
||
+ /* Search for the SOF marker (fixed part) in the header */
|
||
+ for (i = 0; i < len; i++) {
|
||
+ if (m[i] == sn9c2028_sof_marker[sd->sof_read]) {
|
||
+ sd->sof_read++;
|
||
+ if (sd->sof_read == sizeof(sn9c2028_sof_marker)) {
|
||
+ PDEBUG(D_FRAM,
|
||
+ "SOF found, bytes to analyze: %u."
|
||
+ " Frame starts at byte #%u",
|
||
+ len, i + 1);
|
||
+ sd->sof_read = 0;
|
||
+ return m + i + 1;
|
||
+ }
|
||
+ } else {
|
||
+ sd->sof_read = 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
|
||
index 0ca1c06..4a1bc08 100644
|
||
--- a/drivers/media/video/gspca/sn9c20x.c
|
||
+++ b/drivers/media/video/gspca/sn9c20x.c
|
||
@@ -129,7 +129,7 @@ static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
|
||
static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
|
||
static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
#define BRIGHTNESS_IDX 0
|
||
{
|
||
@@ -1506,36 +1506,36 @@ static int set_cmatrix(struct gspca_dev *gspca_dev)
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
s32 hue_coord, hue_index = 180 + sd->hue;
|
||
u8 cmatrix[21];
|
||
- memset(cmatrix, 0, 21);
|
||
|
||
+ memset(cmatrix, 0, sizeof cmatrix);
|
||
cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
|
||
cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
|
||
cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
|
||
cmatrix[18] = sd->brightness - 0x80;
|
||
|
||
hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
|
||
- cmatrix[6] = (unsigned char)(hue_coord & 0xff);
|
||
- cmatrix[7] = (unsigned char)((hue_coord >> 8) & 0x0f);
|
||
+ cmatrix[6] = hue_coord;
|
||
+ cmatrix[7] = (hue_coord >> 8) & 0x0f;
|
||
|
||
hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
|
||
- cmatrix[8] = (unsigned char)(hue_coord & 0xff);
|
||
- cmatrix[9] = (unsigned char)((hue_coord >> 8) & 0x0f);
|
||
+ cmatrix[8] = hue_coord;
|
||
+ cmatrix[9] = (hue_coord >> 8) & 0x0f;
|
||
|
||
hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
|
||
- cmatrix[10] = (unsigned char)(hue_coord & 0xff);
|
||
- cmatrix[11] = (unsigned char)((hue_coord >> 8) & 0x0f);
|
||
+ cmatrix[10] = hue_coord;
|
||
+ cmatrix[11] = (hue_coord >> 8) & 0x0f;
|
||
|
||
hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
|
||
- cmatrix[12] = (unsigned char)(hue_coord & 0xff);
|
||
- cmatrix[13] = (unsigned char)((hue_coord >> 8) & 0x0f);
|
||
+ cmatrix[12] = hue_coord;
|
||
+ cmatrix[13] = (hue_coord >> 8) & 0x0f;
|
||
|
||
hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
|
||
- cmatrix[14] = (unsigned char)(hue_coord & 0xff);
|
||
- cmatrix[15] = (unsigned char)((hue_coord >> 8) & 0x0f);
|
||
+ cmatrix[14] = hue_coord;
|
||
+ cmatrix[15] = (hue_coord >> 8) & 0x0f;
|
||
|
||
hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
|
||
- cmatrix[16] = (unsigned char)(hue_coord & 0xff);
|
||
- cmatrix[17] = (unsigned char)((hue_coord >> 8) & 0x0f);
|
||
+ cmatrix[16] = hue_coord;
|
||
+ cmatrix[17] = (hue_coord >> 8) & 0x0f;
|
||
|
||
return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
|
||
}
|
||
@@ -2015,6 +2015,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
default:
|
||
cam->cam_mode = vga_mode;
|
||
cam->nmodes = ARRAY_SIZE(vga_mode);
|
||
+ break;
|
||
}
|
||
|
||
sd->old_step = 0;
|
||
@@ -2319,7 +2320,7 @@ static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
|
||
}
|
||
}
|
||
if (avg_lum > MAX_AVG_LUM) {
|
||
- if (sd->gain >= 1) {
|
||
+ if (sd->gain > 0) {
|
||
sd->gain--;
|
||
set_gain(gspca_dev);
|
||
}
|
||
@@ -2347,7 +2348,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
int avg_lum;
|
||
- static unsigned char frame_header[] =
|
||
+ static u8 frame_header[] =
|
||
{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
|
||
if (len == 64 && memcmp(data, frame_header, 6) == 0) {
|
||
avg_lum = ((data[35] >> 2) & 3) |
|
||
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
|
||
index ddff2b5..3830973 100644
|
||
--- a/drivers/media/video/gspca/sonixb.c
|
||
+++ b/drivers/media/video/gspca/sonixb.c
|
||
@@ -42,6 +42,7 @@ Reg Use
|
||
|
||
#define MODULE_NAME "sonixb"
|
||
|
||
+#include <linux/input.h>
|
||
#include "gspca.h"
|
||
|
||
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
|
||
@@ -53,9 +54,11 @@ struct sd {
|
||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||
atomic_t avg_lum;
|
||
int prev_avg_lum;
|
||
+ int exp_too_low_cnt;
|
||
+ int exp_too_high_cnt;
|
||
|
||
+ unsigned short exposure;
|
||
unsigned char gain;
|
||
- unsigned char exposure;
|
||
unsigned char brightness;
|
||
unsigned char autogain;
|
||
unsigned char autogain_ignore_frames;
|
||
@@ -73,8 +76,9 @@ struct sd {
|
||
#define SENSOR_OV7630 2
|
||
#define SENSOR_PAS106 3
|
||
#define SENSOR_PAS202 4
|
||
-#define SENSOR_TAS5110 5
|
||
-#define SENSOR_TAS5130CXX 6
|
||
+#define SENSOR_TAS5110C 5
|
||
+#define SENSOR_TAS5110D 6
|
||
+#define SENSOR_TAS5130CXX 7
|
||
__u8 reg11;
|
||
};
|
||
|
||
@@ -95,13 +99,15 @@ struct sensor_data {
|
||
/* sensor_data flags */
|
||
#define F_GAIN 0x01 /* has gain */
|
||
#define F_SIF 0x02 /* sif or vga */
|
||
+#define F_COARSE_EXPO 0x04 /* exposure control is coarse */
|
||
|
||
/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
|
||
#define MODE_RAW 0x10 /* raw bayer mode */
|
||
#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
|
||
|
||
/* ctrl_dis helper macros */
|
||
-#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
|
||
+#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \
|
||
+ (1 << AUTOGAIN_IDX))
|
||
#define NO_FREQ (1 << FREQ_IDX)
|
||
#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
|
||
|
||
@@ -127,11 +133,10 @@ struct sensor_data {
|
||
}
|
||
|
||
/* We calculate the autogain at the end of the transfer of a frame, at this
|
||
- moment a frame with the old settings is being transmitted, and a frame is
|
||
- being captured with the old settings. So if we adjust the autogain we must
|
||
- ignore atleast the 2 next frames for the new settings to come into effect
|
||
- before doing any other adjustments */
|
||
-#define AUTOGAIN_IGNORE_FRAMES 3
|
||
+ moment a frame with the old settings is being captured and transmitted. So
|
||
+ if we adjust the gain or exposure we must ignore atleast the next frame for
|
||
+ the new settings to come into effect before doing any other adjustments. */
|
||
+#define AUTOGAIN_IGNORE_FRAMES 1
|
||
|
||
/* V4L2 controls supported by the driver */
|
||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||
@@ -145,7 +150,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
#define BRIGHTNESS_IDX 0
|
||
{
|
||
{
|
||
@@ -171,7 +176,7 @@ static struct ctrl sd_ctrls[] = {
|
||
.maximum = 255,
|
||
.step = 1,
|
||
#define GAIN_DEF 127
|
||
-#define GAIN_KNEE 200
|
||
+#define GAIN_KNEE 230
|
||
.default_value = GAIN_DEF,
|
||
},
|
||
.set = sd_setgain,
|
||
@@ -183,10 +188,10 @@ static struct ctrl sd_ctrls[] = {
|
||
.id = V4L2_CID_EXPOSURE,
|
||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||
.name = "Exposure",
|
||
-#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
|
||
-#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
|
||
+#define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */
|
||
+#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */
|
||
.minimum = 0,
|
||
- .maximum = 255,
|
||
+ .maximum = 1023,
|
||
.step = 1,
|
||
.default_value = EXPOSURE_DEF,
|
||
.flags = 0,
|
||
@@ -194,7 +199,23 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_setexposure,
|
||
.get = sd_getexposure,
|
||
},
|
||
-#define AUTOGAIN_IDX 3
|
||
+#define COARSE_EXPOSURE_IDX 3
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_EXPOSURE,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Exposure",
|
||
+#define COARSE_EXPOSURE_DEF 2 /* 30 fps */
|
||
+ .minimum = 2,
|
||
+ .maximum = 15,
|
||
+ .step = 1,
|
||
+ .default_value = COARSE_EXPOSURE_DEF,
|
||
+ .flags = 0,
|
||
+ },
|
||
+ .set = sd_setexposure,
|
||
+ .get = sd_getexposure,
|
||
+ },
|
||
+#define AUTOGAIN_IDX 4
|
||
{
|
||
{
|
||
.id = V4L2_CID_AUTOGAIN,
|
||
@@ -210,7 +231,7 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_setautogain,
|
||
.get = sd_getautogain,
|
||
},
|
||
-#define FREQ_IDX 4
|
||
+#define FREQ_IDX 5
|
||
{
|
||
{
|
||
.id = V4L2_CID_POWER_LINE_FREQUENCY,
|
||
@@ -219,7 +240,7 @@ static struct ctrl sd_ctrls[] = {
|
||
.minimum = 0,
|
||
.maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
|
||
.step = 1,
|
||
-#define FREQ_DEF 1
|
||
+#define FREQ_DEF 0
|
||
.default_value = FREQ_DEF,
|
||
},
|
||
.set = sd_setfreq,
|
||
@@ -297,10 +318,18 @@ static const __u8 hv7131_sensor_init[][8] = {
|
||
{0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
|
||
};
|
||
static const __u8 initOv6650[] = {
|
||
+#if 1
|
||
0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
|
||
0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
|
||
+#else
|
||
+/* old version? */
|
||
+ 0x64, 0x44, 0x28, 0x00, 0x00, 0x00, 0x00, 0x10,
|
||
+ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
+ 0x00, 0x01, 0x01, 0x0a, 0x14, 0x0f, 0x68, 0x8b,
|
||
+ 0x10, 0x1d, 0x10, 0x01, 0x01, 0x07, 0x06
|
||
+#endif
|
||
};
|
||
static const __u8 ov6650_sensor_init[][8] =
|
||
{
|
||
@@ -333,6 +362,24 @@ static const __u8 ov6650_sensor_init[][8] =
|
||
/* Some more unknown stuff */
|
||
{0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
|
||
{0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
|
||
+#if 0
|
||
+ /* HDG, don't change registers 0x2d, 0x32 & 0x33 from their reset
|
||
+ defaults, doing so mucks up the framerate, where as the defaults
|
||
+ seem to work good, the combinations below have been observed
|
||
+ under windows and are kept for future reference */
|
||
+ {0xa0, 0x60, 0x2d, 0x0a, 0x99, 0x04, 0x94, 0x16},
|
||
+ {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
|
||
+ {0xa0, 0x60, 0x33, 0x40, 0x99, 0x04, 0x94, 0x16},
|
||
+ {0xa0, 0x60, 0x2d, 0x2a, 0x99, 0x04, 0x94, 0x15},
|
||
+ {0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
|
||
+ {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
|
||
+ {0xa0, 0x60, 0x33, 0x00, 0x99, 0x04, 0x94, 0x16},
|
||
+ {0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
|
||
+ {0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
|
||
+ /* Low Light (Enabled: 0x32 0x1 | Disabled: 0x32 0x00) */
|
||
+ {0xa0, 0x60, 0x33, 0x29, 0x99, 0x04, 0x94, 0x16},
|
||
+ /* Low Ligth (Enabled: 0x33 0x13 | Disabled: 0x33 0x29) */
|
||
+#endif
|
||
};
|
||
|
||
static const __u8 initOv7630[] = {
|
||
@@ -341,11 +388,15 @@ static const __u8 initOv7630[] = {
|
||
0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
|
||
0x28, 0x1e, /* H & V sizes r15 .. r16 */
|
||
0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
|
||
+#if 1
|
||
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
|
||
+#else /* jfm from win */
|
||
+ 0x1d, 0x10, 0x06, 0x01, 0x00, 0x03 /* r1a .. r1f */
|
||
+#endif
|
||
};
|
||
static const __u8 initOv7630_3[] = {
|
||
0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
|
||
- 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
|
||
+ 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
|
||
0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
|
||
0x28, 0x1e, /* H & V sizes r15 .. r16 */
|
||
0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
|
||
@@ -387,6 +438,30 @@ static const __u8 initPas106[] = {
|
||
0x18, 0x10, 0x02, 0x02, 0x09, 0x07
|
||
};
|
||
/* compression 0x86 mckinit1 0x2b */
|
||
+
|
||
+/* "Known" PAS106B registers:
|
||
+ 0x02 clock divider
|
||
+ 0x03 Variable framerate bits 4-11
|
||
+ 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
|
||
+ The variable framerate control must never be set lower then 300,
|
||
+ which sets the framerate at 90 / reg02, otherwise vsync is lost.
|
||
+ 0x05 Shutter Time Line Offset, this can be used as an exposure control:
|
||
+ 0 = use full frame time, 255 = no exposure at all
|
||
+ Note this may never be larger then "var-framerate control" / 2 - 2.
|
||
+ When var-framerate control is < 514, no exposure is reached at the max
|
||
+ allowed value for the framerate control value, rather then at 255.
|
||
+ 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
|
||
+ only a very little bit, leave at 0xcd
|
||
+ 0x07 offset sign bit (bit0 1 > negative offset)
|
||
+ 0x08 offset
|
||
+ 0x09 Blue Gain
|
||
+ 0x0a Green1 Gain
|
||
+ 0x0b Green2 Gain
|
||
+ 0x0c Red Gain
|
||
+ 0x0e Global gain
|
||
+ 0x13 Write 1 to commit settings to sensor
|
||
+*/
|
||
+
|
||
static const __u8 pas106_sensor_init[][8] = {
|
||
/* Pixel Clock Divider 6 */
|
||
{ 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
|
||
@@ -433,37 +508,55 @@ static const __u8 initPas202[] = {
|
||
0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
|
||
0x00, 0x00,
|
||
0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
|
||
- 0x28, 0x1e, 0x28, 0x89, 0x20,
|
||
+ 0x28, 0x1e, 0x20, 0x89, 0x20,
|
||
0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
|
||
};
|
||
+
|
||
+/* "Known" PAS202BCB registers:
|
||
+ 0x02 clock divider
|
||
+ 0x04 Variable framerate bits 6-11 (*)
|
||
+ 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !!
|
||
+ 0x07 Blue Gain
|
||
+ 0x08 Green Gain
|
||
+ 0x09 Red Gain
|
||
+ 0x0b offset sign bit (bit0 1 > negative offset)
|
||
+ 0x0c offset
|
||
+ 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too,
|
||
+ leave at 1 otherwise we get a jump in our exposure control
|
||
+ 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all
|
||
+ 0x10 Master gain 0 - 31
|
||
+ 0x11 write 1 to apply changes
|
||
+ (*) The variable framerate control must never be set lower then 500
|
||
+ which sets the framerate at 30 / reg02, otherwise vsync is lost.
|
||
+*/
|
||
static const __u8 pas202_sensor_init[][8] = {
|
||
- {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
|
||
+ /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like
|
||
+ to set it lower, but for some reason the bridge starts missing
|
||
+ vsync's then */
|
||
+ {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
|
||
{0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
|
||
{0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
|
||
- {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
|
||
+ {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x01, 0x32, 0x10},
|
||
{0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
|
||
{0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
|
||
{0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
|
||
{0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
|
||
{0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
|
||
{0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
|
||
- {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
|
||
- {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
|
||
-
|
||
- {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
|
||
- {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
|
||
- {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
|
||
- {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
|
||
- {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
|
||
- {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
|
||
- {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
|
||
- {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
|
||
};
|
||
|
||
-static const __u8 initTas5110[] = {
|
||
+static const __u8 initTas5110c[] = {
|
||
0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
|
||
0x00, 0x00,
|
||
- 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
|
||
+ 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
|
||
+ 0x16, 0x12, 0x60, 0x86, 0x2b,
|
||
+ 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
|
||
+};
|
||
+/* Same as above, except a different hstart */
|
||
+static const __u8 initTas5110d[] = {
|
||
+ 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
|
||
+ 0x00, 0x00,
|
||
+ 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
|
||
0x16, 0x12, 0x60, 0x86, 0x2b,
|
||
0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
|
||
};
|
||
@@ -476,7 +569,7 @@ static const __u8 tas5110_sensor_init[][8] = {
|
||
static const __u8 initTas5130[] = {
|
||
0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
|
||
0x00, 0x00,
|
||
- 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
|
||
+ 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
|
||
0x28, 0x1e, 0x60, COMP, MCK_INIT,
|
||
0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
|
||
};
|
||
@@ -493,12 +586,14 @@ SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
|
||
SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
|
||
SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
|
||
F_GAIN, 0, 0x21),
|
||
-SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
|
||
+SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ,
|
||
0),
|
||
-SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
|
||
- NO_EXPO|NO_FREQ, 0),
|
||
-SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
|
||
- NO_BRIGHTNESS|NO_FREQ, 0),
|
||
+SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN,
|
||
+ NO_FREQ, 0),
|
||
+SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL,
|
||
+ F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0),
|
||
+SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL,
|
||
+ F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0),
|
||
SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
|
||
0),
|
||
};
|
||
@@ -587,42 +682,28 @@ static void setbrightness(struct gspca_dev *gspca_dev)
|
||
goto err;
|
||
break;
|
||
}
|
||
- case SENSOR_PAS106: {
|
||
- __u8 i2c1[] =
|
||
- {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
|
||
-
|
||
- i2c1[3] = sd->brightness >> 3;
|
||
- i2c1[2] = 0x0e;
|
||
- if (i2c_w(gspca_dev, i2c1) < 0)
|
||
- goto err;
|
||
- i2c1[3] = 0x01;
|
||
- i2c1[2] = 0x13;
|
||
- if (i2c_w(gspca_dev, i2c1) < 0)
|
||
- goto err;
|
||
- break;
|
||
- }
|
||
+ case SENSOR_PAS106:
|
||
case SENSOR_PAS202: {
|
||
- /* __u8 i2cpexpo1[] =
|
||
- {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
|
||
- __u8 i2cpexpo[] =
|
||
- {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
|
||
- __u8 i2cp202[] =
|
||
- {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
|
||
- static __u8 i2cpdoit[] =
|
||
- {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
|
||
-
|
||
- /* change reg 0x10 */
|
||
- i2cpexpo[4] = 0xff - sd->brightness;
|
||
-/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
|
||
- goto err; */
|
||
-/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
|
||
- goto err; */
|
||
- if (i2c_w(gspca_dev, i2cpexpo) < 0)
|
||
- goto err;
|
||
- if (i2c_w(gspca_dev, i2cpdoit) < 0)
|
||
- goto err;
|
||
- i2cp202[3] = sd->brightness >> 3;
|
||
- if (i2c_w(gspca_dev, i2cp202) < 0)
|
||
+ __u8 i2cpbright[] =
|
||
+ {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
|
||
+ __u8 i2cpdoit[] =
|
||
+ {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
|
||
+
|
||
+ /* PAS106 uses reg 7 and 8 instead of b and c */
|
||
+ if (sd->sensor == SENSOR_PAS106) {
|
||
+ i2cpbright[2] = 7;
|
||
+ i2cpdoit[2] = 0x13;
|
||
+ }
|
||
+
|
||
+ if (sd->brightness < 127) {
|
||
+ /* change reg 0x0b, signreg */
|
||
+ i2cpbright[3] = 0x01;
|
||
+ /* set reg 0x0c, offset */
|
||
+ i2cpbright[4] = 127 - sd->brightness;
|
||
+ } else
|
||
+ i2cpbright[4] = sd->brightness - 127;
|
||
+
|
||
+ if (i2c_w(gspca_dev, i2cpbright) < 0)
|
||
goto err;
|
||
if (i2c_w(gspca_dev, i2cpdoit) < 0)
|
||
goto err;
|
||
@@ -652,7 +733,8 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
|
||
|
||
switch (sd->sensor) {
|
||
|
||
- case SENSOR_TAS5110: {
|
||
+ case SENSOR_TAS5110C:
|
||
+ case SENSOR_TAS5110D: {
|
||
__u8 i2c[] =
|
||
{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
|
||
|
||
@@ -674,6 +756,37 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
|
||
goto err;
|
||
break;
|
||
}
|
||
+ case SENSOR_PAS106:
|
||
+ case SENSOR_PAS202: {
|
||
+ __u8 i2cpgain[] =
|
||
+ {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
|
||
+ __u8 i2cpcolorgain[] =
|
||
+ {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
|
||
+ __u8 i2cpdoit[] =
|
||
+ {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
|
||
+
|
||
+ /* PAS106 uses different regs (and has split green gains) */
|
||
+ if (sd->sensor == SENSOR_PAS106) {
|
||
+ i2cpgain[2] = 0x0e;
|
||
+ i2cpcolorgain[0] = 0xd0;
|
||
+ i2cpcolorgain[2] = 0x09;
|
||
+ i2cpdoit[2] = 0x13;
|
||
+ }
|
||
+
|
||
+ i2cpgain[3] = sd->gain >> 3;
|
||
+ i2cpcolorgain[3] = sd->gain >> 4;
|
||
+ i2cpcolorgain[4] = sd->gain >> 4;
|
||
+ i2cpcolorgain[5] = sd->gain >> 4;
|
||
+ i2cpcolorgain[6] = sd->gain >> 4;
|
||
+
|
||
+ if (i2c_w(gspca_dev, i2cpgain) < 0)
|
||
+ goto err;
|
||
+ if (i2c_w(gspca_dev, i2cpcolorgain) < 0)
|
||
+ goto err;
|
||
+ if (i2c_w(gspca_dev, i2cpdoit) < 0)
|
||
+ goto err;
|
||
+ break;
|
||
+ }
|
||
}
|
||
return;
|
||
err:
|
||
@@ -684,19 +797,21 @@ static void setgain(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
__u8 gain;
|
||
- __u8 rgb_value;
|
||
+ __u8 buf[2] = { 0, 0 };
|
||
+
|
||
+ if (sensor_data[sd->sensor].flags & F_GAIN) {
|
||
+ /* Use the sensor gain to do the actual gain */
|
||
+ setsensorgain(gspca_dev);
|
||
+ return;
|
||
+ }
|
||
|
||
gain = sd->gain >> 4;
|
||
|
||
/* red and blue gain */
|
||
- rgb_value = gain << 4 | gain;
|
||
- reg_w(gspca_dev, 0x10, &rgb_value, 1);
|
||
+ buf[0] = gain << 4 | gain;
|
||
/* green gain */
|
||
- rgb_value = gain;
|
||
- reg_w(gspca_dev, 0x11, &rgb_value, 1);
|
||
-
|
||
- if (sensor_data[sd->sensor].flags & F_GAIN)
|
||
- setsensorgain(gspca_dev);
|
||
+ buf[1] = gain;
|
||
+ reg_w(gspca_dev, 0x10, buf, 2);
|
||
}
|
||
|
||
static void setexposure(struct gspca_dev *gspca_dev)
|
||
@@ -704,17 +819,12 @@ static void setexposure(struct gspca_dev *gspca_dev)
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
|
||
switch (sd->sensor) {
|
||
- case SENSOR_TAS5110: {
|
||
- __u8 reg;
|
||
-
|
||
+ case SENSOR_TAS5110C:
|
||
+ case SENSOR_TAS5110D: {
|
||
/* register 19's high nibble contains the sn9c10x clock divider
|
||
The high nibble configures the no fps according to the
|
||
formula: 60 / high_nibble. With a maximum of 30 fps */
|
||
- reg = 120 * sd->exposure / 1000;
|
||
- if (reg < 2)
|
||
- reg = 2;
|
||
- else if (reg > 15)
|
||
- reg = 15;
|
||
+ __u8 reg = sd->exposure;
|
||
reg = (reg << 4) | 0x0b;
|
||
reg_w(gspca_dev, 0x19, ®, 1);
|
||
break;
|
||
@@ -750,20 +860,21 @@ static void setexposure(struct gspca_dev *gspca_dev)
|
||
} else
|
||
reg10_max = 0x41;
|
||
|
||
- reg11 = (60 * sd->exposure + 999) / 1000;
|
||
+ reg11 = (15 * sd->exposure + 999) / 1000;
|
||
if (reg11 < 1)
|
||
reg11 = 1;
|
||
else if (reg11 > 16)
|
||
reg11 = 16;
|
||
|
||
- /* In 640x480, if the reg11 has less than 3, the image is
|
||
- unstable (not enough bandwidth). */
|
||
- if (gspca_dev->width == 640 && reg11 < 3)
|
||
- reg11 = 3;
|
||
+ /* In 640x480, if the reg11 has less than 4, the image is
|
||
+ unstable (the bridge goes into a higher compression mode
|
||
+ which we have not reverse engineered yet). */
|
||
+ if (gspca_dev->width == 640 && reg11 < 4)
|
||
+ reg11 = 4;
|
||
|
||
/* frame exposure time in ms = 1000 * reg11 / 30 ->
|
||
- reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
|
||
- reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
|
||
+ reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */
|
||
+ reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11);
|
||
|
||
/* Don't allow this to get below 10 when using autogain, the
|
||
steps become very large (relatively) when below 10 causing
|
||
@@ -786,10 +897,85 @@ static void setexposure(struct gspca_dev *gspca_dev)
|
||
if (i2c_w(gspca_dev, i2c) == 0)
|
||
sd->reg11 = reg11;
|
||
else
|
||
- PDEBUG(D_ERR, "i2c error exposure");
|
||
+ goto err;
|
||
+ break;
|
||
+ }
|
||
+ case SENSOR_PAS202: {
|
||
+ __u8 i2cpframerate[] =
|
||
+ {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16};
|
||
+ __u8 i2cpexpo[] =
|
||
+ {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16};
|
||
+ const __u8 i2cpdoit[] =
|
||
+ {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
|
||
+ int framerate_ctrl;
|
||
+
|
||
+ /* The exposure knee for the autogain algorithm is 200
|
||
+ (100 ms / 10 fps on other sensors), for values below this
|
||
+ use the control for setting the partial frame expose time,
|
||
+ above that use variable framerate. This way we run at max
|
||
+ framerate (640x480@7.5 fps, 320x240@10fps) until the knee
|
||
+ is reached. Using the variable framerate control above 200
|
||
+ is better then playing around with both clockdiv + partial
|
||
+ frame exposure times (like we are doing with the ov chips),
|
||
+ as that sometimes leads to jumps in the exposure control,
|
||
+ which are bad for auto exposure. */
|
||
+ if (sd->exposure < 200) {
|
||
+ i2cpexpo[3] = 255 - (sd->exposure * 255) / 200;
|
||
+ framerate_ctrl = 500;
|
||
+ } else {
|
||
+ /* The PAS202's exposure control goes from 0 - 4095,
|
||
+ but anything below 500 causes vsync issues, so scale
|
||
+ our 200-1023 to 500-4095 */
|
||
+ framerate_ctrl = (sd->exposure - 200) * 1000 / 229 +
|
||
+ 500;
|
||
+ }
|
||
+
|
||
+ i2cpframerate[3] = framerate_ctrl >> 6;
|
||
+ i2cpframerate[4] = framerate_ctrl & 0x3f;
|
||
+ if (i2c_w(gspca_dev, i2cpframerate) < 0)
|
||
+ goto err;
|
||
+ if (i2c_w(gspca_dev, i2cpexpo) < 0)
|
||
+ goto err;
|
||
+ if (i2c_w(gspca_dev, i2cpdoit) < 0)
|
||
+ goto err;
|
||
+ break;
|
||
+ }
|
||
+ case SENSOR_PAS106: {
|
||
+ __u8 i2cpframerate[] =
|
||
+ {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
|
||
+ __u8 i2cpexpo[] =
|
||
+ {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
|
||
+ const __u8 i2cpdoit[] =
|
||
+ {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
|
||
+ int framerate_ctrl;
|
||
+
|
||
+ /* For values below 150 use partial frame exposure, above
|
||
+ that use framerate ctrl */
|
||
+ if (sd->exposure < 150) {
|
||
+ i2cpexpo[3] = 150 - sd->exposure;
|
||
+ framerate_ctrl = 300;
|
||
+ } else {
|
||
+ /* The PAS106's exposure control goes from 0 - 4095,
|
||
+ but anything below 300 causes vsync issues, so scale
|
||
+ our 150-1023 to 300-4095 */
|
||
+ framerate_ctrl = (sd->exposure - 150) * 1000 / 230 +
|
||
+ 300;
|
||
+ }
|
||
+
|
||
+ i2cpframerate[3] = framerate_ctrl >> 4;
|
||
+ i2cpframerate[4] = framerate_ctrl & 0x0f;
|
||
+ if (i2c_w(gspca_dev, i2cpframerate) < 0)
|
||
+ goto err;
|
||
+ if (i2c_w(gspca_dev, i2cpexpo) < 0)
|
||
+ goto err;
|
||
+ if (i2c_w(gspca_dev, i2cpdoit) < 0)
|
||
+ goto err;
|
||
break;
|
||
}
|
||
}
|
||
+ return;
|
||
+err:
|
||
+ PDEBUG(D_ERR, "i2c error exposure");
|
||
}
|
||
|
||
static void setfreq(struct gspca_dev *gspca_dev)
|
||
@@ -823,30 +1009,43 @@ static void setfreq(struct gspca_dev *gspca_dev)
|
||
}
|
||
}
|
||
|
||
+#include "coarse_expo_autogain.h"
|
||
+
|
||
static void do_autogain(struct gspca_dev *gspca_dev)
|
||
{
|
||
- int deadzone, desired_avg_lum;
|
||
+ int deadzone, desired_avg_lum, result;
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
int avg_lum = atomic_read(&sd->avg_lum);
|
||
|
||
- if (avg_lum == -1)
|
||
+ if (avg_lum == -1 || !sd->autogain)
|
||
return;
|
||
|
||
+ if (sd->autogain_ignore_frames > 0) {
|
||
+ sd->autogain_ignore_frames--;
|
||
+ return;
|
||
+ }
|
||
+
|
||
/* SIF / VGA sensors have a different autoexposure area and thus
|
||
different avg_lum values for the same picture brightness */
|
||
if (sensor_data[sd->sensor].flags & F_SIF) {
|
||
- deadzone = 1000;
|
||
- desired_avg_lum = 7000;
|
||
+ deadzone = 500;
|
||
+ /* SIF sensors tend to overexpose, so keep this small */
|
||
+ desired_avg_lum = 5000;
|
||
} else {
|
||
- deadzone = 3000;
|
||
- desired_avg_lum = 23000;
|
||
+ deadzone = 1500;
|
||
+ desired_avg_lum = 18000;
|
||
}
|
||
|
||
- if (sd->autogain_ignore_frames > 0)
|
||
- sd->autogain_ignore_frames--;
|
||
- else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
|
||
- sd->brightness * desired_avg_lum / 127,
|
||
- deadzone, GAIN_KNEE, EXPOSURE_KNEE)) {
|
||
+ if (sensor_data[sd->sensor].flags & F_COARSE_EXPO)
|
||
+ result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
|
||
+ sd->brightness * desired_avg_lum / 127,
|
||
+ deadzone);
|
||
+ else
|
||
+ result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
|
||
+ sd->brightness * desired_avg_lum / 127,
|
||
+ deadzone, GAIN_KNEE, EXPOSURE_KNEE);
|
||
+
|
||
+ if (result) {
|
||
PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
|
||
(int)sd->gain, (int)sd->exposure);
|
||
sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
|
||
@@ -881,7 +1080,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
|
||
sd->brightness = BRIGHTNESS_DEF;
|
||
sd->gain = GAIN_DEF;
|
||
- sd->exposure = EXPOSURE_DEF;
|
||
+ if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
|
||
+ sd->exposure = COARSE_EXPOSURE_DEF;
|
||
+ gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX);
|
||
+ } else {
|
||
+ sd->exposure = EXPOSURE_DEF;
|
||
+ gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX);
|
||
+ }
|
||
if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
|
||
sd->autogain = 0; /* Disable do_autogain callback */
|
||
else
|
||
@@ -917,9 +1122,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
|
||
/* Special cases where reg 17 and or 19 value depends on mode */
|
||
switch (sd->sensor) {
|
||
- case SENSOR_PAS202:
|
||
- reg12_19[5] = mode ? 0x24 : 0x20;
|
||
- break;
|
||
case SENSOR_TAS5130CXX:
|
||
/* probably not mode specific at all most likely the upper
|
||
nibble of 0x19 is exposure (clock divider) just as with
|
||
@@ -955,6 +1157,16 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
sensor_data[sd->sensor].sensor_bridge_init_size[
|
||
sd->bridge]);
|
||
|
||
+ /* Mode specific sensor setup */
|
||
+ switch (sd->sensor) {
|
||
+ case SENSOR_PAS202: {
|
||
+ const __u8 i2cpclockdiv[] =
|
||
+ {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10};
|
||
+ /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
|
||
+ if (mode)
|
||
+ i2c_w(gspca_dev, i2cpclockdiv);
|
||
+ }
|
||
+ }
|
||
/* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
|
||
reg_w(gspca_dev, 0x15, ®12_19[3], 2);
|
||
/* compression register */
|
||
@@ -985,6 +1197,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
|
||
sd->frames_to_drop = 0;
|
||
sd->autogain_ignore_frames = 0;
|
||
+ sd->exp_too_high_cnt = 0;
|
||
+ sd->exp_too_low_cnt = 0;
|
||
atomic_set(&sd->avg_lum, -1);
|
||
return 0;
|
||
}
|
||
@@ -1143,11 +1357,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
|
||
sd->autogain = val;
|
||
+ sd->exp_too_high_cnt = 0;
|
||
+ sd->exp_too_low_cnt = 0;
|
||
+
|
||
/* when switching to autogain set defaults to make sure
|
||
we are on a valid point of the autogain gain /
|
||
exposure knee graph, and give this change time to
|
||
take effect before doing autogain. */
|
||
- if (sd->autogain) {
|
||
+ if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) {
|
||
sd->exposure = EXPOSURE_DEF;
|
||
sd->gain = GAIN_DEF;
|
||
if (gspca_dev->streaming) {
|
||
@@ -1207,6 +1424,25 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
|
||
return -EINVAL;
|
||
}
|
||
|
||
+#ifdef CONFIG_INPUT
|
||
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data, /* interrupt packet data */
|
||
+ int len) /* interrupt packet length */
|
||
+{
|
||
+ int ret = -EINVAL;
|
||
+
|
||
+ if (len == 1 && data[0] == 1) {
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ ret = 0;
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+#endif
|
||
+
|
||
/* sub-driver description */
|
||
static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
@@ -1219,6 +1455,9 @@ static const struct sd_desc sd_desc = {
|
||
.pkt_scan = sd_pkt_scan,
|
||
.querymenu = sd_querymenu,
|
||
.dq_callback = do_autogain,
|
||
+#ifdef CONFIG_INPUT
|
||
+ .int_pkt_scan = sd_int_pkt_scan,
|
||
+#endif
|
||
};
|
||
|
||
/* -- module initialisation -- */
|
||
@@ -1227,21 +1466,21 @@ static const struct sd_desc sd_desc = {
|
||
|
||
|
||
static const struct usb_device_id device_table[] __devinitconst = {
|
||
- {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */
|
||
- {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */
|
||
+ {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
|
||
+ {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
|
||
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
|
||
- {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */
|
||
+ {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
|
||
+#endif
|
||
{USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
|
||
{USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
|
||
-#endif
|
||
{USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
|
||
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
|
||
{USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
|
||
{USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
|
||
{USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
|
||
+#endif
|
||
{USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
|
||
{USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
|
||
-#endif
|
||
{USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
|
||
{USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
|
||
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
|
||
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
|
||
index 0bd36a0..c5a2423 100644
|
||
--- a/drivers/media/video/gspca/sonixj.c
|
||
+++ b/drivers/media/video/gspca/sonixj.c
|
||
@@ -21,6 +21,7 @@
|
||
|
||
#define MODULE_NAME "sonixj"
|
||
|
||
+#include <linux/input.h>
|
||
#include "gspca.h"
|
||
#include "jpeg.h"
|
||
|
||
@@ -45,6 +46,7 @@ struct sd {
|
||
u8 red;
|
||
u8 gamma;
|
||
u8 vflip; /* ov7630/ov7648 only */
|
||
+ u8 sharpness;
|
||
u8 infrared; /* mt9v111 only */
|
||
u8 freq; /* ov76xx only */
|
||
u8 quality; /* image quality */
|
||
@@ -64,16 +66,17 @@ struct sd {
|
||
#define BRIDGE_SN9C110 2
|
||
#define BRIDGE_SN9C120 3
|
||
u8 sensor; /* Type of image sensor chip */
|
||
-#define SENSOR_HV7131R 0
|
||
-#define SENSOR_MI0360 1
|
||
-#define SENSOR_MO4000 2
|
||
-#define SENSOR_MT9V111 3
|
||
-#define SENSOR_OM6802 4
|
||
-#define SENSOR_OV7630 5
|
||
-#define SENSOR_OV7648 6
|
||
-#define SENSOR_OV7660 7
|
||
-#define SENSOR_PO1030 8
|
||
-#define SENSOR_SP80708 9
|
||
+#define SENSOR_ADCM1700 0
|
||
+#define SENSOR_HV7131R 1
|
||
+#define SENSOR_MI0360 2
|
||
+#define SENSOR_MO4000 3
|
||
+#define SENSOR_MT9V111 4
|
||
+#define SENSOR_OM6802 5
|
||
+#define SENSOR_OV7630 6
|
||
+#define SENSOR_OV7648 7
|
||
+#define SENSOR_OV7660 8
|
||
+#define SENSOR_PO1030 9
|
||
+#define SENSOR_SP80708 10
|
||
u8 i2c_addr;
|
||
|
||
u8 *jpeg_hdr;
|
||
@@ -96,12 +99,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
#define BRIGHTNESS_IDX 0
|
||
{
|
||
{
|
||
@@ -225,8 +230,23 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_setvflip,
|
||
.get = sd_getvflip,
|
||
},
|
||
+#define SHARPNESS_IDX 8
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_SHARPNESS,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Sharpness",
|
||
+ .minimum = 0,
|
||
+ .maximum = 255,
|
||
+ .step = 1,
|
||
+#define SHARPNESS_DEF 90
|
||
+ .default_value = SHARPNESS_DEF,
|
||
+ },
|
||
+ .set = sd_setsharpness,
|
||
+ .get = sd_getsharpness,
|
||
+ },
|
||
/* mt9v111 only */
|
||
-#define INFRARED_IDX 8
|
||
+#define INFRARED_IDX 9
|
||
{
|
||
{
|
||
.id = V4L2_CID_INFRARED,
|
||
@@ -242,7 +262,7 @@ static struct ctrl sd_ctrls[] = {
|
||
.get = sd_getinfrared,
|
||
},
|
||
/* ov7630/ov7648/ov7660 only */
|
||
-#define FREQ_IDX 9
|
||
+#define FREQ_IDX 10
|
||
{
|
||
{
|
||
.id = V4L2_CID_POWER_LINE_FREQUENCY,
|
||
@@ -261,28 +281,37 @@ static struct ctrl sd_ctrls[] = {
|
||
|
||
/* table of the disabled controls */
|
||
static __u32 ctrl_dis[] = {
|
||
+ (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX) |
|
||
+ (1 << AUTOGAIN_IDX), /* SENSOR_ADCM1700 0 */
|
||
(1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
|
||
- /* SENSOR_HV7131R 0 */
|
||
+ /* SENSOR_HV7131R 1 */
|
||
(1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
|
||
- /* SENSOR_MI0360 1 */
|
||
+ /* SENSOR_MI0360 2 */
|
||
(1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
|
||
- /* SENSOR_MO4000 2 */
|
||
+ /* SENSOR_MO4000 3 */
|
||
(1 << VFLIP_IDX) | (1 << FREQ_IDX),
|
||
- /* SENSOR_MT9V111 3 */
|
||
+ /* SENSOR_MT9V111 4 */
|
||
(1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
|
||
- /* SENSOR_OM6802 4 */
|
||
+ /* SENSOR_OM6802 5 */
|
||
(1 << INFRARED_IDX),
|
||
- /* SENSOR_OV7630 5 */
|
||
+ /* SENSOR_OV7630 6 */
|
||
(1 << INFRARED_IDX),
|
||
- /* SENSOR_OV7648 6 */
|
||
+ /* SENSOR_OV7648 7 */
|
||
(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
|
||
- /* SENSOR_OV7660 7 */
|
||
+ /* SENSOR_OV7660 8 */
|
||
(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) |
|
||
- (1 << FREQ_IDX), /* SENSOR_PO1030 8 */
|
||
+ (1 << FREQ_IDX), /* SENSOR_PO1030 9 */
|
||
(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) |
|
||
- (1 << FREQ_IDX), /* SENSOR_SP80708 9 */
|
||
+ (1 << FREQ_IDX), /* SENSOR_SP80708 10 */
|
||
};
|
||
|
||
+static const struct v4l2_pix_format cif_mode[] = {
|
||
+ {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 352,
|
||
+ .sizeimage = 352 * 288 * 4 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG,
|
||
+ .priv = 0},
|
||
+};
|
||
static const struct v4l2_pix_format vga_mode[] = {
|
||
{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
.bytesperline = 160,
|
||
@@ -302,6 +335,17 @@ static const struct v4l2_pix_format vga_mode[] = {
|
||
.priv = 0},
|
||
};
|
||
|
||
+static const u8 sn_adcm1700[0x1c] = {
|
||
+/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
|
||
+ 0x00, 0x43, 0x60, 0x00, 0x1a, 0x00, 0x00, 0x00,
|
||
+/* reg8 reg9 rega regb regc regd rege regf */
|
||
+ 0x80, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
+/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
|
||
+ 0x03, 0x00, 0x05, 0x01, 0x05, 0x16, 0x12, 0x42,
|
||
+/* reg18 reg19 reg1a reg1b */
|
||
+ 0x06, 0x00, 0x00, 0x00
|
||
+};
|
||
+
|
||
/*Data from sn9c102p+hv7131r */
|
||
static const u8 sn_hv7131[0x1c] = {
|
||
/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
|
||
@@ -415,6 +459,7 @@ static const u8 sn_sp80708[0x1c] = {
|
||
|
||
/* sequence specific to the sensors - !! index = SENSOR_xxx */
|
||
static const u8 *sn_tb[] = {
|
||
+ sn_adcm1700,
|
||
sn_hv7131,
|
||
sn_mi0360,
|
||
sn_mo4000,
|
||
@@ -432,6 +477,11 @@ static const u8 gamma_def[17] = {
|
||
0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
|
||
0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
|
||
};
|
||
+/* gamma for sensor ADCM1700 */
|
||
+static const u8 gamma_spec_0[17] = {
|
||
+ 0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,
|
||
+ 0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5
|
||
+};
|
||
/* gamma for sensors HV7131R and MT9V111 */
|
||
static const u8 gamma_spec_1[17] = {
|
||
0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
|
||
@@ -450,6 +500,42 @@ static const u8 reg84[] = {
|
||
0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
|
||
0x00, 0x00, 0x00 /* YUV offsets */
|
||
};
|
||
+static const u8 adcm1700_sensor_init[][8] = {
|
||
+ {0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10}, /* reset */
|
||
+ {0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||
+ {0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||
+ {0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xdd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||
+ {0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xdd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||
+ {0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
|
||
+ {}
|
||
+};
|
||
+static const u8 adcm1700_sensor_param1[][8] = {
|
||
+ {0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10}, /* exposure? */
|
||
+ {0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},
|
||
+
|
||
+ {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},
|
||
+ {0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10}, /* exposure? */
|
||
+
|
||
+ {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
|
||
+ {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10},
|
||
+ {}
|
||
+};
|
||
static const u8 hv7131r_sensor_init[][8] = {
|
||
{0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
|
||
{0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
|
||
@@ -986,17 +1116,18 @@ static const u8 sp80708_sensor_param1[][8] = {
|
||
{}
|
||
};
|
||
|
||
-static const u8 (*sensor_init[10])[8] = {
|
||
- hv7131r_sensor_init, /* HV7131R 0 */
|
||
- mi0360_sensor_init, /* MI0360 1 */
|
||
- mo4000_sensor_init, /* MO4000 2 */
|
||
- mt9v111_sensor_init, /* MT9V111 3 */
|
||
- om6802_sensor_init, /* OM6802 4 */
|
||
- ov7630_sensor_init, /* OV7630 5 */
|
||
- ov7648_sensor_init, /* OV7648 6 */
|
||
- ov7660_sensor_init, /* OV7660 7 */
|
||
- po1030_sensor_init, /* PO1030 8 */
|
||
- sp80708_sensor_init, /* SP80708 9 */
|
||
+static const u8 (*sensor_init[11])[8] = {
|
||
+ adcm1700_sensor_init, /* ADCM1700 0 */
|
||
+ hv7131r_sensor_init, /* HV7131R 1 */
|
||
+ mi0360_sensor_init, /* MI0360 2 */
|
||
+ mo4000_sensor_init, /* MO4000 3 */
|
||
+ mt9v111_sensor_init, /* MT9V111 4 */
|
||
+ om6802_sensor_init, /* OM6802 5 */
|
||
+ ov7630_sensor_init, /* OV7630 6 */
|
||
+ ov7648_sensor_init, /* OV7648 7 */
|
||
+ ov7660_sensor_init, /* OV7660 8 */
|
||
+ po1030_sensor_init, /* PO1030 9 */
|
||
+ sp80708_sensor_init, /* SP80708 10 */
|
||
};
|
||
|
||
/* read <len> bytes to gspca_dev->usb_buf */
|
||
@@ -1064,6 +1195,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
|
||
|
||
PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
|
||
switch (sd->sensor) {
|
||
+ case SENSOR_ADCM1700:
|
||
case SENSOR_OM6802: /* i2c command = a0 (100 kHz) */
|
||
gspca_dev->usb_buf[0] = 0x80 | (2 << 4);
|
||
break;
|
||
@@ -1110,6 +1242,7 @@ static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)
|
||
u8 mode[8];
|
||
|
||
switch (sd->sensor) {
|
||
+ case SENSOR_ADCM1700:
|
||
case SENSOR_OM6802: /* i2c command = 90 (100 kHz) */
|
||
mode[0] = 0x80 | 0x10;
|
||
break;
|
||
@@ -1255,13 +1388,22 @@ static void bridge_init(struct gspca_dev *gspca_dev,
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
const u8 *reg9a;
|
||
static const u8 reg9a_def[] =
|
||
+#if 1
|
||
{0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
|
||
+#else
|
||
+ {0x00, 0x40, 0x20, 0x10, 0x00, 0x04};
|
||
+#endif
|
||
static const u8 reg9a_spec[] =
|
||
{0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
|
||
static const u8 regd4[] = {0x60, 0x00, 0x00};
|
||
|
||
- reg_w1(gspca_dev, 0xf1, 0x00);
|
||
+ /* sensor clock already enabled in sd_init */
|
||
+ /* reg_w1(gspca_dev, 0xf1, 0x00); */
|
||
+#if 1
|
||
reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
|
||
+#else
|
||
+ reg_w1(gspca_dev, 0x01, 0x00); /*jfm: in some win traces*/
|
||
+#endif
|
||
|
||
/* configure gpio */
|
||
reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
|
||
@@ -1284,6 +1426,12 @@ static void bridge_init(struct gspca_dev *gspca_dev,
|
||
reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
|
||
|
||
switch (sd->sensor) {
|
||
+ case SENSOR_ADCM1700:
|
||
+ reg_w1(gspca_dev, 0x01, 0x43);
|
||
+ reg_w1(gspca_dev, 0x17, 0x62);
|
||
+ reg_w1(gspca_dev, 0x01, 0x42);
|
||
+ reg_w1(gspca_dev, 0x01, 0x42);
|
||
+ break;
|
||
case SENSOR_MT9V111:
|
||
reg_w1(gspca_dev, 0x01, 0x61);
|
||
reg_w1(gspca_dev, 0x17, 0x61);
|
||
@@ -1357,14 +1513,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct cam *cam;
|
||
|
||
- cam = &gspca_dev->cam;
|
||
- cam->cam_mode = vga_mode;
|
||
- cam->nmodes = ARRAY_SIZE(vga_mode);
|
||
- cam->npkt = 24; /* 24 packets per ISOC message */
|
||
-
|
||
sd->bridge = id->driver_info >> 16;
|
||
sd->sensor = id->driver_info;
|
||
|
||
+ cam = &gspca_dev->cam;
|
||
+ if (sd->sensor == SENSOR_ADCM1700) {
|
||
+ cam->cam_mode = cif_mode;
|
||
+ cam->nmodes = ARRAY_SIZE(cif_mode);
|
||
+ } else {
|
||
+ cam->cam_mode = vga_mode;
|
||
+ cam->nmodes = ARRAY_SIZE(vga_mode);
|
||
+ }
|
||
+ cam->npkt = 24; /* 24 packets per ISOC message */
|
||
+
|
||
sd->brightness = BRIGHTNESS_DEF;
|
||
sd->contrast = CONTRAST_DEF;
|
||
sd->colors = COLOR_DEF;
|
||
@@ -1374,6 +1535,14 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
sd->autogain = AUTOGAIN_DEF;
|
||
sd->ag_cnt = -1;
|
||
sd->vflip = VFLIP_DEF;
|
||
+ switch (sd->sensor) {
|
||
+ case SENSOR_OM6802:
|
||
+ sd->sharpness = 0x10;
|
||
+ break;
|
||
+ default:
|
||
+ sd->sharpness = SHARPNESS_DEF;
|
||
+ break;
|
||
+ }
|
||
sd->infrared = INFRARED_DEF;
|
||
sd->freq = FREQ_DEF;
|
||
sd->quality = QUALITY_DEF;
|
||
@@ -1433,7 +1602,9 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||
break;
|
||
}
|
||
|
||
- reg_w1(gspca_dev, 0xf1, 0x01);
|
||
+ /* Note we do not disable the sensor clock here (power saving mode),
|
||
+ as that also disables the button on the cam. */
|
||
+ reg_w1(gspca_dev, 0xf1, 0x00);
|
||
|
||
/* set the i2c address */
|
||
sn9c1xx = sn_tb[sd->sensor];
|
||
@@ -1543,6 +1724,10 @@ static void setbrightness(struct gspca_dev *gspca_dev)
|
||
|
||
k2 = ((int) sd->brightness - 0x8000) >> 10;
|
||
switch (sd->sensor) {
|
||
+ case SENSOR_ADCM1700:
|
||
+ if (k2 > 0x1f)
|
||
+ k2 = 0; /* only positive Y offset */
|
||
+ break;
|
||
case SENSOR_HV7131R:
|
||
expo = sd->brightness << 4;
|
||
if (expo > 0x002dc6c0)
|
||
@@ -1625,6 +1810,9 @@ static void setgamma(struct gspca_dev *gspca_dev)
|
||
};
|
||
|
||
switch (sd->sensor) {
|
||
+ case SENSOR_ADCM1700:
|
||
+ gamma_base = gamma_spec_0;
|
||
+ break;
|
||
case SENSOR_HV7131R:
|
||
case SENSOR_MT9V111:
|
||
gamma_base = gamma_spec_1;
|
||
@@ -1689,14 +1877,25 @@ static void setvflip(struct sd *sd)
|
||
i2c_w1(&sd->gspca_dev, 0x75, comn);
|
||
}
|
||
|
||
+static void setsharpness(struct sd *sd)
|
||
+{
|
||
+ reg_w1(&sd->gspca_dev, 0x99, sd->sharpness);
|
||
+}
|
||
+
|
||
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 */
|
||
i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
|
||
sd->infrared ? 0x66 : 0x64);
|
||
+#else
|
||
+/* 370i */
|
||
+ i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
|
||
+ sd->infrared ? 0x55 : 0x54);
|
||
+#endif
|
||
}
|
||
|
||
static void setfreq(struct gspca_dev *gspca_dev)
|
||
@@ -1804,6 +2007,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
int mode;
|
||
static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
|
||
static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
|
||
+ static const u8 CA_adcm1700[] =
|
||
+ { 0x14, 0xec, 0x0a, 0xf6 };
|
||
static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
|
||
static const u8 CE_ov76xx[] =
|
||
{ 0x32, 0xdd, 0x32, 0xdd };
|
||
@@ -1824,6 +2029,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
|
||
|
||
switch (sd->sensor) {
|
||
+ case SENSOR_ADCM1700:
|
||
+ reg2 = 0x60;
|
||
+ break;
|
||
case SENSOR_OM6802:
|
||
reg2 = 0x71;
|
||
break;
|
||
@@ -1842,17 +2050,28 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
|
||
reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
|
||
reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
|
||
- reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
|
||
- reg_w1(gspca_dev, 0xd3, 0x50);
|
||
+ if (sd->sensor == SENSOR_ADCM1700) {
|
||
+ reg_w1(gspca_dev, 0xd2, 0x3a); /* AE_H_SIZE = 116 */
|
||
+ reg_w1(gspca_dev, 0xd3, 0x30); /* AE_V_SIZE = 96 */
|
||
+ } else {
|
||
+ reg_w1(gspca_dev, 0xd2, 0x6a); /* AE_H_SIZE = 212 */
|
||
+ reg_w1(gspca_dev, 0xd3, 0x50); /* AE_V_SIZE = 160 */
|
||
+ }
|
||
reg_w1(gspca_dev, 0xc6, 0x00);
|
||
reg_w1(gspca_dev, 0xc7, 0x00);
|
||
- reg_w1(gspca_dev, 0xc8, 0x50);
|
||
- reg_w1(gspca_dev, 0xc9, 0x3c);
|
||
+ if (sd->sensor == SENSOR_ADCM1700) {
|
||
+ reg_w1(gspca_dev, 0xc8, 0x2c); /* AW_H_STOP = 352 */
|
||
+ reg_w1(gspca_dev, 0xc9, 0x24); /* AW_V_STOP = 288 */
|
||
+ } else {
|
||
+ reg_w1(gspca_dev, 0xc8, 0x50); /* AW_H_STOP = 640 */
|
||
+ reg_w1(gspca_dev, 0xc9, 0x3c); /* AW_V_STOP = 480 */
|
||
+ }
|
||
reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
|
||
switch (sd->sensor) {
|
||
case SENSOR_MT9V111:
|
||
reg17 = 0xe0;
|
||
break;
|
||
+ case SENSOR_ADCM1700:
|
||
case SENSOR_OV7630:
|
||
reg17 = 0xe2;
|
||
break;
|
||
@@ -1863,44 +2082,39 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
break;
|
||
}
|
||
reg_w1(gspca_dev, 0x17, reg17);
|
||
-/* set reg1 was here */
|
||
- reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */
|
||
- reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */
|
||
- reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */
|
||
+
|
||
+ reg_w1(gspca_dev, 0x05, 0x00); /* red */
|
||
+ reg_w1(gspca_dev, 0x07, 0x00); /* green */
|
||
+ reg_w1(gspca_dev, 0x06, 0x00); /* blue */
|
||
reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
|
||
|
||
setgamma(gspca_dev);
|
||
|
||
+/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */
|
||
for (i = 0; i < 8; i++)
|
||
reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
|
||
switch (sd->sensor) {
|
||
+ case SENSOR_ADCM1700:
|
||
+ case SENSOR_OV7660:
|
||
+ case SENSOR_SP80708:
|
||
+ reg_w1(gspca_dev, 0x9a, 0x05);
|
||
+ break;
|
||
case SENSOR_MT9V111:
|
||
reg_w1(gspca_dev, 0x9a, 0x07);
|
||
- reg_w1(gspca_dev, 0x99, 0x59);
|
||
- break;
|
||
- case SENSOR_OM6802:
|
||
- reg_w1(gspca_dev, 0x9a, 0x08);
|
||
- reg_w1(gspca_dev, 0x99, 0x10);
|
||
break;
|
||
case SENSOR_OV7648:
|
||
reg_w1(gspca_dev, 0x9a, 0x0a);
|
||
- reg_w1(gspca_dev, 0x99, 0x60);
|
||
- break;
|
||
- case SENSOR_OV7660:
|
||
- case SENSOR_SP80708:
|
||
- reg_w1(gspca_dev, 0x9a, 0x05);
|
||
- reg_w1(gspca_dev, 0x99, 0x59);
|
||
break;
|
||
default:
|
||
reg_w1(gspca_dev, 0x9a, 0x08);
|
||
- reg_w1(gspca_dev, 0x99, 0x59);
|
||
break;
|
||
}
|
||
+ setsharpness(sd);
|
||
|
||
reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
|
||
- reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */
|
||
- reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */
|
||
- reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */
|
||
+ reg_w1(gspca_dev, 0x05, 0x20); /* red */
|
||
+ reg_w1(gspca_dev, 0x07, 0x20); /* green */
|
||
+ reg_w1(gspca_dev, 0x06, 0x20); /* blue */
|
||
|
||
init = NULL;
|
||
mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
|
||
@@ -1917,6 +2135,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */
|
||
reg17 = 0x61; /* 0x:20: enable sensor clock */
|
||
switch (sd->sensor) {
|
||
+ case SENSOR_ADCM1700:
|
||
+ init = adcm1700_sensor_param1;
|
||
+ reg1 = 0x46;
|
||
+ reg17 = 0xe2;
|
||
+ break;
|
||
case SENSOR_MO4000:
|
||
if (mode) {
|
||
/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
|
||
@@ -1986,8 +2209,12 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
}
|
||
|
||
reg_w(gspca_dev, 0xc0, C0, 6);
|
||
- reg_w(gspca_dev, 0xca, CA, 4);
|
||
+ if (sd->sensor == SENSOR_ADCM1700)
|
||
+ reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
|
||
+ else
|
||
+ reg_w(gspca_dev, 0xca, CA, 4);
|
||
switch (sd->sensor) {
|
||
+ case SENSOR_ADCM1700:
|
||
case SENSOR_OV7630:
|
||
case SENSOR_OV7648:
|
||
case SENSOR_OV7660:
|
||
@@ -2056,7 +2300,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
|
||
reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
|
||
reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
|
||
reg_w1(gspca_dev, 0x01, data);
|
||
- reg_w1(gspca_dev, 0xf1, 0x00);
|
||
+ /* Don't disable sensor clock as that disables the button on the cam */
|
||
+ /* reg_w1(gspca_dev, 0xf1, 0x01); */
|
||
}
|
||
|
||
static void sd_stop0(struct gspca_dev *gspca_dev)
|
||
@@ -2288,6 +2533,24 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
return 0;
|
||
}
|
||
|
||
+static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->sharpness = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ setsharpness(sd);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->sharpness;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
@@ -2391,6 +2654,25 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
|
||
return -EINVAL;
|
||
}
|
||
|
||
+#ifdef CONFIG_INPUT
|
||
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data, /* interrupt packet data */
|
||
+ int len) /* interrupt packet length */
|
||
+{
|
||
+ int ret = -EINVAL;
|
||
+
|
||
+ if (len == 1 && data[0] == 1) {
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ ret = 0;
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+#endif
|
||
+
|
||
/* sub-driver description */
|
||
static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
@@ -2406,6 +2688,9 @@ static const struct sd_desc sd_desc = {
|
||
.get_jcomp = sd_get_jcomp,
|
||
.set_jcomp = sd_set_jcomp,
|
||
.querymenu = sd_querymenu,
|
||
+#ifdef CONFIG_INPUT
|
||
+ .int_pkt_scan = sd_int_pkt_scan,
|
||
+#endif
|
||
};
|
||
|
||
/* -- module initialisation -- */
|
||
@@ -2472,6 +2762,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
|
||
/* {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, *sn9c120b*/
|
||
{USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/
|
||
{USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/
|
||
+ {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/
|
||
{}
|
||
};
|
||
MODULE_DEVICE_TABLE(usb, device_table);
|
||
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
|
||
index fe46868..29e1699 100644
|
||
--- a/drivers/media/video/gspca/spca500.c
|
||
+++ b/drivers/media/video/gspca/spca500.c
|
||
@@ -68,7 +68,7 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -153,6 +153,23 @@ static const struct v4l2_pix_format sif_mode[] = {
|
||
#define SPCA500_OFFSET_AUGPIO 12
|
||
#define SPCA500_OFFSET_DATA 16
|
||
|
||
+#if 0
|
||
+static const __u16 spca500_read_stats[][3] = {
|
||
+ {0x0c, 0x0000, 0x0000},
|
||
+ {0x30, 0x03fd, 0x0001},
|
||
+ /* possible values for following call: 0x01b3, 0x01e6, 0x01f7, 0x0218 */
|
||
+ {0x30, 0x01b3, 0x0002},
|
||
+ /* possible values for following call: 0x0000, 0x0001, 0x0002 */
|
||
+ {0x30, 0x0000, 0x0003},
|
||
+ {0x30, 0x003b, 0x0004},
|
||
+ /* possible values for following call: 0x00aa, 0x00e0 */
|
||
+ {0x30, 0x00e0, 0x0005},
|
||
+ {0x30, 0x0001, 0x0006},
|
||
+ {0x30, 0x0080, 0x0007},
|
||
+ {0x30, 0x0004, 0x0000},
|
||
+ {}
|
||
+};
|
||
+#endif
|
||
|
||
static const __u16 spca500_visual_defaults[][3] = {
|
||
{0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
|
||
@@ -1047,7 +1064,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
|
||
}
|
||
|
||
/* sub-driver description */
|
||
-static struct sd_desc sd_desc = {
|
||
+static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls,
|
||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
|
||
index 6761a30..543f4db 100644
|
||
--- a/drivers/media/video/gspca/spca501.c
|
||
+++ b/drivers/media/video/gspca/spca501.c
|
||
@@ -59,7 +59,7 @@ static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
#define MY_BRIGHTNESS 0
|
||
{
|
||
{
|
||
@@ -1856,6 +1856,31 @@ static int reg_write(struct usb_device *dev,
|
||
return ret;
|
||
}
|
||
|
||
+#if 0
|
||
+/* returns: negative is error, pos or zero is data */
|
||
+static int reg_read(struct gspca_dev *gspca_dev,
|
||
+ __u16 req, /* bRequest */
|
||
+ __u16 index, /* wIndex */
|
||
+ __u16 length) /* wLength (1 or 2 only) */
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ gspca_dev->usb_buf[1] = 0;
|
||
+ ret = usb_control_msg(gspca_dev->dev,
|
||
+ usb_rcvctrlpipe(gspca_dev->dev, 0),
|
||
+ req,
|
||
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||
+ 0, /* value */
|
||
+ index,
|
||
+ gspca_dev->usb_buf, length,
|
||
+ 500); /* timeout */
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "reg_read err %d", ret);
|
||
+ return -1;
|
||
+ }
|
||
+ return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
|
||
+}
|
||
+#endif
|
||
|
||
static int write_vector(struct gspca_dev *gspca_dev,
|
||
const __u16 data[][3])
|
||
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
|
||
index 0f9232f..c576eed 100644
|
||
--- a/drivers/media/video/gspca/spca505.c
|
||
+++ b/drivers/media/video/gspca/spca505.c
|
||
@@ -42,7 +42,7 @@ struct sd {
|
||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
|
||
index 39257e4..89fec4c 100644
|
||
--- a/drivers/media/video/gspca/spca506.c
|
||
+++ b/drivers/media/video/gspca/spca506.c
|
||
@@ -51,7 +51,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
#define SD_BRIGHTNESS 0
|
||
{
|
||
{
|
||
@@ -673,7 +673,7 @@ static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
|
||
}
|
||
|
||
/* sub-driver description */
|
||
-static struct sd_desc sd_desc = {
|
||
+static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls,
|
||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
|
||
index 4d8e6cf..b202e62 100644
|
||
--- a/drivers/media/video/gspca/spca508.c
|
||
+++ b/drivers/media/video/gspca/spca508.c
|
||
@@ -45,7 +45,7 @@ struct sd {
|
||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -86,6 +86,26 @@ static const struct v4l2_pix_format sif_mode[] = {
|
||
};
|
||
|
||
/* Frame packet header offsets for the spca508 */
|
||
+#if 0
|
||
+#define SPCA508_OFFSET_
|
||
+#define SPCA508_OFFSET_TYPE 1
|
||
+#define SPCA508_IMAGE_TYPE_MASK 0x1f
|
||
+#define SPCA508_SNAPBIT 0x20
|
||
+#define SPCA508_SNAPCTRL 0x40
|
||
+#define SPCA508_OFFSET_COMPRESS 2
|
||
+#define SPCA508_OFFSET_FRAMSEQ 8
|
||
+#define SPCA508_OFFSET_GPIO 9
|
||
+#define SPCA508_OFFSET_GLBINF 10
|
||
+#define SPCA508_OFFSET_WIN1LUM 11
|
||
+#define SPCA508_OFFSET_WIN2LUM 12
|
||
+#define SPCA508_OFFSET_WIN1RG 13
|
||
+#define SPCA508_OFFSET_WIN1BG 14
|
||
+#define SPCA508_OFFSET_WIN2RG 15
|
||
+#define SPCA508_OFFSET_WIN2BG 16
|
||
+#define SPCA508_OFFSET_21 21
|
||
+#define SPCA508_GAMMAEN 0x01
|
||
+#define SPCA508_EDGEMODE 0x02
|
||
+#endif
|
||
#define SPCA508_OFFSET_DATA 37
|
||
|
||
/*
|
||
@@ -423,7 +443,24 @@ static const u16 spca508_init_data[][2] =
|
||
{0x007d, 0x8800},
|
||
/* READ { 0x0001, 0x8803 } -> 0000: 00 */
|
||
|
||
+#if 0
|
||
+ /* experimental. dark version. */
|
||
+ {0xba, 0x8705}, /* total pixel clocks per hsync cycle (L) */
|
||
+ {0x00, 0x8706}, /* total pixel clocks per hsync cycle (H in 2:0) */
|
||
+ {0x5a, 0x8707}, /* total pixel clocks per hsync blank period (L) */
|
||
+#elif 0
|
||
+ /* experimental. factory default. */
|
||
+ {0x8e, 0x8705}, /* total pixel clocks per hsync cycle (L) */
|
||
+ {0x03, 0x8706}, /* total pixel clocks per hsync cycle (H in 2:0) */
|
||
+ {0x5a, 0x8707}, /* total pixel clocks per hsync blank period (L) */
|
||
+#elif 0
|
||
+ /* experimental. light. */
|
||
+ {0xba, 0x8705}, /* total pixel clocks per hsync cycle (L) */
|
||
+ {0x01, 0x8706}, /* total pixel clocks per hsync cycle (H in 2:0) */
|
||
+ {0x10, 0x8707}, /* total pixel clocks per hsync blank period (L) */
|
||
+#endif
|
||
|
||
+#if 1
|
||
/* This chunk is seemingly redundant with */
|
||
/* earlier commands (A11 Coef...), but if I disable it, */
|
||
/* the image appears too dark. Maybe there was some kind of */
|
||
@@ -438,6 +475,7 @@ static const u16 spca508_init_data[][2] =
|
||
{0xffdc, 0x860f},
|
||
{0x0039, 0x8610},
|
||
{0x0018, 0x8657},
|
||
+#endif
|
||
|
||
{0x0000, 0x8508}, /* Disable compression. */
|
||
/* Previous line was:
|
||
@@ -480,8 +518,16 @@ static const u16 spca508_init_data[][2] =
|
||
/* READ { 0x0001, 0x8803 } -> 0000: 00 */
|
||
{0x0001, 0x8602}, /* optical black level for user settning = 1 */
|
||
|
||
+#if 0
|
||
+ /* NOTE: Code like this case lets this driver (often) work */
|
||
+ /* in 352x288 resolution, apparently by slowing down the */
|
||
+ /* clock. */
|
||
+
|
||
+ {0x002f, 0x8700}, /* Clock speed */
|
||
+#else
|
||
/* Original: */
|
||
{0x0023, 0x8700}, /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
|
||
+#endif
|
||
{0x000f, 0x8602}, /* optical black level for user settning = 15 */
|
||
|
||
{0x0028, 0x8802},
|
||
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
|
||
index 58c2f00..85eeb51 100644
|
||
--- a/drivers/media/video/gspca/spca561.c
|
||
+++ b/drivers/media/video/gspca/spca561.c
|
||
@@ -190,16 +190,36 @@ static const __u16 rev72a_init_data2[][2] = {
|
||
{0x0002, 0x8201}, /* Output address for r/w serial EEPROM */
|
||
{0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */
|
||
{0x0001, 0x8200}, /* OprMode to be executed by hardware */
|
||
+#if 0
|
||
+ {0x0007, 0x8201}, /* Output address for r/w serial EEPROM */
|
||
+ {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */
|
||
+ {0x0001, 0x8200}, /* OprMode to be executed by hardware */
|
||
+ {0x0010, 0x8660}, /* Compensation memory stuff */
|
||
+ {0x0018, 0x8660}, /* Compensation memory stuff */
|
||
+#endif
|
||
+#if 1
|
||
/* from ms-win */
|
||
{0x0000, 0x8611}, /* R offset for white balance */
|
||
{0x00fd, 0x8612}, /* Gr offset for white balance */
|
||
{0x0003, 0x8613}, /* B offset for white balance */
|
||
+#else
|
||
+ {0x0004, 0x8611}, /* R offset for white balance */
|
||
+ {0x0004, 0x8612}, /* Gr offset for white balance */
|
||
+ {0x0007, 0x8613}, /* B offset for white balance */
|
||
+#endif
|
||
{0x0000, 0x8614}, /* Gb offset for white balance */
|
||
+#if 1
|
||
/* from ms-win */
|
||
{0x0035, 0x8651}, /* R gain for white balance */
|
||
{0x0040, 0x8652}, /* Gr gain for white balance */
|
||
{0x005f, 0x8653}, /* B gain for white balance */
|
||
{0x0040, 0x8654}, /* Gb gain for white balance */
|
||
+#else
|
||
+ {0x008c, 0x8651}, /* R gain for white balance */
|
||
+ {0x008c, 0x8652}, /* Gr gain for white balance */
|
||
+ {0x00b5, 0x8653}, /* B gain for white balance */
|
||
+ {0x008c, 0x8654}, /* Gb gain for white balance */
|
||
+#endif
|
||
{0x0002, 0x8502}, /* Maximum average bit rate stuff */
|
||
{0x0011, 0x8802},
|
||
|
||
@@ -224,6 +244,17 @@ static const u16 rev72a_init_sensor2[][2] = {
|
||
{0x0035, 0x0014},
|
||
{}
|
||
};
|
||
+#if 0
|
||
+static const __u16 rev72a_init_data3[][2] = {
|
||
+ {0x0087, 0x8700}, /* overwrite by start */
|
||
+ {0x0081, 0x8702},
|
||
+ {0x0000, 0x8500},
|
||
+/* {0x0010, 0x8500}, -- Previous line was this */
|
||
+ {0x0002, 0x865b},
|
||
+ {0x0003, 0x865c},
|
||
+ {}
|
||
+};
|
||
+#endif
|
||
|
||
/******************** QC Express etch2 stuff ********************/
|
||
static const __u16 Pb100_1map8300[][2] = {
|
||
@@ -922,7 +953,7 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
|
||
}
|
||
|
||
/* control tables */
|
||
-static struct ctrl sd_ctrls_12a[] = {
|
||
+static const struct ctrl sd_ctrls_12a[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_HUE,
|
||
@@ -964,7 +995,7 @@ static struct ctrl sd_ctrls_12a[] = {
|
||
},
|
||
};
|
||
|
||
-static struct ctrl sd_ctrls_72a[] = {
|
||
+static const struct ctrl sd_ctrls_72a[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_HUE,
|
||
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
|
||
index d70b156..e646620 100644
|
||
--- a/drivers/media/video/gspca/sq905c.c
|
||
+++ b/drivers/media/video/gspca/sq905c.c
|
||
@@ -47,6 +47,7 @@ MODULE_LICENSE("GPL");
|
||
|
||
/* Commands. These go in the "value" slot. */
|
||
#define SQ905C_CLEAR 0xa0 /* clear everything */
|
||
+#define SQ905C_GET_ID 0x14f4 /* Read version number */
|
||
#define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */
|
||
#define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */
|
||
#define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */
|
||
@@ -101,6 +102,26 @@ static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
|
||
return 0;
|
||
}
|
||
|
||
+static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
|
||
+ int size)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = usb_control_msg(gspca_dev->dev,
|
||
+ usb_rcvctrlpipe(gspca_dev->dev, 0),
|
||
+ USB_REQ_SYNCH_FRAME, /* request */
|
||
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||
+ command, index, gspca_dev->usb_buf, size,
|
||
+ SQ905C_CMD_TIMEOUT);
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)",
|
||
+ __func__, ret);
|
||
+ return ret;
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
/* 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
|
||
@@ -183,13 +204,34 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
{
|
||
struct cam *cam = &gspca_dev->cam;
|
||
struct sd *dev = (struct sd *) gspca_dev;
|
||
+ int ret;
|
||
|
||
PDEBUG(D_PROBE,
|
||
"SQ9050 camera detected"
|
||
" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
|
||
+
|
||
+ ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "Get version command failed");
|
||
+ return ret;
|
||
+ }
|
||
+
|
||
+ ret = sq905c_read(gspca_dev, 0xf5, 0, 20);
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "Reading version command failed");
|
||
+ return ret;
|
||
+ }
|
||
+ /* Note we leave out the usb id and the manufacturing date */
|
||
+ PDEBUG(D_PROBE,
|
||
+ "SQ9050 ID string: %02x - %02x %02x %02x %02x %02x %02x",
|
||
+ gspca_dev->usb_buf[3],
|
||
+ gspca_dev->usb_buf[14], gspca_dev->usb_buf[15],
|
||
+ gspca_dev->usb_buf[16], gspca_dev->usb_buf[17],
|
||
+ gspca_dev->usb_buf[18], gspca_dev->usb_buf[19]);
|
||
+
|
||
cam->cam_mode = sq905c_mode;
|
||
cam->nmodes = 2;
|
||
- if (id->idProduct == 0x9050)
|
||
+ if (gspca_dev->usb_buf[15] == 0)
|
||
cam->nmodes = 1;
|
||
/* We don't use the buffer gspca allocates so make it small. */
|
||
cam->bulk_size = 32;
|
||
@@ -258,6 +300,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
static const __devinitdata struct usb_device_id device_table[] = {
|
||
{USB_DEVICE(0x2770, 0x905c)},
|
||
{USB_DEVICE(0x2770, 0x9050)},
|
||
+ {USB_DEVICE(0x2770, 0x9052)},
|
||
{USB_DEVICE(0x2770, 0x913d)},
|
||
{}
|
||
};
|
||
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
|
||
index 2e29355..0fb5342 100644
|
||
--- a/drivers/media/video/gspca/stk014.c
|
||
+++ b/drivers/media/video/gspca/stk014.c
|
||
@@ -53,7 +53,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c
|
||
index 2a69d7c..c3743c9 100644
|
||
--- a/drivers/media/video/gspca/stv0680.c
|
||
+++ b/drivers/media/video/gspca/stv0680.c
|
||
@@ -45,7 +45,7 @@ struct sd {
|
||
};
|
||
|
||
/* V4L2 controls supported by the driver */
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
};
|
||
|
||
static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
|
||
@@ -53,24 +53,28 @@ static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
|
||
{
|
||
int ret = -1;
|
||
u8 req_type = 0;
|
||
+ unsigned int pipe = 0;
|
||
|
||
switch (set) {
|
||
case 0: /* 0xc1 */
|
||
req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
|
||
+ pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
|
||
break;
|
||
case 1: /* 0x41 */
|
||
req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
|
||
+ pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
|
||
break;
|
||
case 2: /* 0x80 */
|
||
req_type = USB_DIR_IN | USB_RECIP_DEVICE;
|
||
+ pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
|
||
break;
|
||
case 3: /* 0x40 */
|
||
req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
|
||
+ pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
|
||
break;
|
||
}
|
||
|
||
- ret = usb_control_msg(gspca_dev->dev,
|
||
- usb_rcvctrlpipe(gspca_dev->dev, 0),
|
||
+ ret = usb_control_msg(gspca_dev->dev, pipe,
|
||
req, req_type,
|
||
val, 0, gspca_dev->usb_buf, size, 500);
|
||
|
||
@@ -138,6 +142,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct cam *cam = &gspca_dev->cam;
|
||
|
||
+ /* Give the camera some time to settle, otherwise initalization will
|
||
+ fail on hotplug, and yes it really needs a full second. */
|
||
+ msleep(1000);
|
||
+
|
||
/* ping camera to be sure STV0680 is present */
|
||
if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 ||
|
||
gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) {
|
||
@@ -169,6 +177,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
PDEBUG(D_PROBE, "Camera supports CIF mode");
|
||
if (gspca_dev->usb_buf[7] & 0x02)
|
||
PDEBUG(D_PROBE, "Camera supports VGA mode");
|
||
+ if (gspca_dev->usb_buf[7] & 0x04)
|
||
+ PDEBUG(D_PROBE, "Camera supports QCIF mode");
|
||
if (gspca_dev->usb_buf[7] & 0x08)
|
||
PDEBUG(D_PROBE, "Camera supports QVGA mode");
|
||
|
||
@@ -185,6 +195,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
PDEBUG(D_PROBE, "Sensor ID is %i",
|
||
(gspca_dev->usb_buf[4]*16) + (gspca_dev->usb_buf[5]>>4));
|
||
|
||
+#if 0 /* The v4l1 driver used to this but I don't think it is necessary */
|
||
+ ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "Set alt 1 failed (%d)", ret);
|
||
+ return ret;
|
||
+ }
|
||
+
|
||
+ if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10)
|
||
+ return stv0680_handle_error(gspca_dev, -EIO);
|
||
+ if (stv_sndctrl(gspca_dev, 0, 0x8d, 0, 0x08) != 0x08)
|
||
+ return stv0680_handle_error(gspca_dev, -EIO);
|
||
+ PDEBUG(D_PROBE, "Camera has %i pictures.", gspca_dev->usb_buf[3]);
|
||
+#endif
|
||
|
||
ret = stv0680_get_video_mode(gspca_dev);
|
||
if (ret < 0)
|
||
@@ -220,6 +243,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
cam->cam_mode = &sd->mode;
|
||
cam->nmodes = 1;
|
||
|
||
+#if 0 /* The v4l1 driver used to this but I don't think it is necessary */
|
||
+ ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
|
||
+ if (ret < 0) {
|
||
+ PDEBUG(D_ERR, "Set alt 0 failed (%d)", ret);
|
||
+ return ret;
|
||
+ }
|
||
+#endif
|
||
|
||
ret = stv0680_set_video_mode(gspca_dev, sd->orig_mode);
|
||
if (ret < 0)
|
||
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
|
||
index 5d0241b..af73da3 100644
|
||
--- a/drivers/media/video/gspca/stv06xx/stv06xx.c
|
||
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
|
||
@@ -27,6 +27,7 @@
|
||
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
|
||
*/
|
||
|
||
+#include <linux/input.h>
|
||
#include "stv06xx_sensor.h"
|
||
|
||
MODULE_AUTHOR("Erik Andrén");
|
||
@@ -219,6 +220,7 @@ static void stv06xx_dump_bridge(struct sd *sd)
|
||
info("Read 0x%x from address 0x%x", data, i);
|
||
}
|
||
|
||
+ info("Testing stv06xx bridge registers for writability");
|
||
for (i = 0x1400; i < 0x160f; i++) {
|
||
stv06xx_read_bridge(sd, i, &data);
|
||
buf = data;
|
||
@@ -229,7 +231,7 @@ static void stv06xx_dump_bridge(struct sd *sd)
|
||
info("Register 0x%x is read/write", i);
|
||
else if (data != buf)
|
||
info("Register 0x%x is read/write,"
|
||
- "but only partially", i);
|
||
+ " but only partially", i);
|
||
else
|
||
info("Register 0x%x is read-only", i);
|
||
|
||
@@ -426,6 +428,29 @@ frame_data:
|
||
}
|
||
}
|
||
|
||
+#ifdef CONFIG_INPUT
|
||
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data, /* interrupt packet data */
|
||
+ int len) /* interrupt packet length */
|
||
+{
|
||
+ int ret = -EINVAL;
|
||
+
|
||
+ if (len == 1 && data[0] == 0x80) {
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ ret = 0;
|
||
+ }
|
||
+
|
||
+ if (len == 1 && data[0] == 0x88) {
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ ret = 0;
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+#endif
|
||
+
|
||
static int stv06xx_config(struct gspca_dev *gspca_dev,
|
||
const struct usb_device_id *id);
|
||
|
||
@@ -436,7 +461,10 @@ static const struct sd_desc sd_desc = {
|
||
.init = stv06xx_init,
|
||
.start = stv06xx_start,
|
||
.stopN = stv06xx_stopN,
|
||
- .pkt_scan = stv06xx_pkt_scan
|
||
+ .pkt_scan = stv06xx_pkt_scan,
|
||
+#ifdef CONFIG_INPUT
|
||
+ .int_pkt_scan = sd_int_pkt_scan,
|
||
+#endif
|
||
};
|
||
|
||
/* This function is called at probe time */
|
||
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
|
||
index 285221e..180f52c 100644
|
||
--- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
|
||
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
|
||
@@ -150,6 +150,28 @@ static const struct ctrl pb0100_ctrl[] = {
|
||
static struct v4l2_pix_format pb0100_mode[] = {
|
||
/* low res / subsample modes disabled as they are only half res horizontal,
|
||
halving the vertical resolution does not seem to work */
|
||
+#if 0
|
||
+ {
|
||
+ 160,
|
||
+ 120,
|
||
+ V4L2_PIX_FMT_SGRBG8,
|
||
+ V4L2_FIELD_NONE,
|
||
+ .sizeimage = 160 * 120 * 2,
|
||
+ .bytesperline = 160,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = PB0100_CROP_TO_VGA | PB0100_SUBSAMPLE
|
||
+ },
|
||
+ {
|
||
+ 176,
|
||
+ 144,
|
||
+ V4L2_PIX_FMT_SGRBG8,
|
||
+ V4L2_FIELD_NONE,
|
||
+ .sizeimage = 176 * 144 * 2,
|
||
+ .bytesperline = 176,
|
||
+ .colorspace = V4L2_COLORSPACE_SRGB,
|
||
+ .priv = PB0100_SUBSAMPLE
|
||
+ },
|
||
+#endif
|
||
{
|
||
320,
|
||
240,
|
||
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
|
||
index 306b7d7..378c4dd 100644
|
||
--- a/drivers/media/video/gspca/sunplus.c
|
||
+++ b/drivers/media/video/gspca/sunplus.c
|
||
@@ -67,7 +67,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||
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[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -207,6 +207,13 @@ static const struct cmd spca504_pccam600_init_data[] = {
|
||
{0x00, 0x0000, 0x21ad}, /* hue */
|
||
{0x00, 0x001a, 0x21ae}, /* saturation */
|
||
{0x00, 0x0002, 0x21a3}, /* gamma */
|
||
+#if 0
|
||
+ {0xb0, 0x0000, 0x0000}, /* reset auto exposure */
|
||
+ {0x0c, 0x0000, 0x0000}, /* reset auto whiteness */
|
||
+ {0x0c, 0x0004, 0x0000}, /* enable auto whiteness */
|
||
+ {0x30, 0x020f, 0x0001}, /* exposure compensation */
|
||
+ {0x30, 0x01f7, 0x0002}, /* whiteness balance */
|
||
+#endif
|
||
{0x30, 0x0154, 0x0008},
|
||
{0x30, 0x0004, 0x0006},
|
||
{0x30, 0x0258, 0x0009},
|
||
@@ -244,10 +251,20 @@ static const struct cmd spca504A_clicksmart420_init_data[] = {
|
||
{0x00, 0x0000, 0x21ad}, /* hue */
|
||
{0x00, 0x001a, 0x21ae}, /* saturation */
|
||
{0x00, 0x0002, 0x21a3}, /* gamma */
|
||
+#if 1
|
||
{0x30, 0x0004, 0x000a},
|
||
{0xb0, 0x0001, 0x0000},
|
||
+#endif
|
||
|
||
+#if 0
|
||
+ {0xb0, 0x0000, 0x0000}, /* reset auto exposure */
|
||
+ {0x0c, 0x0000, 0x0000}, /* reset auto whiteness */
|
||
+ {0x0c, 0x0004, 0x0000}, /* enable auto whiteness */
|
||
+ {0x30, 0x020f, 0x0001}, /* exposure compensation */
|
||
+ {0x30, 0x01f7, 0x0002}, /* whiteness balance */
|
||
+#endif
|
||
|
||
+#if 1
|
||
{0xa1, 0x0080, 0x0001},
|
||
{0x30, 0x0049, 0x0000},
|
||
{0x30, 0x0060, 0x0005},
|
||
@@ -257,6 +274,7 @@ static const struct cmd spca504A_clicksmart420_init_data[] = {
|
||
{0x00, 0x0013, 0x2301},
|
||
{0x00, 0x0003, 0x2000},
|
||
{0x00, 0x0000, 0x2000},
|
||
+#endif
|
||
|
||
};
|
||
|
||
@@ -267,6 +285,8 @@ static const struct cmd spca504A_clicksmart420_open_data[] = {
|
||
{0x06, 0x0000, 0x0000},
|
||
{0x00, 0x0004, 0x2880},
|
||
{0x00, 0x0001, 0x2881},
|
||
+#if 0
|
||
+/*jfm: overloaded by setup_qtable()*/
|
||
/* look like setting a qTable */
|
||
{0x00, 0x0006, 0x2800},
|
||
{0x00, 0x0004, 0x2801},
|
||
@@ -403,6 +423,7 @@ static const struct cmd spca504A_clicksmart420_open_data[] = {
|
||
{0x00, 0x0028, 0x287d},
|
||
{0x00, 0x0028, 0x287e},
|
||
{0x00, 0x0028, 0x287f},
|
||
+#endif
|
||
|
||
{0xa0, 0x0000, 0x0503},
|
||
};
|
||
@@ -622,6 +643,20 @@ static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
|
||
PDEBUG(D_FRAM, "after wait 0x%04x", notdone);
|
||
}
|
||
|
||
+static void spca504_read_info(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ int i;
|
||
+ u8 info[6];
|
||
+
|
||
+ for (i = 0; i < 6; i++)
|
||
+ info[i] = reg_r_1(gspca_dev, i);
|
||
+ PDEBUG(D_STREAM,
|
||
+ "Read info: %d %d %d %d %d %d."
|
||
+ " Should be 1,0,2,2,0,0",
|
||
+ info[0], info[1], info[2],
|
||
+ info[3], info[4], info[5]);
|
||
+}
|
||
+
|
||
static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
|
||
u8 req,
|
||
u16 idx, u16 val, u16 endcode, u8 count)
|
||
@@ -881,8 +916,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
static int sd_init(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- int i;
|
||
- u8 info[6];
|
||
|
||
switch (sd->bridge) {
|
||
case BRIDGE_SPCA504B:
|
||
@@ -924,15 +957,8 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||
/* case BRIDGE_SPCA504: */
|
||
PDEBUG(D_STREAM, "Opening SPCA504");
|
||
if (sd->subtype == AiptekMiniPenCam13) {
|
||
- /*****************************/
|
||
- for (i = 0; i < 6; i++)
|
||
- info[i] = reg_r_1(gspca_dev, i);
|
||
- PDEBUG(D_STREAM,
|
||
- "Read info: %d %d %d %d %d %d."
|
||
- " Should be 1,0,2,2,0,0",
|
||
- info[0], info[1], info[2],
|
||
- info[3], info[4], info[5]);
|
||
- /* spca504a aiptek */
|
||
+ spca504_read_info(gspca_dev);
|
||
+
|
||
/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
|
||
spca504A_acknowledged_command(gspca_dev, 0x24,
|
||
8, 3, 0x9e, 1);
|
||
@@ -971,8 +997,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
int enable;
|
||
- int i;
|
||
- u8 info[6];
|
||
|
||
/* create the JPEG header */
|
||
sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
|
||
@@ -1008,14 +1032,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
break;
|
||
case BRIDGE_SPCA504:
|
||
if (sd->subtype == AiptekMiniPenCam13) {
|
||
- for (i = 0; i < 6; i++)
|
||
- info[i] = reg_r_1(gspca_dev, i);
|
||
- PDEBUG(D_STREAM,
|
||
- "Read info: %d %d %d %d %d %d."
|
||
- " Should be 1,0,2,2,0,0",
|
||
- info[0], info[1], info[2],
|
||
- info[3], info[4], info[5]);
|
||
- /* spca504a aiptek */
|
||
+ spca504_read_info(gspca_dev);
|
||
+
|
||
/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
|
||
spca504A_acknowledged_command(gspca_dev, 0x24,
|
||
8, 3, 0x9e, 1);
|
||
@@ -1026,13 +1044,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
0, 0, 0x9d, 1);
|
||
} else {
|
||
spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
|
||
- for (i = 0; i < 6; i++)
|
||
- info[i] = reg_r_1(gspca_dev, i);
|
||
- PDEBUG(D_STREAM,
|
||
- "Read info: %d %d %d %d %d %d."
|
||
- " Should be 1,0,2,2,0,0",
|
||
- info[0], info[1], info[2],
|
||
- info[3], info[4], info[5]);
|
||
+ spca504_read_info(gspca_dev);
|
||
spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
|
||
spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
|
||
}
|
||
@@ -1336,6 +1348,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
|
||
{USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
|
||
{USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
|
||
{USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
|
||
+ {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
|
||
{USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
|
||
{USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
|
||
{USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
|
||
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
|
||
index 55ef6a7..07002d3 100644
|
||
--- a/drivers/media/video/gspca/t613.c
|
||
+++ b/drivers/media/video/gspca/t613.c
|
||
@@ -52,6 +52,7 @@ struct sd {
|
||
#define SENSOR_OM6802 0
|
||
#define SENSOR_OTHER 1
|
||
#define SENSOR_TAS5130A 2
|
||
+#define SENSOR_LT168G 3 /* must verify if this is the actual model */
|
||
};
|
||
|
||
/* V4L2 controls supported by the driver */
|
||
@@ -78,7 +79,7 @@ static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_querymenu(struct gspca_dev *gspca_dev,
|
||
struct v4l2_querymenu *menu);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -306,6 +307,17 @@ static const u8 n4_tas5130a[] = {
|
||
0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
|
||
0xc6, 0xda
|
||
};
|
||
+static const u8 n4_lt168g[] = {
|
||
+ 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
|
||
+ 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
|
||
+ 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
|
||
+ 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
|
||
+ 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
|
||
+ 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
|
||
+ 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
|
||
+ 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
|
||
+ 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
|
||
+};
|
||
|
||
static const struct additional_sensor_data sensor_data[] = {
|
||
{ /* 0: OM6802 */
|
||
@@ -317,16 +329,35 @@ static const struct additional_sensor_data sensor_data[] = {
|
||
.reg8e = 0x33,
|
||
.nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
|
||
.data1 =
|
||
+#if 1
|
||
{0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
|
||
0xb3, 0xfc},
|
||
+#else
|
||
+ {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
|
||
+ 0xc8, 0xfc},
|
||
+#endif
|
||
.data2 =
|
||
+#if 1
|
||
{0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
|
||
0xff},
|
||
+#else
|
||
+ {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
|
||
+ 0xe0},
|
||
+#endif
|
||
.data3 =
|
||
+#if 1
|
||
{0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
|
||
0xff},
|
||
+#else
|
||
+ {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
|
||
+ 0xe0},
|
||
+#endif
|
||
.data4 = /*Freq (50/60Hz). Splitted for test purpose */
|
||
+#if 0
|
||
+ {0x66, 0x8a, 0xa8, 0xe8},
|
||
+#else
|
||
{0x66, 0xca, 0xa8, 0xf0},
|
||
+#endif
|
||
.data5 = /* this could be removed later */
|
||
{0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
|
||
.stream =
|
||
@@ -365,21 +396,61 @@ static const struct additional_sensor_data sensor_data[] = {
|
||
.reg8e = 0xb4,
|
||
.nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
|
||
.data1 =
|
||
+#if 1
|
||
{0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
|
||
0xc8, 0xfc},
|
||
+#else
|
||
+ {0xf3, 0xa1, 0x0a, 0x2f, 0xbb, 0x2e, 0x21, 0x68,
|
||
+ 0xea, 0xbf},
|
||
+#endif
|
||
.data2 =
|
||
+#if 1
|
||
{0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
|
||
0xe0},
|
||
+#else
|
||
+ {0x40, 0x80, 0xc0, 0x40, 0x80, 0xc0, 0x4d, 0x97,
|
||
+ 0xe4},
|
||
+#endif
|
||
.data3 =
|
||
+#if 1
|
||
{0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
|
||
0xe0},
|
||
+#else
|
||
+ {0x40, 0x80, 0xc0, 0x41, 0x81, 0xc3, 0x5c, 0x99,
|
||
+ 0xe0},
|
||
+#endif
|
||
.data4 = /* Freq (50/60Hz). Splitted for test purpose */
|
||
+#if 1
|
||
{0x66, 0x00, 0xa8, 0xe8},
|
||
+#else
|
||
+ {0x66, 0x40, 0xa8, 0xf0},
|
||
+#endif
|
||
.data5 =
|
||
+#if 0
|
||
+ {0x0c, 0x03, 0xab, 0x08, 0x81, 0x68},
|
||
+#else
|
||
{0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
|
||
+#endif
|
||
.stream =
|
||
{0x0b, 0x04, 0x0a, 0x40},
|
||
},
|
||
+ { /* 3: LT168G */
|
||
+ .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
|
||
+ .n4 = n4_lt168g,
|
||
+ .n4sz = sizeof n4_lt168g,
|
||
+ .reg80 = 0x7c,
|
||
+ .reg8e = 0xb3,
|
||
+ .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
|
||
+ .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
|
||
+ 0xb0, 0xf4},
|
||
+ .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
|
||
+ 0xff},
|
||
+ .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
|
||
+ 0xff},
|
||
+ .data4 = {0x66, 0x41, 0xa8, 0xf0},
|
||
+ .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
|
||
+ .stream = {0x0b, 0x04, 0x0a, 0x28},
|
||
+ },
|
||
};
|
||
|
||
#define MAX_EFFECTS 7
|
||
@@ -716,6 +787,10 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||
PDEBUG(D_PROBE, "sensor tas5130a");
|
||
sd->sensor = SENSOR_TAS5130A;
|
||
break;
|
||
+ case 0x0802:
|
||
+ PDEBUG(D_PROBE, "sensor lt168g");
|
||
+ sd->sensor = SENSOR_LT168G;
|
||
+ break;
|
||
case 0x0803:
|
||
PDEBUG(D_PROBE, "sensor 'other'");
|
||
sd->sensor = SENSOR_OTHER;
|
||
@@ -758,6 +833,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||
reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
|
||
reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
|
||
|
||
+ if (sd->sensor == SENSOR_LT168G) {
|
||
+ test_byte = reg_r(gspca_dev, 0x80);
|
||
+ PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
|
||
+ test_byte);
|
||
+ reg_w(gspca_dev, 0x6c80);
|
||
+ }
|
||
+
|
||
reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
|
||
reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
|
||
reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
|
||
@@ -782,6 +864,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||
reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
|
||
reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
|
||
|
||
+ if (sd->sensor == SENSOR_LT168G) {
|
||
+ test_byte = reg_r(gspca_dev, 0x80);
|
||
+ PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
|
||
+ test_byte);
|
||
+ reg_w(gspca_dev, 0x6c80);
|
||
+ }
|
||
+
|
||
reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
|
||
reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
|
||
reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
|
||
@@ -888,6 +977,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
case SENSOR_OM6802:
|
||
om6802_sensor_init(gspca_dev);
|
||
break;
|
||
+ case SENSOR_LT168G:
|
||
+ break;
|
||
case SENSOR_OTHER:
|
||
break;
|
||
default:
|
||
@@ -920,6 +1011,15 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
if (sd->sensor == SENSOR_OM6802)
|
||
poll_sensor(gspca_dev);
|
||
|
||
+#if 0
|
||
+ /* restart on each start, just in case, sometimes regs goes wrong
|
||
+ * when using controls from app */
|
||
+ setbrightness(gspca_dev);
|
||
+ setcontrast(gspca_dev);
|
||
+ setcolors(gspca_dev);
|
||
+ seteffect(gspca_dev);
|
||
+ setflip(gspca_dev);
|
||
+#endif
|
||
return 0;
|
||
}
|
||
|
||
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c
|
||
index b74a3b6..0267396 100644
|
||
--- a/drivers/media/video/gspca/tv8532.c
|
||
+++ b/drivers/media/video/gspca/tv8532.c
|
||
@@ -39,7 +39,7 @@ struct sd {
|
||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -228,6 +228,12 @@ static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev)
|
||
0
|
||
};
|
||
|
||
+#if 0
|
||
+ data = reg_r(gspca_dev, 0x0001);
|
||
+ PDEBUG(D_USBI, "register 0x01-> %x", data);
|
||
+ data = reg_r(gspca_dev, 0x0002);
|
||
+ PDEBUG(D_USBI, "register 0x02-> %x", data);
|
||
+#endif
|
||
i = 0;
|
||
do {
|
||
reg_r(gspca_dev, reg_tb[i]);
|
||
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
|
||
index 71921c8..e42e55a 100644
|
||
--- a/drivers/media/video/gspca/vc032x.c
|
||
+++ b/drivers/media/video/gspca/vc032x.c
|
||
@@ -32,10 +32,13 @@ MODULE_LICENSE("GPL");
|
||
struct sd {
|
||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||
|
||
+ u8 brightness;
|
||
+ u8 contrast;
|
||
+ u8 colors;
|
||
u8 hflip;
|
||
u8 vflip;
|
||
u8 lightfreq;
|
||
- u8 sharpness;
|
||
+ s8 sharpness;
|
||
|
||
u8 image_offset;
|
||
|
||
@@ -52,6 +55,7 @@ struct sd {
|
||
#define SENSOR_OV7670 6
|
||
#define SENSOR_PO1200 7
|
||
#define SENSOR_PO3130NC 8
|
||
+#define SENSOR_POxxxx 9
|
||
u8 flags;
|
||
#define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */
|
||
#define FL_HFLIP 0x02 /* mirrored by default */
|
||
@@ -59,6 +63,12 @@ struct sd {
|
||
};
|
||
|
||
/* V4L2 controls supported by the driver */
|
||
+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);
|
||
+static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||
+static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
|
||
+static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
|
||
@@ -68,9 +78,54 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
+#define BRIGHTNESS_IDX 0
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_BRIGHTNESS,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Brightness",
|
||
+ .minimum = 0,
|
||
+ .maximum = 255,
|
||
+ .step = 1,
|
||
+#define BRIGHTNESS_DEF 128
|
||
+ .default_value = BRIGHTNESS_DEF,
|
||
+ },
|
||
+ .set = sd_setbrightness,
|
||
+ .get = sd_getbrightness,
|
||
+ },
|
||
+#define CONTRAST_IDX 1
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_CONTRAST,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Contrast",
|
||
+ .minimum = 0,
|
||
+ .maximum = 255,
|
||
+ .step = 1,
|
||
+#define CONTRAST_DEF 127
|
||
+ .default_value = CONTRAST_DEF,
|
||
+ },
|
||
+ .set = sd_setcontrast,
|
||
+ .get = sd_getcontrast,
|
||
+ },
|
||
+#define COLORS_IDX 2
|
||
+ {
|
||
+ {
|
||
+ .id = V4L2_CID_SATURATION,
|
||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||
+ .name = "Saturation",
|
||
+ .minimum = 1,
|
||
+ .maximum = 127,
|
||
+ .step = 1,
|
||
+#define COLOR_DEF 63
|
||
+ .default_value = COLOR_DEF,
|
||
+ },
|
||
+ .set = sd_setcolors,
|
||
+ .get = sd_getcolors,
|
||
+ },
|
||
/* next 2 controls work with some sensors only */
|
||
-#define HFLIP_IDX 0
|
||
+#define HFLIP_IDX 3
|
||
{
|
||
{
|
||
.id = V4L2_CID_HFLIP,
|
||
@@ -85,7 +140,7 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_sethflip,
|
||
.get = sd_gethflip,
|
||
},
|
||
-#define VFLIP_IDX 1
|
||
+#define VFLIP_IDX 4
|
||
{
|
||
{
|
||
.id = V4L2_CID_VFLIP,
|
||
@@ -100,7 +155,7 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_setvflip,
|
||
.get = sd_getvflip,
|
||
},
|
||
-#define LIGHTFREQ_IDX 2
|
||
+#define LIGHTFREQ_IDX 5
|
||
{
|
||
{
|
||
.id = V4L2_CID_POWER_LINE_FREQUENCY,
|
||
@@ -115,17 +170,16 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_setfreq,
|
||
.get = sd_getfreq,
|
||
},
|
||
-/* po1200 only */
|
||
-#define SHARPNESS_IDX 3
|
||
+#define SHARPNESS_IDX 6
|
||
{
|
||
{
|
||
.id = V4L2_CID_SHARPNESS,
|
||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||
.name = "Sharpness",
|
||
- .minimum = 0,
|
||
+ .minimum = -1,
|
||
.maximum = 2,
|
||
.step = 1,
|
||
-#define SHARPNESS_DEF 1
|
||
+#define SHARPNESS_DEF -1
|
||
.default_value = SHARPNESS_DEF,
|
||
},
|
||
.set = sd_setsharpness,
|
||
@@ -133,6 +187,42 @@ static struct ctrl sd_ctrls[] = {
|
||
},
|
||
};
|
||
|
||
+/* table of the disabled controls */
|
||
+static u32 ctrl_dis[] = {
|
||
+/* SENSOR_HV7131R 0 */
|
||
+ (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
|
||
+ | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
|
||
+ | (1 << SHARPNESS_IDX),
|
||
+/* SENSOR_MI0360 1 */
|
||
+ (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
|
||
+ | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
|
||
+ | (1 << SHARPNESS_IDX),
|
||
+/* SENSOR_MI1310_SOC 2 */
|
||
+ (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
|
||
+ | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
|
||
+/* SENSOR_MI1320 3 */
|
||
+ (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
|
||
+ | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
|
||
+/* SENSOR_MI1320_SOC 4 */
|
||
+ (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
|
||
+ | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
|
||
+/* SENSOR_OV7660 5 */
|
||
+ (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
|
||
+ | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
|
||
+/* SENSOR_OV7670 6 */
|
||
+ (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
|
||
+ | (1 << SHARPNESS_IDX),
|
||
+/* SENSOR_PO1200 7 */
|
||
+ (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
|
||
+ | (1 << LIGHTFREQ_IDX),
|
||
+/* SENSOR_PO3130NC 8 */
|
||
+ (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
|
||
+ | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
|
||
+ | (1 << SHARPNESS_IDX),
|
||
+/* SENSOR_POxxxx 9 */
|
||
+ (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX),
|
||
+};
|
||
+
|
||
static const struct v4l2_pix_format vc0321_mode[] = {
|
||
{320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
|
||
.bytesperline = 320,
|
||
@@ -163,16 +253,37 @@ static const struct v4l2_pix_format vc0323_mode[] = {
|
||
.priv = 2},
|
||
};
|
||
static const struct v4l2_pix_format bi_mode[] = {
|
||
+#if 0 /* JPEG vc0323 */
|
||
+ {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 320,
|
||
+ .sizeimage = 320 * 240 * 3 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG,
|
||
+ .priv = 5},
|
||
+#endif
|
||
{320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
|
||
.bytesperline = 320,
|
||
.sizeimage = 320 * 240 * 2,
|
||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||
.priv = 2},
|
||
+#if 0 /* JPEG vc0323 */
|
||
+ {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 640,
|
||
+ .sizeimage = 640 * 480 * 3 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG,
|
||
+ .priv = 4},
|
||
+#endif
|
||
{640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
|
||
.bytesperline = 640,
|
||
.sizeimage = 640 * 480 * 2,
|
||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||
.priv = 1},
|
||
+#if 0 /* JPEG vc0323 */
|
||
+ {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 1280,
|
||
+ .sizeimage = 1280 * 1024 * 1 / 4 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG,
|
||
+ .priv = 3},
|
||
+#endif
|
||
{1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
|
||
.bytesperline = 1280,
|
||
.sizeimage = 1280 * 1024 * 2,
|
||
@@ -215,7 +326,7 @@ static const u8 mi0360_initVGA_JPG[][4] = {
|
||
{0xb3, 0x15, 0x00, 0xcc},
|
||
{0xb3, 0x16, 0x02, 0xcc},
|
||
{0xb3, 0x17, 0x7f, 0xcc},
|
||
- {0xb3, 0x35, 0xdd, 0xcc},
|
||
+ {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */
|
||
{0xb3, 0x34, 0x02, 0xcc},
|
||
{0xb3, 0x00, 0x25, 0xcc},
|
||
{0xbc, 0x00, 0x71, 0xcc},
|
||
@@ -435,7 +546,7 @@ static const u8 mi1310_socinitVGA_JPG[][4] = {
|
||
{0xb3, 0x08, 0x01, 0xcc},
|
||
{0xb3, 0x09, 0x0c, 0xcc},
|
||
{0xb3, 0x34, 0x02, 0xcc},
|
||
- {0xb3, 0x35, 0xdd, 0xcc},
|
||
+ {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */
|
||
{0xb3, 0x02, 0x00, 0xcc},
|
||
{0xb3, 0x03, 0x0a, 0xcc},
|
||
{0xb3, 0x04, 0x05, 0xcc},
|
||
@@ -681,7 +792,11 @@ static const u8 mi1310_soc_InitSXGA_JPG[][4] = {
|
||
{0xc8, 0x9f, 0x0b, 0xbb},
|
||
{0x5b, 0x00, 0x01, 0xbb},
|
||
{0xf0, 0x00, 0x00, 0xbb},
|
||
+#if 1
|
||
{0x20, 0x03, 0x02, 0xbb}, /* h/v flip */
|
||
+#else
|
||
+ {0x20, 0x03, 0x03, 0xbb}, /* h/v flip */
|
||
+#endif
|
||
{0xf0, 0x00, 0x01, 0xbb},
|
||
{0x05, 0x00, 0x07, 0xbb},
|
||
{0x34, 0x00, 0x00, 0xbb},
|
||
@@ -860,7 +975,8 @@ static const u8 mi1320_initVGA_data[][4] = {
|
||
{0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
|
||
{0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
|
||
{0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc},
|
||
- {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc},
|
||
+ {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */
|
||
+ {0xb3, 0x02, 0x00, 0xcc},
|
||
{0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
|
||
{0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
|
||
{0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc},
|
||
@@ -901,7 +1017,8 @@ static const u8 mi1320_initVGA_data[][4] = {
|
||
{0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb},
|
||
{0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb},
|
||
{0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb},
|
||
- {0x08, 0x00, 0x27, 0xbb}, {0x20, 0x01, 0x03, 0xbb},
|
||
+ {0x08, 0x00, 0x27, 0xbb},
|
||
+ {0x20, 0x01, 0x00, 0xbb}, /* h/v flips - was 03 */
|
||
{0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb},
|
||
{0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb},
|
||
{0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb},
|
||
@@ -1012,7 +1129,7 @@ static const u8 mi1320_soc_InitVGA[][4] = {
|
||
{0xb3, 0x08, 0x01, 0xcc},
|
||
{0xb3, 0x09, 0x0c, 0xcc},
|
||
{0xb3, 0x34, 0x02, 0xcc},
|
||
- {0xb3, 0x35, 0xc8, 0xcc},
|
||
+ {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */
|
||
{0xb3, 0x02, 0x00, 0xcc},
|
||
{0xb3, 0x03, 0x0a, 0xcc},
|
||
{0xb3, 0x04, 0x05, 0xcc},
|
||
@@ -1103,6 +1220,123 @@ static const u8 mi1320_soc_InitVGA[][4] = {
|
||
{0xb3, 0x5c, 0x01, 0xcc},
|
||
{}
|
||
};
|
||
+#if 0 /* JPEG vc0323 */
|
||
+static const u8 mi1320_soc_InitVGA_JPG[][4] = {
|
||
+ {0xb3, 0x01, 0x01, 0xcc},
|
||
+ {0xb0, 0x03, 0x19, 0xcc},
|
||
+ {0xb0, 0x04, 0x02, 0xcc},
|
||
+ {0x00, 0x00, 0x30, 0xdd},
|
||
+ {0xb3, 0x00, 0x64, 0xcc},
|
||
+ {0xb3, 0x00, 0x67, 0xcc},
|
||
+ {0xb3, 0x05, 0x01, 0xcc},
|
||
+ {0xb3, 0x06, 0x01, 0xcc},
|
||
+ {0xb3, 0x08, 0x01, 0xcc},
|
||
+ {0xb3, 0x09, 0x0c, 0xcc},
|
||
+ {0xb3, 0x34, 0x02, 0xcc},
|
||
+ {0xb3, 0x35, 0xc8, 0xcc},
|
||
+ {0xb3, 0x02, 0x00, 0xcc},
|
||
+ {0xb3, 0x03, 0x0a, 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, 0x17, 0x7f, 0xcc},
|
||
+ {0xb3, 0x00, 0x67, 0xcc},
|
||
+ {0xb8, 0x00, 0x00, 0xcc},
|
||
+ {0xbc, 0x00, 0x71, 0xcc},
|
||
+ {0xbc, 0x01, 0x01, 0xcc},
|
||
+ {0xb3, 0x5c, 0x01, 0xcc},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x00, 0x00, 0x10, 0xdd},
|
||
+ {0xc8, 0x00, 0x00, 0xbb},
|
||
+ {0x00, 0x00, 0x30, 0xdd},
|
||
+ {0xf0, 0x00, 0x00, 0xbb},
|
||
+ {0x00, 0x00, 0x10, 0xdd},
|
||
+ {0x07, 0x00, 0xe0, 0xbb},
|
||
+ {0x08, 0x00, 0x0b, 0xbb},
|
||
+ {0x21, 0x00, 0x0c, 0xbb},
|
||
+ {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
|
||
+ {0xb6, 0x00, 0x00, 0xcc},
|
||
+ {0xb6, 0x03, 0x02, 0xcc},
|
||
+ {0xb6, 0x02, 0x80, 0xcc},
|
||
+ {0xb6, 0x05, 0x01, 0xcc},
|
||
+ {0xb6, 0x04, 0xe0, 0xcc},
|
||
+ {0xb6, 0x12, 0xf8, 0xcc},
|
||
+ {0xb6, 0x13, 0x05, 0xcc},
|
||
+ {0xb6, 0x18, 0x02, 0xcc},
|
||
+ {0xb6, 0x17, 0x58, 0xcc},
|
||
+ {0xb6, 0x16, 0x00, 0xcc},
|
||
+ {0xb6, 0x22, 0x12, 0xcc},
|
||
+ {0xb6, 0x23, 0x0b, 0xcc},
|
||
+ {0xbf, 0xc0, 0x39, 0xcc},
|
||
+ {0xbf, 0xc1, 0x04, 0xcc},
|
||
+ {0xbf, 0xcc, 0x00, 0xcc},
|
||
+ {0xb3, 0x01, 0x41, 0xcc},
|
||
+ {0xf0, 0x00, 0x00, 0xbb},
|
||
+ {0x05, 0x01, 0x78, 0xbb},
|
||
+ {0x06, 0x00, 0x11, 0xbb},
|
||
+ {0x07, 0x01, 0x42, 0xbb},
|
||
+ {0x08, 0x00, 0x11, 0xbb},
|
||
+ {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
|
||
+ {0x21, 0x80, 0x00, 0xbb},
|
||
+ {0x22, 0x0d, 0x0f, 0xbb},
|
||
+ {0x24, 0x80, 0x00, 0xbb},
|
||
+ {0x59, 0x00, 0xff, 0xbb},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x39, 0x03, 0xca, 0xbb},
|
||
+ {0x3a, 0x06, 0x80, 0xbb},
|
||
+ {0x3b, 0x01, 0x52, 0xbb},
|
||
+ {0x3c, 0x05, 0x40, 0xbb},
|
||
+ {0x57, 0x01, 0x9c, 0xbb},
|
||
+ {0x58, 0x01, 0xee, 0xbb},
|
||
+ {0x59, 0x00, 0xf0, 0xbb},
|
||
+ {0x5a, 0x01, 0x20, 0xbb},
|
||
+ {0x5c, 0x1d, 0x17, 0xbb},
|
||
+ {0x5d, 0x22, 0x1c, 0xbb},
|
||
+ {0x64, 0x1e, 0x1c, 0xbb},
|
||
+ {0x5b, 0x00, 0x00, 0xbb},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x22, 0xa0, 0x78, 0xbb},
|
||
+ {0x23, 0xa0, 0x78, 0xbb},
|
||
+ {0x24, 0x7f, 0x00, 0xbb},
|
||
+ {0x28, 0xea, 0x02, 0xbb},
|
||
+ {0x29, 0x86, 0x7a, 0xbb},
|
||
+ {0x5e, 0x52, 0x4c, 0xbb},
|
||
+ {0x5f, 0x20, 0x24, 0xbb},
|
||
+ {0x60, 0x00, 0x02, 0xbb},
|
||
+ {0x02, 0x00, 0xee, 0xbb},
|
||
+ {0x03, 0x39, 0x23, 0xbb},
|
||
+ {0x04, 0x07, 0x24, 0xbb},
|
||
+ {0x09, 0x00, 0xc0, 0xbb},
|
||
+ {0x0a, 0x00, 0x79, 0xbb},
|
||
+ {0x0b, 0x00, 0x04, 0xbb},
|
||
+ {0x0c, 0x00, 0x5c, 0xbb},
|
||
+ {0x0d, 0x00, 0xd9, 0xbb},
|
||
+ {0x0e, 0x00, 0x53, 0xbb},
|
||
+ {0x0f, 0x00, 0x21, 0xbb},
|
||
+ {0x10, 0x00, 0xa4, 0xbb},
|
||
+ {0x11, 0x00, 0xe5, 0xbb},
|
||
+ {0x15, 0x00, 0x00, 0xbb},
|
||
+ {0x16, 0x00, 0x00, 0xbb},
|
||
+ {0x17, 0x00, 0x00, 0xbb},
|
||
+ {0x18, 0x00, 0x00, 0xbb},
|
||
+ {0x19, 0x00, 0x00, 0xbb},
|
||
+ {0x1a, 0x00, 0x00, 0xbb},
|
||
+ {0x1b, 0x00, 0x00, 0xbb},
|
||
+ {0x1c, 0x00, 0x00, 0xbb},
|
||
+ {0x1d, 0x00, 0x00, 0xbb},
|
||
+ {0x1e, 0x00, 0x00, 0xbb},
|
||
+ {0xf0, 0x00, 0x01, 0xbb},
|
||
+ {0x06, 0xe0, 0x0e, 0xbb},
|
||
+ {0x06, 0x60, 0x0e, 0xbb},
|
||
+ {0xb3, 0x5c, 0x01, 0xcc},
|
||
+ {}
|
||
+};
|
||
+#endif
|
||
static const u8 mi1320_soc_InitQVGA[][4] = {
|
||
{0xb3, 0x01, 0x01, 0xcc},
|
||
{0xb0, 0x03, 0x19, 0xcc},
|
||
@@ -1216,6 +1450,272 @@ static const u8 mi1320_soc_InitQVGA[][4] = {
|
||
{0xb3, 0x5c, 0x01, 0xcc},
|
||
{}
|
||
};
|
||
+#if 0 /* JPEG vc0323 */
|
||
+static const u8 mi1320_soc_InitQVGA_JPG[][4] = {
|
||
+ {0xb3, 0x01, 0x01, 0xcc},
|
||
+ {0xb0, 0x03, 0x19, 0xcc},
|
||
+ {0xb0, 0x04, 0x02, 0xcc},
|
||
+ {0x00, 0x00, 0x30, 0xdd},
|
||
+ {0xb3, 0x00, 0x64, 0xcc},
|
||
+ {0xb3, 0x00, 0x67, 0xcc},
|
||
+ {0xb3, 0x05, 0x01, 0xcc},
|
||
+ {0xb3, 0x06, 0x01, 0xcc},
|
||
+ {0xb3, 0x08, 0x01, 0xcc},
|
||
+ {0xb3, 0x09, 0x0c, 0xcc},
|
||
+ {0xb3, 0x34, 0x02, 0xcc},
|
||
+ {0xb3, 0x35, 0xc8, 0xcc},
|
||
+ {0xb3, 0x02, 0x00, 0xcc},
|
||
+ {0xb3, 0x03, 0x0a, 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, 0x17, 0x7f, 0xcc},
|
||
+ {0xb3, 0x00, 0x67, 0xcc},
|
||
+ {0xb8, 0x00, 0x00, 0xcc},
|
||
+ {0xbc, 0x00, 0xd1, 0xcc},
|
||
+ {0xbc, 0x01, 0x01, 0xcc},
|
||
+ {0xb3, 0x5c, 0x01, 0xcc},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x00, 0x00, 0x10, 0xdd},
|
||
+ {0xc8, 0x00, 0x00, 0xbb},
|
||
+ {0x00, 0x00, 0x30, 0xdd},
|
||
+ {0xf0, 0x00, 0x00, 0xbb},
|
||
+ {0x00, 0x00, 0x10, 0xdd},
|
||
+ {0x07, 0x00, 0xe0, 0xbb},
|
||
+ {0x08, 0x00, 0x0b, 0xbb},
|
||
+ {0x21, 0x00, 0x0c, 0xbb},
|
||
+ {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
|
||
+ {0xb6, 0x00, 0x00, 0xcc},
|
||
+ {0xb6, 0x03, 0x01, 0xcc},
|
||
+ {0xb6, 0x02, 0x40, 0xcc},
|
||
+ {0xb6, 0x05, 0x00, 0xcc},
|
||
+ {0xb6, 0x04, 0xf0, 0xcc},
|
||
+ {0xb6, 0x12, 0xf8, 0xcc},
|
||
+ {0xb6, 0x13, 0x05, 0xcc},
|
||
+ {0xb6, 0x18, 0x00, 0xcc},
|
||
+ {0xb6, 0x17, 0x96, 0xcc},
|
||
+ {0xb6, 0x16, 0x00, 0xcc},
|
||
+ {0xb6, 0x22, 0x12, 0xcc},
|
||
+ {0xb6, 0x23, 0x0b, 0xcc},
|
||
+ {0xbf, 0xc0, 0x39, 0xcc},
|
||
+ {0xbf, 0xc1, 0x04, 0xcc},
|
||
+ {0xbf, 0xcc, 0x00, 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},
|
||
+ {0xb3, 0x01, 0x41, 0xcc},
|
||
+ {0xf0, 0x00, 0x00, 0xbb},
|
||
+ {0x05, 0x01, 0x78, 0xbb},
|
||
+ {0x06, 0x00, 0x11, 0xbb},
|
||
+ {0x07, 0x01, 0x42, 0xbb},
|
||
+ {0x08, 0x00, 0x11, 0xbb},
|
||
+ {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
|
||
+ {0x21, 0x80, 0x00, 0xbb},
|
||
+ {0x22, 0x0d, 0x0f, 0xbb},
|
||
+ {0x24, 0x80, 0x00, 0xbb},
|
||
+ {0x59, 0x00, 0xff, 0xbb},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x39, 0x03, 0xca, 0xbb},
|
||
+ {0x3a, 0x06, 0x80, 0xbb},
|
||
+ {0x3b, 0x01, 0x52, 0xbb},
|
||
+ {0x3c, 0x05, 0x40, 0xbb},
|
||
+ {0x57, 0x01, 0x9c, 0xbb},
|
||
+ {0x58, 0x01, 0xee, 0xbb},
|
||
+ {0x59, 0x00, 0xf0, 0xbb},
|
||
+ {0x5a, 0x01, 0x20, 0xbb},
|
||
+ {0x5c, 0x1d, 0x17, 0xbb},
|
||
+ {0x5d, 0x22, 0x1c, 0xbb},
|
||
+ {0x64, 0x1e, 0x1c, 0xbb},
|
||
+ {0x5b, 0x00, 0x00, 0xbb},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x22, 0xa0, 0x78, 0xbb},
|
||
+ {0x23, 0xa0, 0x78, 0xbb},
|
||
+ {0x24, 0x7f, 0x00, 0xbb},
|
||
+ {0x28, 0xea, 0x02, 0xbb},
|
||
+ {0x29, 0x86, 0x7a, 0xbb},
|
||
+ {0x5e, 0x52, 0x4c, 0xbb},
|
||
+ {0x5f, 0x20, 0x24, 0xbb},
|
||
+ {0x60, 0x00, 0x02, 0xbb},
|
||
+ {0x02, 0x00, 0xee, 0xbb},
|
||
+ {0x03, 0x39, 0x23, 0xbb},
|
||
+ {0x04, 0x07, 0x24, 0xbb},
|
||
+ {0x09, 0x00, 0xc0, 0xbb},
|
||
+ {0x0a, 0x00, 0x79, 0xbb},
|
||
+ {0x0b, 0x00, 0x04, 0xbb},
|
||
+ {0x0c, 0x00, 0x5c, 0xbb},
|
||
+ {0x0d, 0x00, 0xd9, 0xbb},
|
||
+ {0x0e, 0x00, 0x53, 0xbb},
|
||
+ {0x0f, 0x00, 0x21, 0xbb},
|
||
+ {0x10, 0x00, 0xa4, 0xbb},
|
||
+ {0x11, 0x00, 0xe5, 0xbb},
|
||
+ {0x15, 0x00, 0x00, 0xbb},
|
||
+ {0x16, 0x00, 0x00, 0xbb},
|
||
+ {0x17, 0x00, 0x00, 0xbb},
|
||
+ {0x18, 0x00, 0x00, 0xbb},
|
||
+ {0x19, 0x00, 0x00, 0xbb},
|
||
+ {0x1a, 0x00, 0x00, 0xbb},
|
||
+ {0x1b, 0x00, 0x00, 0xbb},
|
||
+ {0x1c, 0x00, 0x00, 0xbb},
|
||
+ {0x1d, 0x00, 0x00, 0xbb},
|
||
+ {0x1e, 0x00, 0x00, 0xbb},
|
||
+ {0xf0, 0x00, 0x01, 0xbb},
|
||
+ {0x06, 0xe0, 0x0e, 0xbb},
|
||
+ {0x06, 0x60, 0x0e, 0xbb},
|
||
+ {0xb3, 0x5c, 0x01, 0xcc},
|
||
+ {}
|
||
+};
|
||
+#endif
|
||
+#if 0 /* JPEG vc0323 */
|
||
+static const u8 mi1320_soc_InitSXGA_JPG[][4] = {
|
||
+ {0xb3, 0x01, 0x01, 0xcc},
|
||
+ {0xb0, 0x03, 0x19, 0xcc},
|
||
+ {0xb0, 0x04, 0x02, 0xcc},
|
||
+ {0x00, 0x00, 0x33, 0xdd},
|
||
+ {0xb3, 0x00, 0x64, 0xcc},
|
||
+ {0xb3, 0x00, 0x67, 0xcc},
|
||
+ {0xb3, 0x05, 0x00, 0xcc},
|
||
+ {0xb3, 0x06, 0x00, 0xcc},
|
||
+ {0xb3, 0x08, 0x01, 0xcc},
|
||
+ {0xb3, 0x09, 0x0c, 0xcc},
|
||
+ {0xb3, 0x34, 0x02, 0xcc},
|
||
+ {0xb3, 0x35, 0xc8, 0xcc},
|
||
+ {0xb3, 0x02, 0x00, 0xcc},
|
||
+ {0xb3, 0x03, 0x0a, 0xcc},
|
||
+ {0xb3, 0x04, 0x05, 0xcc},
|
||
+ {0xb3, 0x20, 0x00, 0xcc},
|
||
+ {0xb3, 0x21, 0x00, 0xcc},
|
||
+ {0xb3, 0x22, 0x04, 0xcc},
|
||
+ {0xb3, 0x23, 0x00, 0xcc},
|
||
+ {0xb3, 0x14, 0x00, 0xcc},
|
||
+ {0xb3, 0x15, 0x00, 0xcc},
|
||
+ {0xb3, 0x16, 0x04, 0xcc},
|
||
+ {0xb3, 0x17, 0xff, 0xcc},
|
||
+ {0xb3, 0x00, 0x67, 0xcc},
|
||
+ {0xbc, 0x00, 0x71, 0xcc},
|
||
+ {0xbc, 0x01, 0x01, 0xcc},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x00, 0x00, 0x30, 0xdd},
|
||
+ {0xc8, 0x9f, 0x0b, 0xbb},
|
||
+ {0x00, 0x00, 0x20, 0xdd},
|
||
+ {0x5b, 0x00, 0x01, 0xbb},
|
||
+ {0x00, 0x00, 0x20, 0xdd},
|
||
+ {0xf0, 0x00, 0x00, 0xbb},
|
||
+ {0x00, 0x00, 0x30, 0xdd},
|
||
+ {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
|
||
+ {0x00, 0x00, 0x20, 0xdd},
|
||
+ {0xb6, 0x00, 0x00, 0xcc},
|
||
+ {0xb6, 0x03, 0x05, 0xcc},
|
||
+ {0xb6, 0x02, 0x00, 0xcc},
|
||
+ {0xb6, 0x05, 0x04, 0xcc},
|
||
+ {0xb6, 0x04, 0x00, 0xcc},
|
||
+ {0xb6, 0x12, 0xf8, 0xcc},
|
||
+ {0xb6, 0x13, 0x29, 0xcc},
|
||
+ {0xb6, 0x18, 0x0a, 0xcc},
|
||
+ {0xb6, 0x17, 0x00, 0xcc},
|
||
+ {0xb6, 0x16, 0x00, 0xcc},
|
||
+ {0xb6, 0x22, 0x12, 0xcc},
|
||
+ {0xb6, 0x23, 0x0b, 0xcc},
|
||
+ {0xbf, 0xc0, 0x39, 0xcc},
|
||
+ {0xbf, 0xc1, 0x04, 0xcc},
|
||
+ {0xbf, 0xcc, 0x00, 0xcc},
|
||
+ {0xb3, 0x5c, 0x01, 0xcc},
|
||
+ {0xb3, 0x01, 0x41, 0xcc},
|
||
+ {0xf0, 0x00, 0x00, 0xbb},
|
||
+ {0x05, 0x01, 0x78, 0xbb},
|
||
+ {0x06, 0x00, 0x11, 0xbb},
|
||
+ {0x07, 0x01, 0x42, 0xbb},
|
||
+ {0x08, 0x00, 0x11, 0xbb},
|
||
+ {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
|
||
+ {0x21, 0x80, 0x00, 0xbb},
|
||
+ {0x22, 0x0d, 0x0f, 0xbb},
|
||
+ {0x24, 0x80, 0x00, 0xbb},
|
||
+ {0x59, 0x00, 0xff, 0xbb},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x39, 0x03, 0xca, 0xbb},
|
||
+ {0x3a, 0x06, 0x80, 0xbb},
|
||
+ {0x3b, 0x01, 0x52, 0xbb},
|
||
+ {0x3c, 0x05, 0x40, 0xbb},
|
||
+ {0x57, 0x01, 0x9c, 0xbb},
|
||
+ {0x58, 0x01, 0xee, 0xbb},
|
||
+ {0x59, 0x00, 0xf0, 0xbb},
|
||
+ {0x5a, 0x01, 0x20, 0xbb},
|
||
+ {0x5c, 0x1d, 0x17, 0xbb},
|
||
+ {0x5d, 0x22, 0x1c, 0xbb},
|
||
+ {0x64, 0x1e, 0x1c, 0xbb},
|
||
+ {0x5b, 0x00, 0x00, 0xbb},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x22, 0xa0, 0x78, 0xbb},
|
||
+ {0x23, 0xa0, 0x78, 0xbb},
|
||
+ {0x24, 0x7f, 0x00, 0xbb},
|
||
+ {0x28, 0xea, 0x02, 0xbb},
|
||
+ {0x29, 0x86, 0x7a, 0xbb},
|
||
+ {0x5e, 0x52, 0x4c, 0xbb},
|
||
+ {0x5f, 0x20, 0x24, 0xbb},
|
||
+ {0x60, 0x00, 0x02, 0xbb},
|
||
+ {0x02, 0x00, 0xee, 0xbb},
|
||
+ {0x03, 0x39, 0x23, 0xbb},
|
||
+ {0x04, 0x07, 0x24, 0xbb},
|
||
+ {0x09, 0x00, 0xc0, 0xbb},
|
||
+ {0x0a, 0x00, 0x79, 0xbb},
|
||
+ {0x0b, 0x00, 0x04, 0xbb},
|
||
+ {0x0c, 0x00, 0x5c, 0xbb},
|
||
+ {0x0d, 0x00, 0xd9, 0xbb},
|
||
+ {0x0e, 0x00, 0x53, 0xbb},
|
||
+ {0x0f, 0x00, 0x21, 0xbb},
|
||
+ {0x10, 0x00, 0xa4, 0xbb},
|
||
+ {0x11, 0x00, 0xe5, 0xbb},
|
||
+ {0x15, 0x00, 0x00, 0xbb},
|
||
+ {0x16, 0x00, 0x00, 0xbb},
|
||
+ {0x17, 0x00, 0x00, 0xbb},
|
||
+ {0x18, 0x00, 0x00, 0xbb},
|
||
+ {0x19, 0x00, 0x00, 0xbb},
|
||
+ {0x1a, 0x00, 0x00, 0xbb},
|
||
+ {0x1b, 0x00, 0x00, 0xbb},
|
||
+ {0x1c, 0x00, 0x00, 0xbb},
|
||
+ {0x1d, 0x00, 0x00, 0xbb},
|
||
+ {0x1e, 0x00, 0x00, 0xbb},
|
||
+ {0xf0, 0x00, 0x01, 0xbb},
|
||
+ {0x06, 0xe0, 0x0e, 0xbb},
|
||
+ {0x06, 0x60, 0x0e, 0xbb},
|
||
+ {0xb3, 0x5c, 0x01, 0xcc},
|
||
+ {0xf0, 0x00, 0x00, 0xbb},
|
||
+ {0x05, 0x01, 0x13, 0xbb},
|
||
+ {0x06, 0x00, 0x11, 0xbb},
|
||
+ {0x07, 0x00, 0x85, 0xbb},
|
||
+ {0x08, 0x00, 0x27, 0xbb},
|
||
+ {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
|
||
+ {0x21, 0x80, 0x00, 0xbb},
|
||
+ {0x22, 0x0d, 0x0f, 0xbb},
|
||
+ {0x24, 0x80, 0x00, 0xbb},
|
||
+ {0x59, 0x00, 0xff, 0xbb},
|
||
+ {0xf0, 0x00, 0x02, 0xbb},
|
||
+ {0x39, 0x03, 0x0d, 0xbb},
|
||
+ {0x3a, 0x06, 0x1b, 0xbb},
|
||
+ {0x3b, 0x00, 0x95, 0xbb},
|
||
+ {0x3c, 0x04, 0xdb, 0xbb},
|
||
+ {0x57, 0x02, 0x00, 0xbb},
|
||
+ {0x58, 0x02, 0x66, 0xbb},
|
||
+ {0x59, 0x00, 0xff, 0xbb},
|
||
+ {0x5a, 0x01, 0x33, 0xbb},
|
||
+ {0x5c, 0x12, 0x0d, 0xbb},
|
||
+ {0x5d, 0x16, 0x11, 0xbb},
|
||
+ {0x64, 0x5e, 0x1c, 0xbb},
|
||
+ {0x2f, 0x90, 0x00, 0xbb},
|
||
+ {}
|
||
+};
|
||
+#endif
|
||
static const u8 mi1320_soc_InitSXGA[][4] = {
|
||
{0xb3, 0x01, 0x01, 0xcc},
|
||
{0xb0, 0x03, 0x19, 0xcc},
|
||
@@ -1359,7 +1859,8 @@ static const u8 po3130_initVGA_data[][4] = {
|
||
{0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc},
|
||
{0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
|
||
{0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
|
||
- {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc},
|
||
+ {0xb3, 0x34, 0x01, 0xcc},
|
||
+ {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */
|
||
{0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc},
|
||
{0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc},
|
||
{0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
|
||
@@ -1532,8 +2033,13 @@ static const u8 po3130_initQVGA_data[][4] = {
|
||
};
|
||
|
||
static const u8 hv7131r_gamma[17] = {
|
||
+#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
|
||
@@ -1561,7 +2067,7 @@ static const u8 hv7131r_initVGA_data[][4] = {
|
||
{0xb3, 0x16, 0x02, 0xcc},
|
||
{0xb3, 0x17, 0x7f, 0xcc},
|
||
{0xb3, 0x34, 0x01, 0xcc},
|
||
- {0xb3, 0x35, 0x91, 0xcc},
|
||
+ {0xb3, 0x35, 0x91, 0xcc}, /* i2c add: 11 */
|
||
{0xb3, 0x00, 0x27, 0xcc},
|
||
{0xbc, 0x00, 0x73, 0xcc},
|
||
{0xb8, 0x00, 0x23, 0xcc},
|
||
@@ -1747,7 +2253,8 @@ static const u8 ov7660_initVGA_data[][4] = {
|
||
{0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc},
|
||
{0xb3, 0x1f, 0x02, 0xcc},
|
||
{0xb3, 0x34, 0x01, 0xcc},
|
||
- {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
|
||
+ {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */
|
||
+ {0xb3, 0x00, 0x26, 0xcc},
|
||
{0xb8, 0x00, 0x33, 0xcc}, /* 13 */
|
||
{0xb8, 0x01, 0x7d, 0xcc},
|
||
{0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
|
||
@@ -1883,7 +2390,8 @@ static const u8 ov7670_initVGA_JPG[][4] = {
|
||
{0x00, 0x00, 0x10, 0xdd},
|
||
{0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd},
|
||
{0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc},
|
||
- {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
|
||
+ {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */
|
||
+ {0xb3, 0x34, 0x01, 0xcc},
|
||
{0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc},
|
||
{0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc},
|
||
{0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc},
|
||
@@ -2143,14 +2651,26 @@ static const u8 ov7670_initQVGA_JPG[][4] = {
|
||
|
||
/* PO1200 - values from usbvm326.inf and ms-win trace */
|
||
static const u8 po1200_gamma[17] = {
|
||
+#if 1
|
||
0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
|
||
0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
|
||
+#else
|
||
+/*ms-win trace*/
|
||
+ 0x01, 0x0b, 0x1e, 0x38, 0x51, 0x6b, 0x83, 0x9a, 0xaf,
|
||
+ 0xc1, 0xd0, 0xdd, 0xe8, 0xf2, 0xf9, 0xff, 0xff
|
||
+#endif
|
||
};
|
||
static const u8 po1200_matrix[9] = {
|
||
0x60, 0xf9, 0xe5, 0xe7, 0x50, 0x05, 0xf3, 0xe6, 0x5e
|
||
};
|
||
static const u8 po1200_initVGA_data[][4] = {
|
||
{0xb0, 0x03, 0x19, 0xcc}, /* reset? */
|
||
+#if 0
|
||
+ {0x00, 0x00, 0x64, 0xdd},
|
||
+ {0xb3, 0x49, 0x11, 0xcc},
|
||
+ {0x00, 0x00, 0x33, 0xdd},
|
||
+/*read b349*/
|
||
+#endif
|
||
{0xb0, 0x03, 0x19, 0xcc},
|
||
/* {0x00, 0x00, 0x33, 0xdd}, */
|
||
{0xb0, 0x04, 0x02, 0xcc},
|
||
@@ -2181,7 +2701,7 @@ static const u8 po1200_initVGA_data[][4] = {
|
||
{0xb0, 0x54, 0x13, 0xcc},
|
||
{0xb3, 0x00, 0x67, 0xcc},
|
||
{0xb3, 0x34, 0x01, 0xcc},
|
||
- {0xb3, 0x35, 0xdc, 0xcc},
|
||
+ {0xb3, 0x35, 0xdc, 0xcc}, /* i2c add: 5c */
|
||
{0x00, 0x03, 0x00, 0xaa},
|
||
{0x00, 0x12, 0x05, 0xaa},
|
||
{0x00, 0x13, 0x02, 0xaa},
|
||
@@ -2346,7 +2866,12 @@ static const u8 po1200_initVGA_data[][4] = {
|
||
{0x00, 0xe2, 0x01, 0xaa},
|
||
{0x00, 0xd6, 0x40, 0xaa},
|
||
{0x00, 0xe4, 0x40, 0xaa},
|
||
+#if 1
|
||
{0x00, 0xa8, 0x8f, 0xaa},
|
||
+#else
|
||
+/*modified later*/
|
||
+ {0x00, 0xa8, 0x9f, 0xaa},
|
||
+#endif
|
||
{0x00, 0xb4, 0x16, 0xaa},
|
||
{0xb0, 0x02, 0x06, 0xcc},
|
||
{0xb0, 0x18, 0x06, 0xcc},
|
||
@@ -2383,6 +2908,10 @@ static const u8 po1200_initVGA_data[][4] = {
|
||
{0x00, 0x03, 0x00, 0xaa},
|
||
{0x00, 0x95, 0x85, 0xaa},
|
||
/*matrix*/
|
||
+#if 0
|
||
+ {0x00, 0x03, 0x00, 0xaa},
|
||
+ {0x00, 0x61, 0xb8, 0xaa}, /* sharpness */
|
||
+#endif
|
||
{0x00, 0x03, 0x00, 0xaa},
|
||
{0x00, 0x4d, 0x20, 0xaa},
|
||
{0xb8, 0x22, 0x40, 0xcc},
|
||
@@ -2402,12 +2931,270 @@ static const u8 po1200_initVGA_data[][4] = {
|
||
{0x00, 0x46, 0x3c, 0xaa},
|
||
{0x00, 0x00, 0x18, 0xdd},
|
||
/*read bfff*/
|
||
+#if 0
|
||
+ {0x00, 0x03, 0x00, 0xaa},
|
||
+ {0x00, 0x1e, 0x46, 0xaa}, /* h/v flip */
|
||
+ {0x00, 0xa8, 0x8f, 0xaa},
|
||
+#endif
|
||
{0x00, 0x03, 0x00, 0xaa},
|
||
{0x00, 0xb4, 0x1c, 0xaa},
|
||
{0x00, 0xb5, 0x92, 0xaa},
|
||
{0x00, 0xb6, 0x39, 0xaa},
|
||
{0x00, 0xb7, 0x24, 0xaa},
|
||
/*write 89 0400 1415*/
|
||
+ {}
|
||
+};
|
||
+
|
||
+static const u8 poxxxx_init_common[][4] = {
|
||
+ {0xb3, 0x00, 0x04, 0xcc},
|
||
+ {0x00, 0x00, 0x10, 0xdd},
|
||
+ {0xb3, 0x00, 0x64, 0xcc},
|
||
+ {0x00, 0x00, 0x10, 0xdd},
|
||
+ {0xb3, 0x00, 0x65, 0xcc},
|
||
+ {0x00, 0x00, 0x10, 0xdd},
|
||
+ {0xb3, 0x00, 0x67, 0xcc},
|
||
+ {0xb0, 0x03, 0x09, 0xcc},
|
||
+ {0xb3, 0x05, 0x00, 0xcc},
|
||
+ {0xb3, 0x06, 0x00, 0xcc},
|
||
+ {0xb3, 0x5c, 0x01, 0xcc},
|
||
+ {0xb3, 0x08, 0x01, 0xcc},
|
||
+ {0xb3, 0x09, 0x0c, 0xcc},
|
||
+ {0xb3, 0x34, 0x01, 0xcc},
|
||
+ {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */
|
||
+ {0xb3, 0x02, 0xb0, 0xcc},
|
||
+ {0xb3, 0x03, 0x18, 0xcc},
|
||
+ {0xb3, 0x04, 0x15, 0xcc},
|
||
+ {0xb3, 0x20, 0x00, 0xcc},
|
||
+ {0xb3, 0x21, 0x00, 0xcc},
|
||
+ {0xb3, 0x22, 0x04, 0xcc},
|
||
+ {0xb3, 0x23, 0x00, 0xcc},
|
||
+ {0xb3, 0x14, 0x00, 0xcc},
|
||
+ {0xb3, 0x15, 0x00, 0xcc},
|
||
+ {0xb3, 0x16, 0x04, 0xcc},
|
||
+ {0xb3, 0x17, 0xff, 0xcc},
|
||
+ {0xb3, 0x2c, 0x03, 0xcc},
|
||
+ {0xb3, 0x2d, 0x56, 0xcc},
|
||
+ {0xb3, 0x2e, 0x02, 0xcc},
|
||
+ {0xb3, 0x2f, 0x0a, 0xcc},
|
||
+ {0xb3, 0x40, 0x00, 0xcc},
|
||
+ {0xb3, 0x41, 0x34, 0xcc},
|
||
+ {0xb3, 0x42, 0x01, 0xcc},
|
||
+ {0xb3, 0x43, 0xe0, 0xcc},
|
||
+ {0xbc, 0x00, 0x71, 0xcc},
|
||
+ {0xbc, 0x01, 0x01, 0xcc},
|
||
+ {0xb3, 0x01, 0x41, 0xcc},
|
||
+ {0xb3, 0x4d, 0x00, 0xcc},
|
||
+ {0x00, 0x0b, 0x2a, 0xaa},
|
||
+ {0x00, 0x0e, 0x03, 0xaa},
|
||
+ {0x00, 0x0f, 0xea, 0xaa},
|
||
+ {0x00, 0x12, 0x08, 0xaa},
|
||
+ {0x00, 0x1e, 0x06, 0xaa},
|
||
+ {0x00, 0x21, 0x00, 0xaa},
|
||
+ {0x00, 0x31, 0x1f, 0xaa},
|
||
+ {0x00, 0x33, 0x38, 0xaa},
|
||
+ {0x00, 0x36, 0xc0, 0xaa},
|
||
+ {0x00, 0x37, 0xc8, 0xaa},
|
||
+ {0x00, 0x3b, 0x36, 0xaa},
|
||
+ {0x00, 0x4b, 0xfe, 0xaa},
|
||
+ {0x00, 0x4d, 0x2e, 0xaa},
|
||
+ {0x00, 0x51, 0x1c, 0xaa},
|
||
+ {0x00, 0x52, 0x01, 0xaa},
|
||
+ {0x00, 0x55, 0x0a, 0xaa},
|
||
+ {0x00, 0x56, 0x0a, 0xaa},
|
||
+ {0x00, 0x57, 0x07, 0xaa},
|
||
+ {0x00, 0x58, 0x07, 0xaa},
|
||
+ {0x00, 0x59, 0x04, 0xaa},
|
||
+ {0x00, 0x70, 0x68, 0xaa},
|
||
+ {0x00, 0x71, 0x04, 0xaa},
|
||
+ {0x00, 0x72, 0x10, 0xaa},
|
||
+ {0x00, 0x80, 0x71, 0xaa},
|
||
+ {0x00, 0x81, 0x08, 0xaa},
|
||
+ {0x00, 0x82, 0x00, 0xaa},
|
||
+ {0x00, 0x83, 0x55, 0xaa},
|
||
+ {0x00, 0x84, 0x06, 0xaa},
|
||
+ {0x00, 0x85, 0x06, 0xaa},
|
||
+ {0x00, 0x8b, 0x25, 0xaa},
|
||
+ {0x00, 0x8c, 0x00, 0xaa},
|
||
+ {0x00, 0x8d, 0x86, 0xaa},
|
||
+ {0x00, 0x8e, 0x82, 0xaa},
|
||
+ {0x00, 0x8f, 0x2d, 0xaa},
|
||
+ {0x00, 0x90, 0x8b, 0xaa},
|
||
+ {0x00, 0x91, 0x81, 0xaa},
|
||
+ {0x00, 0x92, 0x81, 0xaa},
|
||
+ {0x00, 0x93, 0x23, 0xaa},
|
||
+ {0x00, 0xa3, 0x2a, 0xaa},
|
||
+ {0x00, 0xa4, 0x03, 0xaa},
|
||
+ {0x00, 0xa5, 0xea, 0xaa},
|
||
+ {0x00, 0xb0, 0x68, 0xaa},
|
||
+ {0x00, 0xbc, 0x04, 0xaa},
|
||
+ {0x00, 0xbe, 0x3b, 0xaa},
|
||
+ {0x00, 0x4e, 0x40, 0xaa},
|
||
+ {0x00, 0x06, 0x04, 0xaa},
|
||
+ {0x00, 0x07, 0x03, 0xaa},
|
||
+ {0x00, 0xcd, 0x18, 0xaa},
|
||
+ {0x00, 0x28, 0x03, 0xaa},
|
||
+ {0x00, 0x29, 0xef, 0xaa},
|
||
+/* reinit on alt 2 (qvga) or alt7 (vga) */
|
||
+ {0xb3, 0x05, 0x00, 0xcc},
|
||
+ {0xb3, 0x06, 0x00, 0xcc},
|
||
+ {0xb8, 0x00, 0x01, 0xcc},
|
||
+
|
||
+ {0x00, 0x1d, 0x85, 0xaa},
|
||
+ {0x00, 0x1e, 0xc6, 0xaa},
|
||
+ {0x00, 0x00, 0x40, 0xdd},
|
||
+ {0x00, 0x1d, 0x05, 0xaa},
|
||
+
|
||
+ {0x00, 0xd6, 0x22, 0xaa}, /* gamma 0 */
|
||
+ {0x00, 0x73, 0x00, 0xaa},
|
||
+ {0x00, 0x74, 0x0a, 0xaa},
|
||
+ {0x00, 0x75, 0x16, 0xaa},
|
||
+ {0x00, 0x76, 0x25, 0xaa},
|
||
+ {0x00, 0x77, 0x34, 0xaa},
|
||
+ {0x00, 0x78, 0x49, 0xaa},
|
||
+ {0x00, 0x79, 0x5a, 0xaa},
|
||
+ {0x00, 0x7a, 0x7f, 0xaa},
|
||
+ {0x00, 0x7b, 0x9b, 0xaa},
|
||
+ {0x00, 0x7c, 0xba, 0xaa},
|
||
+ {0x00, 0x7d, 0xd4, 0xaa},
|
||
+ {0x00, 0x7e, 0xea, 0xaa},
|
||
+
|
||
+ {0x00, 0xd6, 0x62, 0xaa}, /* gamma 1 */
|
||
+ {0x00, 0x73, 0x00, 0xaa},
|
||
+ {0x00, 0x74, 0x0a, 0xaa},
|
||
+ {0x00, 0x75, 0x16, 0xaa},
|
||
+ {0x00, 0x76, 0x25, 0xaa},
|
||
+ {0x00, 0x77, 0x34, 0xaa},
|
||
+ {0x00, 0x78, 0x49, 0xaa},
|
||
+ {0x00, 0x79, 0x5a, 0xaa},
|
||
+ {0x00, 0x7a, 0x7f, 0xaa},
|
||
+ {0x00, 0x7b, 0x9b, 0xaa},
|
||
+ {0x00, 0x7c, 0xba, 0xaa},
|
||
+ {0x00, 0x7d, 0xd4, 0xaa},
|
||
+ {0x00, 0x7e, 0xea, 0xaa},
|
||
+
|
||
+ {0x00, 0xd6, 0xa2, 0xaa}, /* gamma 2 */
|
||
+ {0x00, 0x73, 0x00, 0xaa},
|
||
+ {0x00, 0x74, 0x0a, 0xaa},
|
||
+ {0x00, 0x75, 0x16, 0xaa},
|
||
+ {0x00, 0x76, 0x25, 0xaa},
|
||
+ {0x00, 0x77, 0x34, 0xaa},
|
||
+ {0x00, 0x78, 0x49, 0xaa},
|
||
+ {0x00, 0x79, 0x5a, 0xaa},
|
||
+ {0x00, 0x7a, 0x7f, 0xaa},
|
||
+ {0x00, 0x7b, 0x9b, 0xaa},
|
||
+ {0x00, 0x7c, 0xba, 0xaa},
|
||
+ {0x00, 0x7d, 0xd4, 0xaa},
|
||
+ {0x00, 0x7e, 0xea, 0xaa},
|
||
+
|
||
+ {0x00, 0xaa, 0xff, 0xaa}, /* back light comp */
|
||
+ {0x00, 0xc4, 0x03, 0xaa},
|
||
+ {0x00, 0xc5, 0x19, 0xaa},
|
||
+ {0x00, 0xc6, 0x03, 0xaa},
|
||
+ {0x00, 0xc7, 0x91, 0xaa},
|
||
+ {0x00, 0xc8, 0x01, 0xaa},
|
||
+ {0x00, 0xc9, 0xdd, 0xaa},
|
||
+ {0x00, 0xca, 0x02, 0xaa},
|
||
+ {0x00, 0xcb, 0x37, 0xaa},
|
||
+
|
||
+/* read d1 */
|
||
+ {0x00, 0xd1, 0x3c, 0xaa},
|
||
+ {0x00, 0xb8, 0x28, 0xaa},
|
||
+ {0x00, 0xb9, 0x1e, 0xaa},
|
||
+ {0x00, 0xb6, 0x14, 0xaa},
|
||
+ {0x00, 0xb7, 0x0f, 0xaa},
|
||
+ {0x00, 0x5c, 0x10, 0xaa},
|
||
+ {0x00, 0x5d, 0x18, 0xaa},
|
||
+ {0x00, 0x5e, 0x24, 0xaa},
|
||
+ {0x00, 0x5f, 0x24, 0xaa},
|
||
+ {0x00, 0x86, 0x1a, 0xaa},
|
||
+ {0x00, 0x60, 0x00, 0xaa},
|
||
+ {0x00, 0x61, 0x1b, 0xaa},
|
||
+ {0x00, 0x62, 0x30, 0xaa},
|
||
+ {0x00, 0x63, 0x40, 0xaa},
|
||
+ {0x00, 0x87, 0x1a, 0xaa},
|
||
+ {0x00, 0x64, 0x00, 0xaa},
|
||
+ {0x00, 0x65, 0x08, 0xaa},
|
||
+ {0x00, 0x66, 0x10, 0xaa},
|
||
+ {0x00, 0x67, 0x20, 0xaa},
|
||
+ {0x00, 0x88, 0x10, 0xaa},
|
||
+ {0x00, 0x68, 0x00, 0xaa},
|
||
+ {0x00, 0x69, 0x08, 0xaa},
|
||
+ {0x00, 0x6a, 0x0f, 0xaa},
|
||
+ {0x00, 0x6b, 0x0f, 0xaa},
|
||
+ {0x00, 0x89, 0x07, 0xaa},
|
||
+ {0x00, 0xd5, 0x4c, 0xaa},
|
||
+ {0x00, 0x0a, 0x00, 0xaa},
|
||
+ {0x00, 0x0b, 0x2a, 0xaa},
|
||
+ {0x00, 0x0e, 0x03, 0xaa},
|
||
+ {0x00, 0x0f, 0xea, 0xaa},
|
||
+ {0x00, 0xa2, 0x00, 0xaa},
|
||
+ {0x00, 0xa3, 0x2a, 0xaa},
|
||
+ {0x00, 0xa4, 0x03, 0xaa},
|
||
+ {0x00, 0xa5, 0xea, 0xaa},
|
||
+ {}
|
||
+};
|
||
+static const u8 poxxxx_initVGA[][4] = {
|
||
+ {0x00, 0x20, 0x11, 0xaa},
|
||
+ {0x00, 0x33, 0x38, 0xaa},
|
||
+ {0x00, 0xbb, 0x0d, 0xaa},
|
||
+ {0xb3, 0x22, 0x01, 0xcc},
|
||
+ {0xb3, 0x23, 0xe0, 0xcc},
|
||
+ {0xb3, 0x16, 0x02, 0xcc},
|
||
+ {0xb3, 0x17, 0x7f, 0xcc},
|
||
+ {0xb3, 0x02, 0xb0, 0xcc},
|
||
+ {0xb3, 0x06, 0x00, 0xcc},
|
||
+ {0xb3, 0x5c, 0x01, 0xcc},
|
||
+ {0x00, 0x04, 0x06, 0xaa},
|
||
+ {0x00, 0x05, 0x3f, 0xaa},
|
||
+ {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */
|
||
+ {}
|
||
+};
|
||
+static const u8 poxxxx_initQVGA[][4] = {
|
||
+ {0x00, 0x20, 0x33, 0xaa},
|
||
+ {0x00, 0x33, 0x38, 0xaa},
|
||
+ {0x00, 0xbb, 0x0d, 0xaa},
|
||
+ {0xb3, 0x22, 0x00, 0xcc},
|
||
+ {0xb3, 0x23, 0xf0, 0xcc},
|
||
+ {0xb3, 0x16, 0x01, 0xcc},
|
||
+ {0xb3, 0x17, 0x3f, 0xcc},
|
||
+ {0xb3, 0x02, 0xb0, 0xcc},
|
||
+ {0xb3, 0x06, 0x01, 0xcc},
|
||
+ {0xb3, 0x5c, 0x00, 0xcc},
|
||
+ {0x00, 0x04, 0x06, 0xaa},
|
||
+ {0x00, 0x05, 0x3f, 0xaa},
|
||
+ {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */
|
||
+ {}
|
||
+};
|
||
+static const u8 poxxxx_init_end_1[][4] = {
|
||
+ {0x00, 0x47, 0x25, 0xaa},
|
||
+ {0x00, 0x48, 0x80, 0xaa},
|
||
+ {0x00, 0x49, 0x1f, 0xaa},
|
||
+ {0x00, 0x4a, 0x40, 0xaa},
|
||
+ {0x00, 0x44, 0x40, 0xaa},
|
||
+ {0x00, 0xab, 0x4a, 0xaa},
|
||
+ {0x00, 0xb1, 0x00, 0xaa},
|
||
+ {0x00, 0xb2, 0x04, 0xaa},
|
||
+ {0x00, 0xb3, 0x08, 0xaa},
|
||
+ {0x00, 0xb4, 0x0b, 0xaa},
|
||
+ {0x00, 0xb5, 0x0d, 0xaa},
|
||
+ {0x00, 0x59, 0x7e, 0xaa}, /* sharpness */
|
||
+ {0x00, 0x16, 0x00, 0xaa}, /* white balance */
|
||
+ {0x00, 0x18, 0x00, 0xaa},
|
||
+#if 0
|
||
+/* read d1 */
|
||
+ {0x00, 0xd1, 0x3c, 0xaa},
|
||
+ {0x00, 0x94, 0x46, 0xaa}, /* colors */
|
||
+ {0x00, 0x95, 0x51, 0xaa},
|
||
+ {0x00, 0x98, 0x88, 0xaa}, /* contrast */
|
||
+ {0x00, 0x99, 0x93, 0xaa}, /* brightness */
|
||
+#endif
|
||
+ {}
|
||
+};
|
||
+static const u8 poxxxx_init_end_2[][4] = {
|
||
+ {0x00, 0x1d, 0x85, 0xaa},
|
||
+ {0x00, 0x1e, 0x06, 0xaa},
|
||
+ {0x00, 0x1d, 0x05, 0xaa},
|
||
+ {}
|
||
};
|
||
|
||
struct sensor_info {
|
||
@@ -2420,33 +3207,89 @@ struct sensor_info {
|
||
u8 op;
|
||
};
|
||
|
||
-static const struct sensor_info sensor_info_data[] = {
|
||
-/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */
|
||
+/* probe values */
|
||
+static const struct sensor_info vc0321_probe_data[] = {
|
||
+/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */
|
||
+/* 0 OV9640 */
|
||
{-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
|
||
+/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
|
||
{-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
|
||
-/* (tested in vc032x_probe_sensor) */
|
||
-/* {-1, 0x80 | 0x20, 0x83, 0x0000, 0x24, 0x25, 0x01}, */
|
||
- {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01},
|
||
+/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
|
||
+ {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* 3 MI1310 */
|
||
+ {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* 4 MI360 - tested in vc032x_probe_sensor */
|
||
+/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
|
||
+/* 5 7131R */
|
||
+ {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
|
||
+/* 6 OV7649 */
|
||
+ {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
|
||
+/* 7 PAS302BCW */
|
||
+ {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
|
||
+/* 8 OV7660 */
|
||
+ {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
|
||
+/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
|
||
+/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
|
||
+/* 10 PO1030KC */
|
||
+ {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* 11 MI1310_SOC */
|
||
{SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
|
||
-/* (tested in vc032x_probe_sensor) */
|
||
+/* 12 OV9650 */
|
||
+ {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
|
||
+/* 13 S5K532 */
|
||
+ {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* 14 MI360_SOC - ??? */
|
||
+/* 15 PO1200N */
|
||
+ {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
|
||
+/* 16 PO3030K */
|
||
+ {-1, 0x80 | 0x18, 0x00, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* 17 PO2030 */
|
||
+ {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* ?? */
|
||
+ {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
|
||
+ {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01},
|
||
+};
|
||
+static const struct sensor_info vc0323_probe_data[] = {
|
||
+/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */
|
||
+/* 0 OV9640 */
|
||
+ {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
|
||
+/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
|
||
+ {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
|
||
+ {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* 3 MI1310 */
|
||
+ {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* 4 MI360 - tested in vc032x_probe_sensor */
|
||
/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
|
||
+/* 5 7131R */
|
||
{SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
|
||
+/* 6 OV7649 */
|
||
{-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
|
||
+/* 7 PAS302BCW */
|
||
{-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
|
||
+/* 8 OV7660 */
|
||
{SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
|
||
-/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, */
|
||
+/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
|
||
+/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
|
||
+/* 10 PO1030KC */
|
||
{-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
|
||
-/* {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, */
|
||
-/* {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, */
|
||
+/* 11 MI1310_SOC */
|
||
+ {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
|
||
+/* 12 OV9650 */
|
||
+ {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
|
||
+/* 13 S5K532 */
|
||
{-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* 14 MI360_SOC - ??? */
|
||
+/* 15 PO1200N */
|
||
{SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
|
||
+/* 16 ?? */
|
||
{-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01},
|
||
+/* 17 PO2030 */
|
||
{-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
|
||
+/* ?? */
|
||
{-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
|
||
{SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01},
|
||
-/*fixme: previously detected?*/
|
||
- {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01},
|
||
-/*fixme: not in the ms-win probe - may be found before?*/
|
||
+/*fixme: not in the ms-win probe - may be found before? */
|
||
{SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
|
||
};
|
||
|
||
@@ -2520,20 +3363,31 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct usb_device *dev = gspca_dev->dev;
|
||
- int i;
|
||
+ int i, n;
|
||
u16 value;
|
||
const struct sensor_info *ptsensor_info;
|
||
|
||
/*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/
|
||
if (sd->flags & FL_SAMSUNG) {
|
||
reg_w(dev, 0xa0, 0x01, 0xb301);
|
||
+#if 1
|
||
reg_w(dev, 0x89, 0xf0ff, 0xffff); /* select the back sensor */
|
||
+#else
|
||
+ reg_w(dev, 0x89, 0xf3ff, 0xffff); /* select the front sensor */
|
||
+#endif
|
||
}
|
||
|
||
reg_r(gspca_dev, 0xa1, 0xbfcf, 1);
|
||
- PDEBUG(D_PROBE, "check sensor header %02x", gspca_dev->usb_buf[0]);
|
||
- for (i = 0; i < ARRAY_SIZE(sensor_info_data); i++) {
|
||
- ptsensor_info = &sensor_info_data[i];
|
||
+ PDEBUG(D_PROBE, "vc032%d check sensor header %02x",
|
||
+ sd->bridge == BRIDGE_VC0321 ? 1 : 3, gspca_dev->usb_buf[0]);
|
||
+ if (sd->bridge == BRIDGE_VC0321) {
|
||
+ ptsensor_info = vc0321_probe_data;
|
||
+ n = ARRAY_SIZE(vc0321_probe_data);
|
||
+ } else {
|
||
+ ptsensor_info = vc0323_probe_data;
|
||
+ n = ARRAY_SIZE(vc0323_probe_data);
|
||
+ }
|
||
+ for (i = 0; i < n; i++) {
|
||
reg_w(dev, 0xa0, 0x02, 0xb334);
|
||
reg_w(dev, 0xa0, ptsensor_info->m1, 0xb300);
|
||
reg_w(dev, 0xa0, ptsensor_info->m2, 0xb300);
|
||
@@ -2551,13 +3405,15 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
|
||
return ptsensor_info->sensorId;
|
||
|
||
switch (value) {
|
||
+ case 0x3130:
|
||
+ return SENSOR_PO3130NC;
|
||
case 0x7673:
|
||
return SENSOR_OV7670;
|
||
case 0x8243:
|
||
return SENSOR_MI0360;
|
||
}
|
||
-/*fixme: should return here*/
|
||
}
|
||
+ ptsensor_info++;
|
||
}
|
||
return -1;
|
||
}
|
||
@@ -2619,7 +3475,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev,
|
||
i2c_write(gspca_dev, data[i][0], &data[i][1], 2);
|
||
break;
|
||
case 0xdd:
|
||
- msleep(data[i][2] + 10);
|
||
+ msleep(data[i][1] * 256 + data[i][2] + 10);
|
||
break;
|
||
}
|
||
i++;
|
||
@@ -2627,6 +3483,16 @@ static void usb_exchange(struct gspca_dev *gspca_dev,
|
||
/*not reached*/
|
||
}
|
||
|
||
+#if 0
|
||
+static void vc0321_reset(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb04d);
|
||
+ reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb301);
|
||
+ msleep(100);
|
||
+ reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb003);
|
||
+ msleep(100);
|
||
+}
|
||
+#endif
|
||
|
||
/* this function is called at probe time */
|
||
static int sd_config(struct gspca_dev *gspca_dev,
|
||
@@ -2646,12 +3512,20 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
64, /* OV7670 6 */
|
||
128, /* PO1200 7 */
|
||
128, /* PO3130NC 8 */
|
||
+ 128, /* POxxxx 9 */
|
||
};
|
||
|
||
cam = &gspca_dev->cam;
|
||
sd->bridge = id->driver_info >> 8;
|
||
sd->flags = id->driver_info & 0xff;
|
||
- sensor = vc032x_probe_sensor(gspca_dev);
|
||
+#if 0
|
||
+ vc0321_reset(gspca_dev);
|
||
+#endif
|
||
+ if (id->idVendor == 0x046d &&
|
||
+ (id->idProduct == 0x0892 || id->idProduct == 0x0896))
|
||
+ sensor = SENSOR_POxxxx;
|
||
+ else
|
||
+ sensor = vc032x_probe_sensor(gspca_dev);
|
||
switch (sensor) {
|
||
case -1:
|
||
PDEBUG(D_PROBE, "Unknown sensor...");
|
||
@@ -2684,6 +3558,9 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
case SENSOR_PO3130NC:
|
||
PDEBUG(D_PROBE, "Find Sensor PO3130NC");
|
||
break;
|
||
+ case SENSOR_POxxxx:
|
||
+ PDEBUG(D_PROBE, "Sensor POxxxx");
|
||
+ break;
|
||
}
|
||
sd->sensor = sensor;
|
||
|
||
@@ -2712,28 +3589,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
}
|
||
cam->npkt = npkt[sd->sensor];
|
||
|
||
+ sd->brightness = BRIGHTNESS_DEF;
|
||
+ sd->contrast = CONTRAST_DEF;
|
||
+ sd->colors = COLOR_DEF;
|
||
sd->hflip = HFLIP_DEF;
|
||
sd->vflip = VFLIP_DEF;
|
||
- if (sd->sensor == SENSOR_OV7670)
|
||
- sd->flags |= FL_HFLIP | FL_VFLIP;
|
||
sd->lightfreq = FREQ_DEF;
|
||
- if (sd->sensor != SENSOR_OV7670)
|
||
- gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX);
|
||
- switch (sd->sensor) {
|
||
- case SENSOR_MI1310_SOC:
|
||
- case SENSOR_MI1320_SOC:
|
||
- case SENSOR_OV7660:
|
||
- case SENSOR_OV7670:
|
||
- case SENSOR_PO1200:
|
||
- break;
|
||
- default:
|
||
- gspca_dev->ctrl_dis = (1 << HFLIP_IDX)
|
||
- | (1 << VFLIP_IDX);
|
||
- break;
|
||
- }
|
||
-
|
||
sd->sharpness = SHARPNESS_DEF;
|
||
|
||
+ gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
|
||
+
|
||
+ if (sd->sensor == SENSOR_OV7670)
|
||
+ sd->flags |= FL_HFLIP | FL_VFLIP;
|
||
+
|
||
if (sd->bridge == BRIDGE_VC0321) {
|
||
reg_r(gspca_dev, 0x8a, 0, 3);
|
||
reg_w(dev, 0x87, 0x00, 0x0f0f);
|
||
@@ -2747,10 +3615,55 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
/* this function is called at probe and resume time */
|
||
static int sd_init(struct gspca_dev *gspca_dev)
|
||
{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ if (sd->sensor == SENSOR_POxxxx) {
|
||
+ reg_r(gspca_dev, 0xa1, 0xb300, 1);
|
||
+ if (gspca_dev->usb_buf[0] != 0) {
|
||
+ reg_w(gspca_dev->dev, 0xa0, 0x26, 0xb300);
|
||
+ reg_w(gspca_dev->dev, 0xa0, 0x04, 0xb300);
|
||
+ reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb300);
|
||
+ }
|
||
+ }
|
||
return 0;
|
||
}
|
||
|
||
-/* some sensors only */
|
||
+static void setbrightness(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ u8 data;
|
||
+
|
||
+ if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX))
|
||
+ return;
|
||
+ data = sd->brightness;
|
||
+ if (data >= 0x80)
|
||
+ data &= 0x7f;
|
||
+ else
|
||
+ data = 0xff ^ data;
|
||
+ i2c_write(gspca_dev, 0x98, &data, 1);
|
||
+}
|
||
+
|
||
+static void setcontrast(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX))
|
||
+ return;
|
||
+ i2c_write(gspca_dev, 0x99, &sd->contrast, 1);
|
||
+}
|
||
+
|
||
+static void setcolors(struct gspca_dev *gspca_dev)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+ u8 data;
|
||
+
|
||
+ if (gspca_dev->ctrl_dis & (1 << COLORS_IDX))
|
||
+ return;
|
||
+ data = sd->colors - (sd->colors >> 3) - 1;
|
||
+ i2c_write(gspca_dev, 0x94, &data, 1);
|
||
+ i2c_write(gspca_dev, 0x95, &sd->colors, 1);
|
||
+}
|
||
+
|
||
static void sethvflip(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
@@ -2764,6 +3677,7 @@ static void sethvflip(struct gspca_dev *gspca_dev)
|
||
vflip = !vflip;
|
||
switch (sd->sensor) {
|
||
case SENSOR_MI1310_SOC:
|
||
+ case SENSOR_MI1320:
|
||
case SENSOR_MI1320_SOC:
|
||
data[0] = data[1] = 0; /* select page 0 */
|
||
i2c_write(gspca_dev, 0xf0, data, 2);
|
||
@@ -2801,18 +3715,29 @@ static void setlightfreq(struct gspca_dev *gspca_dev)
|
||
usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]);
|
||
}
|
||
|
||
-/* po1200 only */
|
||
static void setsharpness(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
u8 data;
|
||
|
||
- if (sd->sensor != SENSOR_PO1200)
|
||
- return;
|
||
- data = 0;
|
||
- i2c_write(gspca_dev, 0x03, &data, 1);
|
||
- data = 0xb5 + sd->sharpness * 3;
|
||
- i2c_write(gspca_dev, 0x61, &data, 1);
|
||
+ switch (sd->sensor) {
|
||
+ case SENSOR_PO1200:
|
||
+ data = 0;
|
||
+ i2c_write(gspca_dev, 0x03, &data, 1);
|
||
+ if (sd->sharpness < 0)
|
||
+ data = 0x6a;
|
||
+ else
|
||
+ data = 0xb5 + sd->sharpness * 3;
|
||
+ i2c_write(gspca_dev, 0x61, &data, 1);
|
||
+ break;
|
||
+ case SENSOR_POxxxx:
|
||
+ if (sd->sharpness < 0)
|
||
+ data = 0x7e; /* def = max */
|
||
+ else
|
||
+ data = 0x60 + sd->sharpness * 0x0f;
|
||
+ i2c_write(gspca_dev, 0x59, &data, 1);
|
||
+ break;
|
||
+ }
|
||
}
|
||
|
||
static int sd_start(struct gspca_dev *gspca_dev)
|
||
@@ -2826,6 +3751,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
mi1320_soc_InitSXGA,
|
||
mi1320_soc_InitVGA,
|
||
mi1320_soc_InitQVGA,
|
||
+#if 0 /* JPEG vc0323 */
|
||
+ mi1320_soc_InitSXGA_JPG,
|
||
+ mi1320_soc_InitVGA_JPG,
|
||
+ mi1320_soc_InitQVGA_JPG
|
||
+#endif
|
||
};
|
||
|
||
/*fixme: back sensor only*/
|
||
@@ -2922,12 +3852,27 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
usb_exchange(gspca_dev, init);
|
||
init = po3130_rundata;
|
||
break;
|
||
- default:
|
||
-/* case SENSOR_PO1200: */
|
||
+ case SENSOR_PO1200:
|
||
GammaT = po1200_gamma;
|
||
MatrixT = po1200_matrix;
|
||
init = po1200_initVGA_data;
|
||
break;
|
||
+ default:
|
||
+/* case SENSOR_POxxxx: */
|
||
+ usb_exchange(gspca_dev, poxxxx_init_common);
|
||
+ if (mode)
|
||
+ init = poxxxx_initQVGA;
|
||
+ else
|
||
+ init = poxxxx_initVGA;
|
||
+ usb_exchange(gspca_dev, init);
|
||
+ reg_r(gspca_dev, 0x8c, 0x0000, 3);
|
||
+ reg_w(gspca_dev->dev, 0xa0,
|
||
+ gspca_dev->usb_buf[2] & 1 ? 0 : 1,
|
||
+ 0xb35c);
|
||
+ msleep(300);
|
||
+/*fixme: i2c read 04 and 05*/
|
||
+ init = poxxxx_init_end_1;
|
||
+ break;
|
||
}
|
||
usb_exchange(gspca_dev, init);
|
||
if (GammaT && MatrixT) {
|
||
@@ -2936,7 +3881,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c);
|
||
put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c);
|
||
|
||
- /* set the led on 0x0892 0x0896 */
|
||
switch (sd->sensor) {
|
||
case SENSOR_PO1200:
|
||
case SENSOR_HV7131R:
|
||
@@ -2945,16 +3889,22 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
case SENSOR_MI1310_SOC:
|
||
reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000);
|
||
break;
|
||
- default:
|
||
- if (!(sd->flags & FL_SAMSUNG))
|
||
- reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff);
|
||
- break;
|
||
}
|
||
msleep(100);
|
||
setsharpness(gspca_dev);
|
||
sethvflip(gspca_dev);
|
||
setlightfreq(gspca_dev);
|
||
}
|
||
+ if (sd->sensor == SENSOR_POxxxx) {
|
||
+ setcolors(gspca_dev);
|
||
+ setbrightness(gspca_dev);
|
||
+ setcontrast(gspca_dev);
|
||
+
|
||
+ /* led on */
|
||
+ msleep(80);
|
||
+ reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff);
|
||
+ usb_exchange(gspca_dev, poxxxx_init_end_2);
|
||
+ }
|
||
return 0;
|
||
}
|
||
|
||
@@ -2963,10 +3913,17 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
|
||
struct usb_device *dev = gspca_dev->dev;
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
|
||
- if (sd->sensor == SENSOR_MI1310_SOC)
|
||
+ switch (sd->sensor) {
|
||
+ case SENSOR_MI1310_SOC:
|
||
reg_w(dev, 0x89, 0x058c, 0x00ff);
|
||
- else if (!(sd->flags & FL_SAMSUNG))
|
||
- reg_w(dev, 0x89, 0xffff, 0xffff);
|
||
+ break;
|
||
+ case SENSOR_POxxxx:
|
||
+ return;
|
||
+ default:
|
||
+ if (!(sd->flags & FL_SAMSUNG))
|
||
+ reg_w(dev, 0x89, 0xffff, 0xffff);
|
||
+ break;
|
||
+ }
|
||
reg_w(dev, 0xa0, 0x01, 0xb301);
|
||
reg_w(dev, 0xa0, 0x09, 0xb003);
|
||
}
|
||
@@ -2984,6 +3941,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
|
||
reg_w(dev, 0x89, 0x058c, 0x00ff);
|
||
else if (!(sd->flags & FL_SAMSUNG))
|
||
reg_w(dev, 0x89, 0xffff, 0xffff);
|
||
+
|
||
+ if (sd->sensor == SENSOR_POxxxx) {
|
||
+ reg_w(dev, 0xa0, 0x26, 0xb300);
|
||
+ reg_w(dev, 0xa0, 0x04, 0xb300);
|
||
+ reg_w(dev, 0xa0, 0x00, 0xb300);
|
||
+ }
|
||
}
|
||
|
||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||
@@ -3020,6 +3983,60 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
|
||
}
|
||
|
||
+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_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->contrast = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ setcontrast(gspca_dev);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->contrast;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ sd->colors = val;
|
||
+ if (gspca_dev->streaming)
|
||
+ setcolors(gspca_dev);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
|
||
+{
|
||
+ struct sd *sd = (struct sd *) gspca_dev;
|
||
+
|
||
+ *val = sd->colors;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
|
||
index 1a800fc..56fc686 100644
|
||
--- a/drivers/media/video/gspca/zc3xx.c
|
||
+++ b/drivers/media/video/gspca/zc3xx.c
|
||
@@ -1,9 +1,8 @@
|
||
/*
|
||
- * Z-Star/Vimicro zc301/zc302p/vc30x library
|
||
- * Copyright (C) 2004 2005 2006 Michel Xhaard
|
||
- * mxhaard@magic.fr
|
||
+ * Z-Star/Vimicro zc301/zc302p/vc30x library
|
||
*
|
||
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
|
||
+ * Copyright (C) 2009-2010 Jean-Francois Moine <http://moinejf.free.fr>
|
||
+ * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr
|
||
*
|
||
* 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
|
||
@@ -22,10 +21,11 @@
|
||
|
||
#define MODULE_NAME "zc3xx"
|
||
|
||
+#include <linux/input.h>
|
||
#include "gspca.h"
|
||
#include "jpeg.h"
|
||
|
||
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>, "
|
||
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
|
||
"Serge A. Suchkov <Serge.A.S@tochka.ru>");
|
||
MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver");
|
||
MODULE_LICENSE("GPL");
|
||
@@ -39,18 +39,18 @@ static int force_sensor = -1;
|
||
struct sd {
|
||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||
|
||
- __u8 brightness;
|
||
- __u8 contrast;
|
||
- __u8 gamma;
|
||
- __u8 autogain;
|
||
- __u8 lightfreq;
|
||
- __u8 sharpness;
|
||
+ u8 brightness;
|
||
+ u8 contrast;
|
||
+ u8 gamma;
|
||
+ u8 autogain;
|
||
+ u8 lightfreq;
|
||
+ u8 sharpness;
|
||
u8 quality; /* image quality */
|
||
#define QUALITY_MIN 40
|
||
#define QUALITY_MAX 60
|
||
#define QUALITY_DEF 50
|
||
|
||
- signed char sensor; /* Type of image sensor chip */
|
||
+ u8 sensor; /* Type of image sensor chip */
|
||
/* !! values used in different tables */
|
||
#define SENSOR_ADCM2700 0
|
||
#define SENSOR_CS2102 1
|
||
@@ -92,9 +92,8 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
|
||
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
|
||
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
|
||
|
||
-static struct ctrl sd_ctrls[] = {
|
||
+static const struct ctrl sd_ctrls[] = {
|
||
#define BRIGHTNESS_IDX 0
|
||
-#define SD_BRIGHTNESS 0
|
||
{
|
||
{
|
||
.id = V4L2_CID_BRIGHTNESS,
|
||
@@ -103,26 +102,26 @@ static struct ctrl sd_ctrls[] = {
|
||
.minimum = 0,
|
||
.maximum = 255,
|
||
.step = 1,
|
||
- .default_value = 128,
|
||
+#define BRIGHTNESS_DEF 128
|
||
+ .default_value = BRIGHTNESS_DEF,
|
||
},
|
||
.set = sd_setbrightness,
|
||
.get = sd_getbrightness,
|
||
},
|
||
-#define SD_CONTRAST 1
|
||
{
|
||
{
|
||
.id = V4L2_CID_CONTRAST,
|
||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||
.name = "Contrast",
|
||
.minimum = 0,
|
||
- .maximum = 256,
|
||
+ .maximum = 255,
|
||
.step = 1,
|
||
- .default_value = 128,
|
||
+#define CONTRAST_DEF 128
|
||
+ .default_value = CONTRAST_DEF,
|
||
},
|
||
.set = sd_setcontrast,
|
||
.get = sd_getcontrast,
|
||
},
|
||
-#define SD_GAMMA 2
|
||
{
|
||
{
|
||
.id = V4L2_CID_GAMMA,
|
||
@@ -136,7 +135,6 @@ static struct ctrl sd_ctrls[] = {
|
||
.set = sd_setgamma,
|
||
.get = sd_getgamma,
|
||
},
|
||
-#define SD_AUTOGAIN 3
|
||
{
|
||
{
|
||
.id = V4L2_CID_AUTOGAIN,
|
||
@@ -145,13 +143,13 @@ 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,
|
||
},
|
||
#define LIGHTFREQ_IDX 4
|
||
-#define SD_FREQ 4
|
||
{
|
||
{
|
||
.id = V4L2_CID_POWER_LINE_FREQUENCY,
|
||
@@ -160,12 +158,12 @@ static struct ctrl sd_ctrls[] = {
|
||
.minimum = 0,
|
||
.maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
|
||
.step = 1,
|
||
- .default_value = 1,
|
||
+#define FREQ_DEF 0
|
||
+ .default_value = FREQ_DEF,
|
||
},
|
||
.set = sd_setfreq,
|
||
.get = sd_getfreq,
|
||
},
|
||
-#define SD_SHARPNESS 5
|
||
{
|
||
{
|
||
.id = V4L2_CID_SHARPNESS,
|
||
@@ -174,7 +172,8 @@ static struct ctrl sd_ctrls[] = {
|
||
.minimum = 0,
|
||
.maximum = 3,
|
||
.step = 1,
|
||
- .default_value = 2,
|
||
+#define SHARPNESS_DEF 2
|
||
+ .default_value = SHARPNESS_DEF,
|
||
},
|
||
.set = sd_setsharpness,
|
||
.get = sd_getsharpness,
|
||
@@ -194,6 +193,19 @@ static const struct v4l2_pix_format vga_mode[] = {
|
||
.priv = 0},
|
||
};
|
||
|
||
+static const struct v4l2_pix_format broken_vga_mode[] = {
|
||
+ {320, 232, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 320,
|
||
+ .sizeimage = 320 * 232 * 4 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG,
|
||
+ .priv = 1},
|
||
+ {640, 472, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
+ .bytesperline = 640,
|
||
+ .sizeimage = 640 * 472 * 3 / 8 + 590,
|
||
+ .colorspace = V4L2_COLORSPACE_JPEG,
|
||
+ .priv = 0},
|
||
+};
|
||
+
|
||
static const struct v4l2_pix_format sif_mode[] = {
|
||
{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||
.bytesperline = 176,
|
||
@@ -209,15 +221,19 @@ static const struct v4l2_pix_format sif_mode[] = {
|
||
|
||
/* usb exchanges */
|
||
struct usb_action {
|
||
- __u8 req;
|
||
- __u8 val;
|
||
- __u16 idx;
|
||
+ u8 req;
|
||
+ u8 val;
|
||
+ u16 idx;
|
||
};
|
||
|
||
static const struct usb_action adcm2700_Initial[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
{0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
|
||
+#if 1 /*jfm*/
|
||
{0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
|
||
+#else
|
||
+ {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
|
||
+#endif
|
||
{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
|
||
{0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
|
||
{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
|
||
@@ -237,7 +253,11 @@ static const struct usb_action adcm2700_Initial[] = {
|
||
{0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
|
||
{0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
|
||
{0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
|
||
+#if 1 /*jfm-mswin*/
|
||
{0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
|
||
+#else
|
||
+ {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
|
||
+#endif
|
||
{0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
|
||
{0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
|
||
{0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
|
||
@@ -306,7 +326,11 @@ static const struct usb_action adcm2700_Initial[] = {
|
||
static const struct usb_action adcm2700_InitialScale[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
|
||
+#if 1 /*jfm*/
|
||
{0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
|
||
+#else
|
||
+ {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
|
||
+#endif
|
||
{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
|
||
{0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
|
||
{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
|
||
@@ -326,7 +350,11 @@ static const struct usb_action adcm2700_InitialScale[] = {
|
||
{0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
|
||
{0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
|
||
{0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
|
||
+#if 1 /*jfm-mswin*/
|
||
{0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
|
||
+#else
|
||
+ {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
|
||
+#endif
|
||
{0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
|
||
{0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
|
||
{0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
|
||
@@ -354,9 +382,17 @@ static const struct usb_action adcm2700_InitialScale[] = {
|
||
{0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */
|
||
{0xbb, 0x01, 0x8000}, /* 80,01,00,bb */
|
||
{0xbb, 0x09, 0x8400}, /* 84,09,00,bb */
|
||
+#if 1 /*jfm-mswin*/
|
||
{0xbb, 0x86, 0x0002}, /* 00,88,02,bb */
|
||
+#else
|
||
+ {0xbb, 0x88, 0x0002}, /* 00,88,02,bb */
|
||
+#endif
|
||
{0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */
|
||
+#if 1 /*jfm-mswin*/
|
||
{0xbb, 0x86, 0x0802}, /* 08,88,02,bb */
|
||
+#else
|
||
+ {0xbb, 0x88, 0x0802}, /* 08,88,02,bb */
|
||
+#endif
|
||
{0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */
|
||
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
|
||
{0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
|
||
@@ -421,7 +457,7 @@ static const struct usb_action adcm2700_NoFliker[] = {
|
||
{0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
|
||
{}
|
||
};
|
||
-static const struct usb_action cs2102_Initial[] = { /* 320x240 */
|
||
+static const struct usb_action cs2102_InitialScale[] = { /* 320x240 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
|
||
@@ -473,7 +509,7 @@ static const struct usb_action cs2102_Initial[] = { /* 320x240 */
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action cs2102_InitialScale[] = { /* 640x480 */
|
||
+static const struct usb_action cs2102_Initial[] = { /* 640x480 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
|
||
@@ -524,7 +560,7 @@ static const struct usb_action cs2102_InitialScale[] = { /* 640x480 */
|
||
{0xa0, 0x00, 0x01ad},
|
||
{}
|
||
};
|
||
-static const struct usb_action cs2102_50HZ[] = {
|
||
+static const struct usb_action cs2102_50HZScale[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||
{0xaa, 0x23, 0x0001},
|
||
{0xaa, 0x24, 0x005f},
|
||
@@ -546,7 +582,7 @@ static const struct usb_action cs2102_50HZ[] = {
|
||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
|
||
{}
|
||
};
|
||
-static const struct usb_action cs2102_50HZScale[] = {
|
||
+static const struct usb_action cs2102_50HZ[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||
{0xaa, 0x23, 0x0000},
|
||
{0xaa, 0x24, 0x00af},
|
||
@@ -568,7 +604,7 @@ static const struct usb_action cs2102_50HZScale[] = {
|
||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
|
||
{}
|
||
};
|
||
-static const struct usb_action cs2102_60HZ[] = {
|
||
+static const struct usb_action cs2102_60HZScale[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||
{0xaa, 0x23, 0x0001},
|
||
{0xaa, 0x24, 0x0055},
|
||
@@ -590,7 +626,7 @@ static const struct usb_action cs2102_60HZ[] = {
|
||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
|
||
{}
|
||
};
|
||
-static const struct usb_action cs2102_60HZScale[] = {
|
||
+static const struct usb_action cs2102_60HZ[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||
{0xaa, 0x23, 0x0000},
|
||
{0xaa, 0x24, 0x00aa},
|
||
@@ -612,7 +648,7 @@ static const struct usb_action cs2102_60HZScale[] = {
|
||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
|
||
{}
|
||
};
|
||
-static const struct usb_action cs2102_NoFliker[] = {
|
||
+static const struct usb_action cs2102_NoFlikerScale[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||
{0xaa, 0x23, 0x0001},
|
||
{0xaa, 0x24, 0x005f},
|
||
@@ -634,7 +670,7 @@ static const struct usb_action cs2102_NoFliker[] = {
|
||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
|
||
{}
|
||
};
|
||
-static const struct usb_action cs2102_NoFlikerScale[] = {
|
||
+static const struct usb_action cs2102_NoFliker[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||
{0xaa, 0x23, 0x0000},
|
||
{0xaa, 0x24, 0x00af},
|
||
@@ -658,7 +694,7 @@ static const struct usb_action cs2102_NoFlikerScale[] = {
|
||
};
|
||
|
||
/* CS2102_KOCOM */
|
||
-static const struct usb_action cs2102K_Initial[] = {
|
||
+static const struct usb_action cs2102K_InitialScale[] = {
|
||
{0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
{0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
|
||
@@ -917,7 +953,7 @@ static const struct usb_action cs2102K_Initial[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action cs2102K_InitialScale[] = {
|
||
+static const struct usb_action cs2102K_Initial[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
@@ -1495,7 +1531,7 @@ static const struct usb_action gc0305_NoFliker[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action hdcs2020xb_Initial[] = {
|
||
+static const struct usb_action hdcs2020b_InitialScale[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */
|
||
@@ -1627,7 +1663,7 @@ static const struct usb_action hdcs2020xb_Initial[] = {
|
||
{0xa0, 0x40, ZC3XX_R118_BGAIN},
|
||
{}
|
||
};
|
||
-static const struct usb_action hdcs2020xb_InitialScale[] = {
|
||
+static const struct usb_action hdcs2020b_Initial[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
@@ -1819,7 +1855,7 @@ static const struct usb_action hdcs2020b_NoFliker[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */
|
||
+static const struct usb_action hv7131b_InitialScale[] = { /* 320x240 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
|
||
@@ -1866,7 +1902,7 @@ static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action hv7131bxx_InitialScale[] = { /* 640x480*/
|
||
+static const struct usb_action hv7131b_Initial[] = { /* 640x480*/
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
|
||
@@ -2063,7 +2099,7 @@ static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action hv7131cxx_Initial[] = {
|
||
+static const struct usb_action hv7131r_InitialScale[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
|
||
@@ -2157,7 +2193,7 @@ static const struct usb_action hv7131cxx_Initial[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action hv7131cxx_InitialScale[] = {
|
||
+static const struct usb_action hv7131r_Initial[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
|
||
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* diff */
|
||
@@ -2259,7 +2295,7 @@ static const struct usb_action hv7131cxx_InitialScale[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action icm105axx_Initial[] = {
|
||
+static const struct usb_action icm105a_InitialScale[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
@@ -2436,7 +2472,7 @@ static const struct usb_action icm105axx_Initial[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action icm105axx_InitialScale[] = {
|
||
+static const struct usb_action icm105a_Initial[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
@@ -2615,7 +2651,7 @@ static const struct usb_action icm105axx_InitialScale[] = {
|
||
{0xa0, 0x40, ZC3XX_R118_BGAIN},
|
||
{}
|
||
};
|
||
-static const struct usb_action icm105a_50HZ[] = {
|
||
+static const struct usb_action icm105a_50HZScale[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
|
||
{0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */
|
||
@@ -2646,7 +2682,7 @@ static const struct usb_action icm105a_50HZ[] = {
|
||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
|
||
{}
|
||
};
|
||
-static const struct usb_action icm105a_50HZScale[] = {
|
||
+static const struct usb_action icm105a_50HZ[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
|
||
{0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */
|
||
@@ -2679,7 +2715,7 @@ static const struct usb_action icm105a_50HZScale[] = {
|
||
{0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
|
||
{}
|
||
};
|
||
-static const struct usb_action icm105a_60HZ[] = {
|
||
+static const struct usb_action icm105a_60HZScale[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
|
||
{0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
|
||
@@ -2710,7 +2746,7 @@ static const struct usb_action icm105a_60HZ[] = {
|
||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
|
||
{}
|
||
};
|
||
-static const struct usb_action icm105a_60HZScale[] = {
|
||
+static const struct usb_action icm105a_60HZ[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
|
||
{0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */
|
||
@@ -2743,7 +2779,7 @@ static const struct usb_action icm105a_60HZScale[] = {
|
||
{0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
|
||
{}
|
||
};
|
||
-static const struct usb_action icm105a_NoFliker[] = {
|
||
+static const struct usb_action icm105a_NoFlikerScale[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
|
||
{0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
|
||
@@ -2774,7 +2810,7 @@ static const struct usb_action icm105a_NoFliker[] = {
|
||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
|
||
{}
|
||
};
|
||
-static const struct usb_action icm105a_NoFlikerScale[] = {
|
||
+static const struct usb_action icm105a_NoFliker[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
|
||
{0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
|
||
@@ -2808,7 +2844,7 @@ static const struct usb_action icm105a_NoFlikerScale[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action MC501CB_InitialScale[] = {
|
||
+static const struct usb_action mc501cb_Initial[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
|
||
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
|
||
@@ -2928,7 +2964,7 @@ static const struct usb_action MC501CB_InitialScale[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action MC501CB_Initial[] = { /* 320x240 */
|
||
+static const struct usb_action mc501cb_InitialScale[] = { /* 320x240 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
|
||
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
|
||
@@ -3047,7 +3083,7 @@ static const struct usb_action MC501CB_Initial[] = { /* 320x240 */
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action MC501CB_50HZ[] = {
|
||
+static const struct usb_action mc501cb_50HZScale[] = {
|
||
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
|
||
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
|
||
{0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
|
||
@@ -3064,7 +3100,7 @@ static const struct usb_action MC501CB_50HZ[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action MC501CB_50HZScale[] = {
|
||
+static const struct usb_action mc501cb_50HZ[] = {
|
||
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
|
||
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
|
||
{0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */
|
||
@@ -3081,7 +3117,7 @@ static const struct usb_action MC501CB_50HZScale[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action MC501CB_60HZ[] = {
|
||
+static const struct usb_action mc501cb_60HZScale[] = {
|
||
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
|
||
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
|
||
{0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
|
||
@@ -3098,7 +3134,7 @@ static const struct usb_action MC501CB_60HZ[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action MC501CB_60HZScale[] = {
|
||
+static const struct usb_action mc501cb_60HZ[] = {
|
||
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
|
||
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
|
||
{0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
|
||
@@ -3115,7 +3151,7 @@ static const struct usb_action MC501CB_60HZScale[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action MC501CB_NoFliker[] = {
|
||
+static const struct usb_action mc501cb_NoFlikerScale[] = {
|
||
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
|
||
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
|
||
{0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
|
||
@@ -3132,7 +3168,7 @@ static const struct usb_action MC501CB_NoFliker[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action MC501CB_NoFlikerScale[] = {
|
||
+static const struct usb_action mc501cb_NoFliker[] = {
|
||
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
|
||
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
|
||
{0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
|
||
@@ -3144,11 +3180,16 @@ static const struct usb_action MC501CB_NoFlikerScale[] = {
|
||
{}
|
||
};
|
||
|
||
-/* from zs211.inf - HKR,%OV7620%,Initial - 640x480 */
|
||
-static const struct usb_action OV7620_mode0[] = {
|
||
+/* from zs211.inf */
|
||
+static const struct usb_action ov7620_Initial[] = { /* 640x480 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
{0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */
|
||
+#if 1 /*jfm*/
|
||
{0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
|
||
+#else
|
||
+ {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
|
||
+ /* mx change? */
|
||
+#endif
|
||
{0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
|
||
{0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
|
||
{0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
|
||
@@ -3214,9 +3255,7 @@ static const struct usb_action OV7620_mode0[] = {
|
||
{0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
|
||
{}
|
||
};
|
||
-
|
||
-/* from zs211.inf - HKR,%OV7620%,InitialScale - 320x240 */
|
||
-static const struct usb_action OV7620_mode1[] = {
|
||
+static const struct usb_action ov7620_InitialScale[] = { /* 320x240 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
{0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
|
||
@@ -3287,9 +3326,7 @@ static const struct usb_action OV7620_mode1[] = {
|
||
{0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
|
||
{}
|
||
};
|
||
-
|
||
-/* from zs211.inf - HKR,%OV7620%\AE,50HZ */
|
||
-static const struct usb_action OV7620_50HZ[] = {
|
||
+static const struct usb_action ov7620_50HZ[] = {
|
||
{0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
|
||
{0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
|
||
{0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
|
||
@@ -3307,9 +3344,7 @@ static const struct usb_action OV7620_50HZ[] = {
|
||
if mode0 (640x480) */
|
||
{}
|
||
};
|
||
-
|
||
-/* from zs211.inf - HKR,%OV7620%\AE,60HZ */
|
||
-static const struct usb_action OV7620_60HZ[] = {
|
||
+static const struct usb_action ov7620_60HZ[] = {
|
||
{0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
|
||
/* (bug in zs211.inf) */
|
||
{0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
|
||
@@ -3331,9 +3366,7 @@ static const struct usb_action OV7620_60HZ[] = {
|
||
{0xa1, 0x01, 0x0037}, */
|
||
{}
|
||
};
|
||
-
|
||
-/* from zs211.inf - HKR,%OV7620%\AE,NoFliker */
|
||
-static const struct usb_action OV7620_NoFliker[] = {
|
||
+static const struct usb_action ov7620_NoFliker[] = {
|
||
{0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
|
||
/* (bug in zs211.inf) */
|
||
{0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
|
||
@@ -3354,7 +3387,7 @@ static const struct usb_action OV7620_NoFliker[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action ov7630c_Initial[] = {
|
||
+static const struct usb_action ov7630c_InitialScale[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
@@ -3511,7 +3544,7 @@ static const struct usb_action ov7630c_Initial[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action ov7630c_InitialScale[] = {
|
||
+static const struct usb_action ov7630c_Initial[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
@@ -3682,7 +3715,7 @@ static const struct usb_action pas106b_Initial_com[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action pas106b_Initial[] = { /* 176x144 */
|
||
+static const struct usb_action pas106b_InitialScale[] = { /* 176x144 */
|
||
/* JPEG control */
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
/* Sream and Sensor specific */
|
||
@@ -3800,7 +3833,7 @@ static const struct usb_action pas106b_Initial[] = { /* 176x144 */
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action pas106b_InitialScale[] = { /* 352x288 */
|
||
+static const struct usb_action pas106b_Initial[] = { /* 352x288 */
|
||
/* JPEG control */
|
||
{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
/* Sream and Sensor specific */
|
||
@@ -3972,10 +4005,10 @@ static const struct usb_action pas106b_NoFliker[] = {
|
||
{}
|
||
};
|
||
|
||
-/* from usbvm31b.inf */
|
||
+/* from lvWIMv.inf 046d:08a2/:08aa 2007/06/03 */
|
||
static const struct usb_action pas202b_Initial[] = { /* 640x480 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
- {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
|
||
+ {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
{0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */
|
||
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
|
||
{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
|
||
@@ -4000,7 +4033,7 @@ static const struct usb_action pas202b_Initial[] = { /* 640x480 */
|
||
{0xaa, 0x09, 0x0006}, /* 00,09,06,aa */
|
||
{0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */
|
||
{0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */
|
||
- {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */
|
||
+ {0xaa, 0x0c, 0x0006},
|
||
{0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */
|
||
{0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
|
||
{0xaa, 0x12, 0x0005}, /* 00,12,05,aa */
|
||
@@ -4019,13 +4052,13 @@ static const struct usb_action pas202b_Initial[] = { /* 640x480 */
|
||
};
|
||
static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
- {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
|
||
+ {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
|
||
{0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */
|
||
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
|
||
{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
|
||
{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
|
||
{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
|
||
- {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
|
||
+ {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
|
||
{0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
|
||
{0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
|
||
{0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
|
||
@@ -4035,7 +4068,7 @@ static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */
|
||
{0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,08,cc */
|
||
{0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,02,cc */
|
||
{0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
|
||
- {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */
|
||
+ {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
|
||
{0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
|
||
{0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
|
||
{0xaa, 0x02, 0x0002}, /* 00,02,02,aa */
|
||
@@ -4044,7 +4077,7 @@ static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */
|
||
{0xaa, 0x09, 0x0006}, /* 00,09,06,aa */
|
||
{0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */
|
||
{0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */
|
||
- {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */
|
||
+ {0xaa, 0x0c, 0x0006},
|
||
{0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */
|
||
{0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
|
||
{0xaa, 0x12, 0x0005}, /* 00,12,05,aa */
|
||
@@ -4059,6 +4092,8 @@ static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */
|
||
{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
|
||
{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
|
||
{0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */
|
||
+ {0xa0, 0xff, ZC3XX_R097_WINYSTARTHIGH},
|
||
+ {0xa0, 0xfe, ZC3XX_R098_WINYSTARTLOW},
|
||
{}
|
||
};
|
||
static const struct usb_action pas202b_50HZ[] = {
|
||
@@ -4066,22 +4101,22 @@ static const struct usb_action pas202b_50HZ[] = {
|
||
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
|
||
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
|
||
{0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
|
||
- {0xaa, 0x21, 0x0068}, /* 00,21,68,aa */
|
||
+ {0xaa, 0x21, 0x001b},
|
||
{0xaa, 0x03, 0x0044}, /* 00,03,44,aa */
|
||
- {0xaa, 0x04, 0x0009}, /* 00,04,09,aa */
|
||
- {0xaa, 0x05, 0x0028}, /* 00,05,28,aa */
|
||
+ {0xaa, 0x04, 0x0008},
|
||
+ {0xaa, 0x05, 0x001b},
|
||
{0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
|
||
{0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
|
||
- {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */
|
||
+ {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
|
||
{0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
|
||
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
|
||
- {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
|
||
- {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,d2,cc */
|
||
+ {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
|
||
+ {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW},
|
||
{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
|
||
{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
|
||
{0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4d,cc */
|
||
- {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
|
||
- {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
|
||
+ {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
|
||
+ {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
|
||
{0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, /* 00,1d,44,cc */
|
||
{0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */
|
||
{0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */
|
||
@@ -4094,23 +4129,23 @@ static const struct usb_action pas202b_50HZScale[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
|
||
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
|
||
- {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
|
||
- {0xaa, 0x21, 0x006c}, /* 00,21,6c,aa */
|
||
+ {0xaa, 0x20, 0x0004},
|
||
+ {0xaa, 0x21, 0x003d},
|
||
{0xaa, 0x03, 0x0041}, /* 00,03,41,aa */
|
||
- {0xaa, 0x04, 0x0009}, /* 00,04,09,aa */
|
||
- {0xaa, 0x05, 0x002c}, /* 00,05,2c,aa */
|
||
+ {0xaa, 0x04, 0x0010},
|
||
+ {0xaa, 0x05, 0x003d},
|
||
{0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
|
||
{0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
|
||
- {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */
|
||
+ {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
|
||
{0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
|
||
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
|
||
- {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */
|
||
- {0xa0, 0xbe, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,be,cc */
|
||
+ {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
|
||
+ {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW},
|
||
{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
|
||
{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
|
||
{0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,9b,cc */
|
||
- {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
|
||
- {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
|
||
+ {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
|
||
+ {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
|
||
{0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */
|
||
{0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */
|
||
{0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */
|
||
@@ -4130,16 +4165,16 @@ static const struct usb_action pas202b_60HZ[] = {
|
||
{0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
|
||
{0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
|
||
{0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
|
||
- {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */
|
||
+ {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
|
||
{0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
|
||
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
|
||
- {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
|
||
- {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,c0,cc */
|
||
+ {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
|
||
+ {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
|
||
{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
|
||
{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
|
||
{0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,40,cc */
|
||
- {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
|
||
- {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
|
||
+ {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
|
||
+ {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
|
||
{0xa0, 0x45, ZC3XX_R01D_HSYNC_0}, /* 00,1d,45,cc */
|
||
{0xa0, 0x8e, ZC3XX_R01E_HSYNC_1}, /* 00,1e,8e,cc */
|
||
{0xa0, 0xc1, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c1,cc */
|
||
@@ -4152,23 +4187,23 @@ static const struct usb_action pas202b_60HZScale[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
|
||
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
|
||
- {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
|
||
- {0xaa, 0x21, 0x0004}, /* 00,21,04,aa */
|
||
+ {0xaa, 0x20, 0x0004},
|
||
+ {0xaa, 0x21, 0x0008},
|
||
{0xaa, 0x03, 0x0042}, /* 00,03,42,aa */
|
||
- {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */
|
||
- {0xaa, 0x05, 0x0004}, /* 00,05,04,aa */
|
||
+ {0xaa, 0x04, 0x0010},
|
||
+ {0xaa, 0x05, 0x0008},
|
||
{0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
|
||
{0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
|
||
- {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */
|
||
+ {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
|
||
{0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
|
||
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
|
||
- {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */
|
||
- {0xa0, 0x9f, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,9f,cc */
|
||
+ {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
|
||
+ {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW},
|
||
{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
|
||
{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
|
||
{0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */
|
||
- {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
|
||
- {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
|
||
+ {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
|
||
+ {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
|
||
{0xa0, 0x42, ZC3XX_R01D_HSYNC_0}, /* 00,1d,42,cc */
|
||
{0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */
|
||
{0xa0, 0xaf, ZC3XX_R01F_HSYNC_2}, /* 00,1f,af,cc */
|
||
@@ -4182,22 +4217,22 @@ static const struct usb_action pas202b_NoFliker[] = {
|
||
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
|
||
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
|
||
{0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
|
||
- {0xaa, 0x21, 0x0020}, /* 00,21,20,aa */
|
||
+ {0xaa, 0x21, 0x0006},
|
||
{0xaa, 0x03, 0x0040}, /* 00,03,40,aa */
|
||
{0xaa, 0x04, 0x0008}, /* 00,04,08,aa */
|
||
- {0xaa, 0x05, 0x0020}, /* 00,05,20,aa */
|
||
+ {0xaa, 0x05, 0x0006},
|
||
{0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
|
||
{0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
|
||
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
|
||
- {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
|
||
- {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
|
||
+ {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
|
||
+ {0xa0, 0x06, ZC3XX_R192_EXPOSURELIMITLOW},
|
||
{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
|
||
{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
|
||
- {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */
|
||
+ {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
|
||
{0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
|
||
{0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
|
||
{0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
|
||
- {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
|
||
+ {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
|
||
{0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */
|
||
{0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */
|
||
{0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
|
||
@@ -4210,23 +4245,23 @@ static const struct usb_action pas202b_NoFlikerScale[] = {
|
||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
|
||
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
|
||
- {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
|
||
- {0xaa, 0x21, 0x0010}, /* 00,21,10,aa */
|
||
+ {0xaa, 0x20, 0x0004},
|
||
+ {0xaa, 0x21, 0x000c},
|
||
{0xaa, 0x03, 0x0040}, /* 00,03,40,aa */
|
||
- {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */
|
||
- {0xaa, 0x05, 0x0010}, /* 00,05,10,aa */
|
||
+ {0xaa, 0x04, 0x0010},
|
||
+ {0xaa, 0x05, 0x000c},
|
||
{0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
|
||
{0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
|
||
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
|
||
- {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */
|
||
- {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
|
||
+ {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
|
||
+ {0xa0, 0x0c, ZC3XX_R192_EXPOSURELIMITLOW},
|
||
{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
|
||
{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
|
||
{0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */
|
||
{0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
|
||
{0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
|
||
{0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
|
||
- {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
|
||
+ {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
|
||
{0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */
|
||
{0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */
|
||
{0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
|
||
@@ -4713,8 +4748,8 @@ static const struct usb_action pb0330_NoFlikerScale[] = {
|
||
{}
|
||
};
|
||
|
||
-/* from oem9.inf - HKR,%PO2030%,Initial - 640x480 - (close to CS2102) */
|
||
-static const struct usb_action PO2030_mode0[] = {
|
||
+/* from oem9.inf */
|
||
+static const struct usb_action po2030_Initial[] = { /* 640x480 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
{0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
|
||
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
|
||
@@ -4790,8 +4825,8 @@ static const struct usb_action PO2030_mode0[] = {
|
||
{}
|
||
};
|
||
|
||
-/* from oem9.inf - HKR,%PO2030%,InitialScale - 320x240 */
|
||
-static const struct usb_action PO2030_mode1[] = {
|
||
+/* from oem9.inf */
|
||
+static const struct usb_action po2030_InitialScale[] = { /* 320x240 */
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
|
||
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
|
||
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
|
||
@@ -4867,7 +4902,7 @@ static const struct usb_action PO2030_mode1[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action PO2030_50HZ[] = {
|
||
+static const struct usb_action po2030_50HZ[] = {
|
||
{0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
|
||
{0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */
|
||
{0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */
|
||
@@ -4889,7 +4924,7 @@ static const struct usb_action PO2030_50HZ[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action PO2030_60HZ[] = {
|
||
+static const struct usb_action po2030_60HZ[] = {
|
||
{0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
|
||
{0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
|
||
{0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */
|
||
@@ -4912,7 +4947,7 @@ static const struct usb_action PO2030_60HZ[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action PO2030_NoFliker[] = {
|
||
+static const struct usb_action po2030_NoFliker[] = {
|
||
{0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
|
||
{0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
|
||
{0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
|
||
@@ -4924,7 +4959,7 @@ static const struct usb_action PO2030_NoFliker[] = {
|
||
};
|
||
|
||
/* TEST */
|
||
-static const struct usb_action tas5130CK_Initial[] = {
|
||
+static const struct usb_action tas5130cK_InitialScale[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x01, 0x003b},
|
||
{0xa0, 0x0e, 0x003a},
|
||
@@ -5127,7 +5162,7 @@ static const struct usb_action tas5130CK_Initial[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action tas5130CK_InitialScale[] = {
|
||
+static const struct usb_action tas5130cK_Initial[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
|
||
{0xa0, 0x01, 0x003b},
|
||
{0xa0, 0x0e, 0x003a},
|
||
@@ -5560,7 +5595,7 @@ static const struct usb_action tas5130cxx_NoFlikerScale[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action tas5130c_vf0250_Initial[] = {
|
||
+static const struct usb_action tas5130c_vf0250_InitialScale[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
|
||
{0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
|
||
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
|
||
@@ -5627,7 +5662,7 @@ static const struct usb_action tas5130c_vf0250_Initial[] = {
|
||
{}
|
||
};
|
||
|
||
-static const struct usb_action tas5130c_vf0250_InitialScale[] = {
|
||
+static const struct usb_action tas5130c_vf0250_Initial[] = {
|
||
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
|
||
{0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
|
||
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
|
||
@@ -5692,8 +5727,7 @@ static const struct usb_action tas5130c_vf0250_InitialScale[] = {
|
||
{0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
|
||
{}
|
||
};
|
||
-/* "50HZ" light frequency banding filter */
|
||
-static const struct usb_action tas5130c_vf0250_50HZ[] = {
|
||
+static const struct usb_action tas5130c_vf0250_50HZScale[] = {
|
||
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
|
||
{0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
|
||
{0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */
|
||
@@ -5717,8 +5751,7 @@ static const struct usb_action tas5130c_vf0250_50HZ[] = {
|
||
{}
|
||
};
|
||
|
||
-/* "50HZScale" light frequency banding filter */
|
||
-static const struct usb_action tas5130c_vf0250_50HZScale[] = {
|
||
+static const struct usb_action tas5130c_vf0250_50HZ[] = {
|
||
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
|
||
{0xaa, 0x83, 0x0003}, /* 00,83,03,aa */
|
||
{0xaa, 0x84, 0x0054}, /* 00,84,54,aa */
|
||
@@ -5742,8 +5775,7 @@ static const struct usb_action tas5130c_vf0250_50HZScale[] = {
|
||
{}
|
||
};
|
||
|
||
-/* "60HZ" light frequency banding filter */
|
||
-static const struct usb_action tas5130c_vf0250_60HZ[] = {
|
||
+static const struct usb_action tas5130c_vf0250_60HZScale[] = {
|
||
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
|
||
{0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
|
||
{0xaa, 0x84, 0x0062}, /* 00,84,62,aa */
|
||
@@ -5767,8 +5799,7 @@ static const struct usb_action tas5130c_vf0250_60HZ[] = {
|
||
{}
|
||
};
|
||
|
||
-/* "60HZScale" light frequency banding ilter */
|
||
-static const struct usb_action tas5130c_vf0250_60HZScale[] = {
|
||
+static const struct usb_action tas5130c_vf0250_60HZ[] = {
|
||
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
|
||
{0xaa, 0x83, 0x0002}, /* 00,83,02,aa */
|
||
{0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */
|
||
@@ -5792,8 +5823,7 @@ static const struct usb_action tas5130c_vf0250_60HZScale[] = {
|
||
{}
|
||
};
|
||
|
||
-/* "NoFliker" light frequency banding flter */
|
||
-static const struct usb_action tas5130c_vf0250_NoFliker[] = {
|
||
+static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = {
|
||
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
|
||
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
|
||
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
|
||
@@ -5815,8 +5845,7 @@ static const struct usb_action tas5130c_vf0250_NoFliker[] = {
|
||
{}
|
||
};
|
||
|
||
-/* "NoFlikerScale" light frequency banding filter */
|
||
-static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = {
|
||
+static const struct usb_action tas5130c_vf0250_NoFliker[] = {
|
||
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
|
||
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
|
||
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
|
||
@@ -5839,7 +5868,7 @@ static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = {
|
||
};
|
||
|
||
static u8 reg_r_i(struct gspca_dev *gspca_dev,
|
||
- __u16 index)
|
||
+ u16 index)
|
||
{
|
||
usb_control_msg(gspca_dev->dev,
|
||
usb_rcvctrlpipe(gspca_dev->dev, 0),
|
||
@@ -5852,7 +5881,7 @@ static u8 reg_r_i(struct gspca_dev *gspca_dev,
|
||
}
|
||
|
||
static u8 reg_r(struct gspca_dev *gspca_dev,
|
||
- __u16 index)
|
||
+ u16 index)
|
||
{
|
||
u8 ret;
|
||
|
||
@@ -5862,8 +5891,8 @@ static u8 reg_r(struct gspca_dev *gspca_dev,
|
||
}
|
||
|
||
static void reg_w_i(struct usb_device *dev,
|
||
- __u8 value,
|
||
- __u16 index)
|
||
+ u8 value,
|
||
+ u16 index)
|
||
{
|
||
usb_control_msg(dev,
|
||
usb_sndctrlpipe(dev, 0),
|
||
@@ -5874,18 +5903,18 @@ static void reg_w_i(struct usb_device *dev,
|
||
}
|
||
|
||
static void reg_w(struct usb_device *dev,
|
||
- __u8 value,
|
||
- __u16 index)
|
||
+ u8 value,
|
||
+ u16 index)
|
||
{
|
||
PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value);
|
||
reg_w_i(dev, value, index);
|
||
}
|
||
|
||
-static __u16 i2c_read(struct gspca_dev *gspca_dev,
|
||
- __u8 reg)
|
||
+static u16 i2c_read(struct gspca_dev *gspca_dev,
|
||
+ u8 reg)
|
||
{
|
||
- __u8 retbyte;
|
||
- __u16 retval;
|
||
+ u8 retbyte;
|
||
+ u16 retval;
|
||
|
||
reg_w_i(gspca_dev->dev, reg, 0x0092);
|
||
reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */
|
||
@@ -5900,12 +5929,12 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev,
|
||
return retval;
|
||
}
|
||
|
||
-static __u8 i2c_write(struct gspca_dev *gspca_dev,
|
||
- __u8 reg,
|
||
- __u8 valL,
|
||
- __u8 valH)
|
||
+static u8 i2c_write(struct gspca_dev *gspca_dev,
|
||
+ u8 reg,
|
||
+ u8 valL,
|
||
+ u8 valH)
|
||
{
|
||
- __u8 retbyte;
|
||
+ u8 retbyte;
|
||
|
||
reg_w_i(gspca_dev->dev, reg, 0x92);
|
||
reg_w_i(gspca_dev->dev, valL, 0x93);
|
||
@@ -5957,24 +5986,24 @@ static void setmatrix(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
int i;
|
||
- const __u8 *matrix;
|
||
+ const u8 *matrix;
|
||
static const u8 adcm2700_matrix[9] =
|
||
/* {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */
|
||
/*ms-win*/
|
||
{0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74};
|
||
- static const __u8 gc0305_matrix[9] =
|
||
+ static const u8 gc0305_matrix[9] =
|
||
{0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50};
|
||
- static const __u8 ov7620_matrix[9] =
|
||
+ static const u8 ov7620_matrix[9] =
|
||
{0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58};
|
||
- static const __u8 pas202b_matrix[9] =
|
||
+ static const u8 pas202b_matrix[9] =
|
||
{0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f};
|
||
- static const __u8 po2030_matrix[9] =
|
||
+ static const u8 po2030_matrix[9] =
|
||
{0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60};
|
||
static const u8 tas5130c_matrix[9] =
|
||
{0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68};
|
||
- static const __u8 vf0250_matrix[9] =
|
||
+ static const u8 vf0250_matrix[9] =
|
||
{0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b};
|
||
- static const __u8 *matrix_tb[SENSOR_MAX] = {
|
||
+ static const u8 *matrix_tb[SENSOR_MAX] = {
|
||
adcm2700_matrix, /* SENSOR_ADCM2700 0 */
|
||
ov7620_matrix, /* SENSOR_CS2102 1 */
|
||
NULL, /* SENSOR_CS2102K 2 */
|
||
@@ -6006,11 +6035,12 @@ static void setmatrix(struct gspca_dev *gspca_dev)
|
||
static void setbrightness(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- __u8 brightness;
|
||
+ u8 brightness;
|
||
|
||
switch (sd->sensor) {
|
||
case SENSOR_GC0305:
|
||
case SENSOR_OV7620:
|
||
+ case SENSOR_PAS202B:
|
||
case SENSOR_PO2030:
|
||
return;
|
||
}
|
||
@@ -6034,7 +6064,7 @@ static void setsharpness(struct gspca_dev *gspca_dev)
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct usb_device *dev = gspca_dev->dev;
|
||
int sharpness;
|
||
- static const __u8 sharpness_tb[][2] = {
|
||
+ static const u8 sharpness_tb[][2] = {
|
||
{0x02, 0x03},
|
||
{0x04, 0x07},
|
||
{0x08, 0x0f},
|
||
@@ -6053,118 +6083,69 @@ static void setcontrast(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct usb_device *dev = gspca_dev->dev;
|
||
- const __u8 *Tgamma, *Tgradient;
|
||
- int g, i, k;
|
||
- static const __u8 kgamma_tb[16] = /* delta for contrast */
|
||
+ const u8 *Tgamma;
|
||
+ int g, i, k, adj, gp;
|
||
+ u8 gr[16];
|
||
+ static const u8 delta_tb[16] = /* delta for contrast */
|
||
{0x15, 0x0d, 0x0a, 0x09, 0x08, 0x08, 0x08, 0x08,
|
||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
|
||
- static const __u8 kgrad_tb[16] =
|
||
- {0x1b, 0x06, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x04};
|
||
- static const __u8 Tgamma_1[16] =
|
||
+ static const u8 gamma_tb[6][16] = {
|
||
{0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f,
|
||
- 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff};
|
||
- static const __u8 Tgradient_1[16] =
|
||
- {0x00, 0x01, 0x05, 0x0b, 0x10, 0x15, 0x18, 0x1a,
|
||
- 0x1a, 0x18, 0x16, 0x14, 0x12, 0x0f, 0x0d, 0x06};
|
||
- static const __u8 Tgamma_2[16] =
|
||
+ 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff},
|
||
{0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c,
|
||
- 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff};
|
||
- static const __u8 Tgradient_2[16] =
|
||
- {0x05, 0x0f, 0x16, 0x1a, 0x19, 0x19, 0x17, 0x15,
|
||
- 0x12, 0x10, 0x0e, 0x0b, 0x09, 0x08, 0x06, 0x03};
|
||
- static const __u8 Tgamma_3[16] =
|
||
+ 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff},
|
||
{0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac,
|
||
- 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff};
|
||
- static const __u8 Tgradient_3[16] =
|
||
- {0x0c, 0x16, 0x1b, 0x1c, 0x19, 0x18, 0x15, 0x12,
|
||
- 0x10, 0x0d, 0x0b, 0x09, 0x08, 0x06, 0x05, 0x03};
|
||
- static const __u8 Tgamma_4[16] =
|
||
+ 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff},
|
||
{0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
|
||
- 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff};
|
||
- static const __u8 Tgradient_4[16] =
|
||
- {0x26, 0x22, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0d,
|
||
- 0x0b, 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02};
|
||
- static const __u8 Tgamma_5[16] =
|
||
+ 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff},
|
||
{0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2,
|
||
- 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff};
|
||
- static const __u8 Tgradient_5[16] =
|
||
- {0x37, 0x26, 0x20, 0x1a, 0x14, 0x10, 0x0e, 0x0b,
|
||
- 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02};
|
||
- static const __u8 Tgamma_6[16] = /* ?? was gamma 5 */
|
||
+ 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff},
|
||
{0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3,
|
||
- 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||
- static const __u8 Tgradient_6[16] =
|
||
- {0x18, 0x20, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0e,
|
||
- 0x0b, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||
- static const __u8 *gamma_tb[] = {
|
||
- NULL, Tgamma_1, Tgamma_2,
|
||
- Tgamma_3, Tgamma_4, Tgamma_5, Tgamma_6
|
||
- };
|
||
- static const __u8 *gradient_tb[] = {
|
||
- NULL, Tgradient_1, Tgradient_2,
|
||
- Tgradient_3, Tgradient_4, Tgradient_5, Tgradient_6
|
||
+ 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||
};
|
||
-#ifdef GSPCA_DEBUG
|
||
- __u8 v[16];
|
||
-#endif
|
||
|
||
- Tgamma = gamma_tb[sd->gamma];
|
||
- Tgradient = gradient_tb[sd->gamma];
|
||
+ Tgamma = gamma_tb[sd->gamma - 1];
|
||
|
||
- k = (sd->contrast - 128) /* -128 / 128 */
|
||
- * Tgamma[0];
|
||
- PDEBUG(D_CONF, "gamma:%d contrast:%d gamma coeff: %d/128",
|
||
- sd->gamma, sd->contrast, k);
|
||
+ k = ((int) sd->contrast - 128); /* -128 / 128 */
|
||
+ adj = 0;
|
||
+ gp = 0;
|
||
for (i = 0; i < 16; i++) {
|
||
- g = Tgamma[i] + kgamma_tb[i] * k / 128;
|
||
+ g = Tgamma[i] - delta_tb[i] * k / 128 - adj / 2;
|
||
if (g > 0xff)
|
||
g = 0xff;
|
||
else if (g <= 0)
|
||
g = 1;
|
||
reg_w(dev, g, 0x0120 + i); /* gamma */
|
||
-#ifdef GSPCA_DEBUG
|
||
- if (gspca_debug & D_CONF)
|
||
- v[i] = g;
|
||
-#endif
|
||
- }
|
||
- PDEBUG(D_CONF, "tb: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||
- v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
|
||
- PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x",
|
||
- v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]);
|
||
- for (i = 0; i < 16; i++) {
|
||
- g = Tgradient[i] - kgrad_tb[i] * k / 128;
|
||
- if (g > 0xff)
|
||
- g = 0xff;
|
||
- else if (g <= 0) {
|
||
- if (i != 15)
|
||
- g = 0;
|
||
+ if (k > 0)
|
||
+ adj--;
|
||
+ else
|
||
+ adj++;
|
||
+
|
||
+ if (i != 0) {
|
||
+ if (gp == 0)
|
||
+ gr[i - 1] = 0;
|
||
else
|
||
- g = 1;
|
||
+ gr[i - 1] = g - gp;
|
||
}
|
||
- reg_w(dev, g, 0x0130 + i); /* gradient */
|
||
-#ifdef GSPCA_DEBUG
|
||
- if (gspca_debug & D_CONF)
|
||
- v[i] = g;
|
||
-#endif
|
||
+ gp = g;
|
||
}
|
||
- PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x",
|
||
- v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
|
||
- PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x",
|
||
- v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]);
|
||
+ gr[15] = gr[14] / 2;
|
||
+ for (i = 0; i < 16; i++)
|
||
+ reg_w(dev, gr[i], 0x0130 + i); /* gradient */
|
||
}
|
||
|
||
static void setquality(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct usb_device *dev = gspca_dev->dev;
|
||
- __u8 frxt;
|
||
+ u8 frxt;
|
||
|
||
switch (sd->sensor) {
|
||
case SENSOR_ADCM2700:
|
||
case SENSOR_GC0305:
|
||
case SENSOR_HV7131B:
|
||
case SENSOR_OV7620:
|
||
+ case SENSOR_PAS202B:
|
||
case SENSOR_PO2030:
|
||
return;
|
||
}
|
||
@@ -6218,9 +6199,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
|
||
hdcs2020b_50HZ, hdcs2020b_50HZ,
|
||
hdcs2020b_60HZ, hdcs2020b_60HZ},
|
||
/* SENSOR_HV7131B 5 */
|
||
- {hv7131b_NoFlikerScale, hv7131b_NoFliker,
|
||
- hv7131b_50HZScale, hv7131b_50HZ,
|
||
- hv7131b_60HZScale, hv7131b_60HZ},
|
||
+ {hv7131b_NoFliker, hv7131b_NoFlikerScale,
|
||
+ hv7131b_50HZ, hv7131b_50HZScale,
|
||
+ hv7131b_60HZ, hv7131b_60HZScale},
|
||
/* SENSOR_HV7131C 6 */
|
||
{NULL, NULL,
|
||
NULL, NULL,
|
||
@@ -6230,17 +6211,17 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
|
||
icm105a_50HZ, icm105a_50HZScale,
|
||
icm105a_60HZ, icm105a_60HZScale},
|
||
/* SENSOR_MC501CB 8 */
|
||
- {MC501CB_NoFliker, MC501CB_NoFlikerScale,
|
||
- MC501CB_50HZ, MC501CB_50HZScale,
|
||
- MC501CB_60HZ, MC501CB_60HZScale},
|
||
+ {mc501cb_NoFliker, mc501cb_NoFlikerScale,
|
||
+ mc501cb_50HZ, mc501cb_50HZScale,
|
||
+ mc501cb_60HZ, mc501cb_60HZScale},
|
||
/* SENSOR_MI0360SOC 9 */
|
||
- {mi360soc_AENoFlikerScale, mi360soc_AENoFliker,
|
||
- mi360soc_AE50HZScale, mi360soc_AE50HZ,
|
||
- mi360soc_AE60HZScale, mi360soc_AE60HZ},
|
||
+ {mi360soc_AENoFliker, mi360soc_AENoFlikerScale,
|
||
+ mi360soc_AE50HZ, mi360soc_AE50HZScale,
|
||
+ mi360soc_AE60HZ, mi360soc_AE60HZScale},
|
||
/* SENSOR_OV7620 10 */
|
||
- {OV7620_NoFliker, OV7620_NoFliker,
|
||
- OV7620_50HZ, OV7620_50HZ,
|
||
- OV7620_60HZ, OV7620_60HZ},
|
||
+ {ov7620_NoFliker, ov7620_NoFliker,
|
||
+ ov7620_50HZ, ov7620_50HZ,
|
||
+ ov7620_60HZ, ov7620_60HZ},
|
||
/* SENSOR_OV7630C 11 */
|
||
{NULL, NULL,
|
||
NULL, NULL,
|
||
@@ -6258,17 +6239,17 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
|
||
pb0330_50HZScale, pb0330_50HZ,
|
||
pb0330_60HZScale, pb0330_60HZ},
|
||
/* SENSOR_PO2030 15 */
|
||
- {PO2030_NoFliker, PO2030_NoFliker,
|
||
- PO2030_50HZ, PO2030_50HZ,
|
||
- PO2030_60HZ, PO2030_60HZ},
|
||
+ {po2030_NoFliker, po2030_NoFliker,
|
||
+ po2030_50HZ, po2030_50HZ,
|
||
+ po2030_60HZ, po2030_60HZ},
|
||
/* SENSOR_TAS5130CK 16 */
|
||
- {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker,
|
||
- tas5130cxx_50HZScale, tas5130cxx_50HZ,
|
||
- tas5130cxx_60HZScale, tas5130cxx_60HZ},
|
||
+ {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale,
|
||
+ tas5130cxx_50HZ, tas5130cxx_50HZScale,
|
||
+ tas5130cxx_60HZ, tas5130cxx_60HZScale},
|
||
/* SENSOR_TAS5130CXX 17 */
|
||
- {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker,
|
||
- tas5130cxx_50HZScale, tas5130cxx_50HZ,
|
||
- tas5130cxx_60HZScale, tas5130cxx_60HZ},
|
||
+ {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale,
|
||
+ tas5130cxx_50HZ, tas5130cxx_50HZScale,
|
||
+ tas5130cxx_60HZ, tas5130cxx_60HZScale},
|
||
/* SENSOR_TAS5130C_VF0250 18 */
|
||
{tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale,
|
||
tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale,
|
||
@@ -6277,9 +6258,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
|
||
|
||
i = sd->lightfreq * 2;
|
||
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
|
||
- if (!mode)
|
||
- i++; /* 640x480 */
|
||
- zc3_freq = freq_tb[(int) sd->sensor][i];
|
||
+ if (mode)
|
||
+ i++; /* 320x240 */
|
||
+ zc3_freq = freq_tb[sd->sensor][i];
|
||
if (zc3_freq != NULL) {
|
||
usb_exchange(gspca_dev, zc3_freq);
|
||
switch (sd->sensor) {
|
||
@@ -6297,6 +6278,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
|
||
reg_w(gspca_dev->dev, 0x44, 0x0002);
|
||
}
|
||
break;
|
||
+ case SENSOR_PAS202B:
|
||
+ reg_w(gspca_dev->dev, 0x00, 0x01a7);
|
||
+ break;
|
||
}
|
||
}
|
||
return 0;
|
||
@@ -6305,7 +6289,7 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
|
||
static void setautogain(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
- __u8 autoval;
|
||
+ u8 autoval;
|
||
|
||
if (sd->autogain)
|
||
autoval = 0x42;
|
||
@@ -6333,6 +6317,12 @@ static void send_unknown(struct usb_device *dev, int sensor)
|
||
reg_w(dev, 0x02, 0x003b);
|
||
reg_w(dev, 0x00, 0x0038);
|
||
break;
|
||
+ case SENSOR_PAS202B:
|
||
+ reg_w(dev, 0x03, 0x003b);
|
||
+ reg_w(dev, 0x0c, 0x003a);
|
||
+ reg_w(dev, 0x0b, 0x0039);
|
||
+ reg_w(dev, 0x0b, 0x0038);
|
||
+ break;
|
||
}
|
||
}
|
||
|
||
@@ -6349,7 +6339,7 @@ static void start_2wr_probe(struct usb_device *dev, int sensor)
|
||
|
||
static int sif_probe(struct gspca_dev *gspca_dev)
|
||
{
|
||
- __u16 checkword;
|
||
+ u16 checkword;
|
||
|
||
start_2wr_probe(gspca_dev->dev, 0x0f); /* PAS106 */
|
||
reg_w(gspca_dev->dev, 0x08, 0x008d);
|
||
@@ -6392,6 +6382,7 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev)
|
||
}
|
||
|
||
start_2wr_probe(dev, 0x08); /* HDCS2020 */
|
||
+ i2c_write(gspca_dev, 0x1c, 0x00, 0x00);
|
||
i2c_write(gspca_dev, 0x15, 0xaa, 0x00);
|
||
retword = i2c_read(gspca_dev, 0x15);
|
||
if (retword != 0)
|
||
@@ -6410,7 +6401,11 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev)
|
||
return 0x0a; /* PB0330 ?? */
|
||
|
||
start_2wr_probe(dev, 0x0c); /* ICM105A */
|
||
+#if 1
|
||
i2c_write(gspca_dev, 0x01, 0x11, 0x00);
|
||
+#else
|
||
+ i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
|
||
+#endif
|
||
retword = i2c_read(gspca_dev, 0x01);
|
||
if (retword != 0)
|
||
return 0x0c; /* ICM105A */
|
||
@@ -6420,8 +6415,10 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev)
|
||
i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
|
||
msleep(50);
|
||
retword = i2c_read(gspca_dev, 0x03);
|
||
- if (retword != 0)
|
||
+ if (retword != 0) {
|
||
+ send_unknown(dev, SENSOR_PAS202B);
|
||
return 0x0e; /* PAS202BCB */
|
||
+ }
|
||
|
||
start_2wr_probe(dev, 0x02); /* TAS5130C */
|
||
i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
|
||
@@ -6457,8 +6454,8 @@ ov_check:
|
||
}
|
||
|
||
struct sensor_by_chipset_revision {
|
||
- __u16 revision;
|
||
- __u8 internal_sensor_id;
|
||
+ u16 revision;
|
||
+ u8 internal_sensor_id;
|
||
};
|
||
static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
|
||
{0xc000, 0x12}, /* TAS5130C */
|
||
@@ -6467,6 +6464,7 @@ static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
|
||
{0x8001, 0x13},
|
||
{0x8000, 0x14}, /* CS2102K */
|
||
{0x8400, 0x15}, /* TAS5130K */
|
||
+ {0xe400, 0x15},
|
||
};
|
||
|
||
static int vga_3wr_probe(struct gspca_dev *gspca_dev)
|
||
@@ -6474,7 +6472,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev)
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct usb_device *dev = gspca_dev->dev;
|
||
int i;
|
||
- __u8 retbyte;
|
||
+ u8 retbyte;
|
||
u16 retword;
|
||
|
||
/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
|
||
@@ -6622,8 +6620,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct cam *cam;
|
||
int sensor;
|
||
- int vga = 1; /* 1: vga, 0: sif */
|
||
- static const __u8 gamma[SENSOR_MAX] = {
|
||
+ static const u8 gamma[SENSOR_MAX] = {
|
||
4, /* SENSOR_ADCM2700 0 */
|
||
4, /* SENSOR_CS2102 1 */
|
||
5, /* SENSOR_CS2102K 2 */
|
||
@@ -6644,9 +6641,30 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
3, /* SENSOR_TAS5130CXX 17 */
|
||
3, /* SENSOR_TAS5130C_VF0250 18 */
|
||
};
|
||
+ static const u8 mode_tb[SENSOR_MAX] = {
|
||
+ 2, /* SENSOR_ADCM2700 0 */
|
||
+ 1, /* SENSOR_CS2102 1 */
|
||
+ 1, /* SENSOR_CS2102K 2 */
|
||
+ 1, /* SENSOR_GC0305 3 */
|
||
+ 1, /* SENSOR_HDCS2020b 4 */
|
||
+ 1, /* SENSOR_HV7131B 5 */
|
||
+ 1, /* SENSOR_HV7131C 6 */
|
||
+ 1, /* SENSOR_ICM105A 7 */
|
||
+ 2, /* SENSOR_MC501CB 8 */
|
||
+ 1, /* SENSOR_MI0360SOC 9 */
|
||
+ 2, /* SENSOR_OV7620 10 */
|
||
+ 1, /* SENSOR_OV7630C 11 */
|
||
+ 0, /* SENSOR_PAS106 12 */
|
||
+ 1, /* SENSOR_PAS202B 13 */
|
||
+ 1, /* SENSOR_PB0330 14 */
|
||
+ 1, /* SENSOR_PO2030 15 */
|
||
+ 1, /* SENSOR_TAS5130CK 16 */
|
||
+ 1, /* SENSOR_TAS5130CXX 17 */
|
||
+ 1, /* SENSOR_TAS5130C_VF0250 18 */
|
||
+ };
|
||
|
||
/* define some sensors from the vendor/product */
|
||
- sd->sharpness = 2;
|
||
+ sd->sharpness = SHARPNESS_DEF;
|
||
sd->sensor = id->driver_info;
|
||
sensor = zcxx_probeSensor(gspca_dev);
|
||
if (sensor >= 0)
|
||
@@ -6671,8 +6689,21 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
}
|
||
break;
|
||
case 0:
|
||
- PDEBUG(D_PROBE, "Find Sensor HV7131B");
|
||
- sd->sensor = SENSOR_HV7131B;
|
||
+ /* check the sensor type */
|
||
+ sensor = i2c_read(gspca_dev, 0x00);
|
||
+ PDEBUG(D_PROBE, "Sensor hv7131 type %d", sensor);
|
||
+ switch (sensor) {
|
||
+ case 0: /* hv7131b */
|
||
+ case 1: /* hv7131e */
|
||
+ PDEBUG(D_PROBE, "Find Sensor HV7131B");
|
||
+ sd->sensor = SENSOR_HV7131B;
|
||
+ break;
|
||
+ default:
|
||
+/* case 2: * hv7131r */
|
||
+ PDEBUG(D_PROBE, "Find Sensor HV7131R(c)");
|
||
+ sd->sensor = SENSOR_HV7131C;
|
||
+ break;
|
||
+ }
|
||
break;
|
||
case 0x02:
|
||
PDEBUG(D_PROBE, "Sensor TAS5130C");
|
||
@@ -6699,12 +6730,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
case 0x0e:
|
||
PDEBUG(D_PROBE, "Find Sensor PAS202B");
|
||
sd->sensor = SENSOR_PAS202B;
|
||
- sd->sharpness = 1;
|
||
+/* sd->sharpness = 1; */
|
||
break;
|
||
case 0x0f:
|
||
PDEBUG(D_PROBE, "Find Sensor PAS106");
|
||
sd->sensor = SENSOR_PAS106;
|
||
- vga = 0; /* SIF */
|
||
break;
|
||
case 0x10:
|
||
case 0x12:
|
||
@@ -6770,31 +6800,42 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
if (sensor < 0x20) {
|
||
if (sensor == -1 || sensor == 0x10 || sensor == 0x12)
|
||
reg_w(gspca_dev->dev, 0x02, 0x0010);
|
||
+#if 0
|
||
else
|
||
reg_w(gspca_dev->dev, sensor & 0x0f, 0x0010);
|
||
+#endif
|
||
reg_r(gspca_dev, 0x0010);
|
||
}
|
||
|
||
cam = &gspca_dev->cam;
|
||
/*fixme:test*/
|
||
gspca_dev->nbalt--;
|
||
- if (vga) {
|
||
- cam->cam_mode = vga_mode;
|
||
- cam->nmodes = ARRAY_SIZE(vga_mode);
|
||
- } else {
|
||
+ switch (mode_tb[sd->sensor]) {
|
||
+ case 0:
|
||
cam->cam_mode = sif_mode;
|
||
cam->nmodes = ARRAY_SIZE(sif_mode);
|
||
+ break;
|
||
+ case 1:
|
||
+ cam->cam_mode = vga_mode;
|
||
+ cam->nmodes = ARRAY_SIZE(vga_mode);
|
||
+ break;
|
||
+ default:
|
||
+/* case 2: */
|
||
+ cam->cam_mode = broken_vga_mode;
|
||
+ cam->nmodes = ARRAY_SIZE(broken_vga_mode);
|
||
+ break;
|
||
}
|
||
- sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
|
||
- sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
|
||
- sd->gamma = gamma[(int) sd->sensor];
|
||
- sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
|
||
- sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value;
|
||
+ sd->brightness = BRIGHTNESS_DEF;
|
||
+ sd->contrast = CONTRAST_DEF;
|
||
+ sd->gamma = gamma[sd->sensor];
|
||
+ sd->autogain = AUTOGAIN_DEF;
|
||
+ sd->lightfreq = FREQ_DEF;
|
||
sd->quality = QUALITY_DEF;
|
||
|
||
switch (sd->sensor) {
|
||
case SENSOR_GC0305:
|
||
case SENSOR_OV7620:
|
||
+ case SENSOR_PAS202B:
|
||
case SENSOR_PO2030:
|
||
gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX);
|
||
break;
|
||
@@ -6805,14 +6846,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||
break;
|
||
}
|
||
|
||
- /* switch the led off */
|
||
- reg_w(gspca_dev->dev, 0x01, 0x0000);
|
||
return 0;
|
||
}
|
||
|
||
/* this function is called at probe and resume time */
|
||
static int sd_init(struct gspca_dev *gspca_dev)
|
||
{
|
||
+ /* switch off the led */
|
||
reg_w(gspca_dev->dev, 0x01, 0x0000);
|
||
return 0;
|
||
}
|
||
@@ -6821,28 +6861,27 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
{
|
||
struct sd *sd = (struct sd *) gspca_dev;
|
||
struct usb_device *dev = gspca_dev->dev;
|
||
- const struct usb_action *zc3_init;
|
||
int mode;
|
||
static const struct usb_action *init_tb[SENSOR_MAX][2] = {
|
||
{adcm2700_Initial, adcm2700_InitialScale}, /* 0 */
|
||
- {cs2102_InitialScale, cs2102_Initial}, /* 1 */
|
||
- {cs2102K_InitialScale, cs2102K_Initial}, /* 2 */
|
||
+ {cs2102_Initial, cs2102_InitialScale}, /* 1 */
|
||
+ {cs2102K_Initial, cs2102K_InitialScale}, /* 2 */
|
||
{gc0305_Initial, gc0305_InitialScale}, /* 3 */
|
||
- {hdcs2020xb_InitialScale, hdcs2020xb_Initial}, /* 4 */
|
||
- {hv7131bxx_InitialScale, hv7131bxx_Initial}, /* 5 */
|
||
- {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */
|
||
- {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */
|
||
- {MC501CB_InitialScale, MC501CB_Initial}, /* 8 */
|
||
+ {hdcs2020b_Initial, hdcs2020b_InitialScale}, /* 4 */
|
||
+ {hv7131b_Initial, hv7131b_InitialScale}, /* 5 */
|
||
+ {hv7131r_Initial, hv7131r_InitialScale}, /* 6 */
|
||
+ {icm105a_Initial, icm105a_InitialScale}, /* 7 */
|
||
+ {mc501cb_Initial, mc501cb_InitialScale}, /* 8 */
|
||
{mi0360soc_Initial, mi0360soc_InitialScale}, /* 9 */
|
||
- {OV7620_mode0, OV7620_mode1}, /* 10 */
|
||
- {ov7630c_InitialScale, ov7630c_Initial}, /* 11 */
|
||
- {pas106b_InitialScale, pas106b_Initial}, /* 12 */
|
||
+ {ov7620_Initial, ov7620_InitialScale}, /* 10 */
|
||
+ {ov7630c_Initial, ov7630c_InitialScale}, /* 11 */
|
||
+ {pas106b_Initial, pas106b_InitialScale}, /* 12 */
|
||
{pas202b_Initial, pas202b_InitialScale}, /* 13 */
|
||
{pb0330_Initial, pb0330_InitialScale}, /* 14 */
|
||
- {PO2030_mode0, PO2030_mode1}, /* 15 */
|
||
- {tas5130CK_InitialScale, tas5130CK_Initial}, /* 16 */
|
||
+ {po2030_Initial, po2030_InitialScale}, /* 15 */
|
||
+ {tas5130cK_Initial, tas5130cK_InitialScale}, /* 16 */
|
||
{tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 17 */
|
||
- {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial},
|
||
+ {tas5130c_vf0250_Initial, tas5130c_vf0250_InitialScale},
|
||
/* 18 */
|
||
};
|
||
|
||
@@ -6854,8 +6893,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
0x21); /* JPEG 422 */
|
||
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
|
||
|
||
- mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
|
||
- zc3_init = init_tb[(int) sd->sensor][mode];
|
||
+ mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
|
||
switch (sd->sensor) {
|
||
case SENSOR_HV7131C:
|
||
zcxx_probeSensor(gspca_dev);
|
||
@@ -6864,7 +6902,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
usb_exchange(gspca_dev, pas106b_Initial_com);
|
||
break;
|
||
}
|
||
- usb_exchange(gspca_dev, zc3_init);
|
||
+ usb_exchange(gspca_dev, init_tb[sd->sensor][mode]);
|
||
|
||
switch (sd->sensor) {
|
||
case SENSOR_ADCM2700:
|
||
@@ -6883,6 +6921,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
reg_w(dev, 0x02, 0x003b);
|
||
reg_w(dev, 0x00, 0x0038);
|
||
break;
|
||
+ case SENSOR_PAS202B:
|
||
+ reg_w(dev, 0x03, 0x003b);
|
||
+ reg_w(dev, 0x0c, 0x003a);
|
||
+ reg_w(dev, 0x0b, 0x0039);
|
||
+ break;
|
||
}
|
||
|
||
setmatrix(gspca_dev);
|
||
@@ -6961,13 +7004,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||
switch (sd->sensor) {
|
||
case SENSOR_PO2030:
|
||
msleep(50);
|
||
- reg_r(gspca_dev, 0x0008);
|
||
- reg_r(gspca_dev, 0x0007);
|
||
- /*fall thru*/
|
||
- case SENSOR_PAS202B:
|
||
reg_w(dev, 0x00, 0x0007); /* (from win traces) */
|
||
reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING);
|
||
break;
|
||
+ case SENSOR_PAS202B:
|
||
+ reg_w(dev, 0x32, 0x0007); /* (from win traces) */
|
||
+ reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING);
|
||
+ break;
|
||
}
|
||
return 0;
|
||
}
|
||
@@ -7165,6 +7208,22 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
|
||
return 0;
|
||
}
|
||
|
||
+#ifdef CONFIG_INPUT
|
||
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
|
||
+ u8 *data, /* interrupt packet data */
|
||
+ int len) /* interrput packet length */
|
||
+{
|
||
+ if (len == 8 && data[4] == 1) {
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
|
||
+ input_sync(gspca_dev->input_dev);
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+#endif
|
||
+
|
||
static const struct sd_desc sd_desc = {
|
||
.name = MODULE_NAME,
|
||
.ctrls = sd_ctrls,
|
||
@@ -7177,6 +7236,9 @@ static const struct sd_desc sd_desc = {
|
||
.querymenu = sd_querymenu,
|
||
.get_jcomp = sd_get_jcomp,
|
||
.set_jcomp = sd_set_jcomp,
|
||
+#ifdef CONFIG_INPUT
|
||
+ .int_pkt_scan = sd_int_pkt_scan,
|
||
+#endif
|
||
};
|
||
|
||
static const __devinitdata struct usb_device_id device_table[] = {
|
||
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
|
||
index d4962a7..3793d16 100644
|
||
--- a/include/linux/videodev2.h
|
||
+++ b/include/linux/videodev2.h
|
||
@@ -350,6 +350,7 @@ struct v4l2_pix_format {
|
||
#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 */
|
||
|
||
/* Vendor-specific formats */
|
||
+#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
|
||
#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
|
||
#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
|
||
#define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
|
||
@@ -362,6 +363,7 @@ struct v4l2_pix_format {
|
||
#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
|
||
#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
|
||
#define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
|
||
+#define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
|
||
#define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
|
||
#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
|
||
#define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
|
||
--
|
||
1.7.0
|
||
|