Commit 4c98834a authored by Erik Andren's avatar Erik Andren Committed by Mauro Carvalho Chehab

V4L/DVB (10048): gspca - stv06xx: New subdriver.

Signed-off-by: default avatarErik Andren <erik.andren@gmail.com>
Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 15f64864
......@@ -50,6 +50,9 @@ ov519 045e:028c Micro$oft xbox cam
spca508 0461:0815 Micro Innovation IC200
sunplus 0461:0821 Fujifilm MV-1
zc3xx 0461:0a00 MicroInnovation WebCam320
stv06xx 046d:0840 QuickCam Express
stv06xx 046d:0850 LEGO cam / QuickCam Web
stv06xx 046d:0870 Dexxa WebCam USB
spca500 046d:0890 Logitech QuickCam traveler
vc032x 046d:0892 Logitech Orbicam
vc032x 046d:0896 Logitech Orbicam
......
......@@ -18,6 +18,7 @@ menuconfig USB_GSPCA
if USB_GSPCA && VIDEO_V4L2
source "drivers/media/video/gspca/m5602/Kconfig"
source "drivers/media/video/gspca/stv06xx/Kconfig"
config USB_GSPCA_CONEX
tristate "Conexant Camera Driver"
......
......@@ -47,4 +47,4 @@ gspca_vc032x-objs := vc032x.o
gspca_zc3xx-objs := zc3xx.o
obj-$(CONFIG_USB_M5602) += m5602/
obj-$(CONFIG_USB_STV06XX) += stv06xx/
config USB_STV06XX
tristate "STV06XX USB Camera Driver"
depends on USB_GSPCA
help
Say Y here if you want support for cameras based on
the ST STV06XX chip.
To compile this driver as a module, choose M here: the
module will be called gspca_stv06xx.
obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o
gspca_stv06xx-objs := stv06xx.o \
stv06xx_vv6410.o \
stv06xx_hdcs.o \
stv06xx_pb0100.o
This diff is collapsed.
/*
* Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
* Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
* Copyright (c) 2002, 2003 Tuukka Toivonen
* Copyright (c) 2008 Erik Andrén
*
* 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
*
* P/N 861037: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
* P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
* P/N 861075-0040: Sensor HDCS1000 ASIC
* P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
#ifndef STV06XX_H_
#define STV06XX_H_
#include "gspca.h"
#define MODULE_NAME "STV06xx"
#define STV_ISOC_ENDPOINT_ADDR 0x81
#ifndef V4L2_PIX_FMT_SGRBG8
#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G')
#endif
#define STV_REG23 0x0423
/* Control registers of the STV0600 ASIC */
#define STV_I2C_PARTNER 0x1420
#define STV_I2C_VAL_REG_VAL_PAIRS_MIN1 0x1421
#define STV_I2C_READ_WRITE_TOGGLE 0x1422
#define STV_I2C_FLUSH 0x1423
#define STV_I2C_SUCC_READ_REG_VALS 0x1424
#define STV_ISO_ENABLE 0x1440
#define STV_SCAN_RATE 0x1443
#define STV_LED_CTRL 0x1445
#define STV_STV0600_EMULATION 0x1446
#define STV_REG00 0x1500
#define STV_REG01 0x1501
#define STV_REG02 0x1502
#define STV_REG03 0x1503
#define STV_REG04 0x1504
#define STV_ISO_SIZE_L 0x15c1
#define STV_ISO_SIZE_H 0x15c2
/* Refers to the CIF 352x288 and QCIF 176x144 */
/* 1: 288 lines, 2: 144 lines */
#define STV_Y_CTRL 0x15c3
/* 0xa: 352 columns, 0x6: 176 columns */
#define STV_X_CTRL 0x1680
#define STV06XX_URB_MSG_TIMEOUT 5000
#define I2C_MAX_BYTES 16
#define I2C_MAX_WORDS 8
#define I2C_BUFFER_LENGTH 0x23
#define I2C_READ_CMD 3
#define I2C_WRITE_CMD 1
#define LED_ON 1
#define LED_OFF 0
/* STV06xx device descriptor */
struct sd {
struct gspca_dev gspca_dev;
/* A pointer to the currently connected sensor */
const struct stv06xx_sensor *sensor;
/* A pointer to the sd_desc struct */
struct sd_desc desc;
/* Sensor private data */
void *sensor_priv;
};
int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data);
int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data);
int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len);
int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len);
int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value);
int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value);
#endif
This diff is collapsed.
/*
* Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
* Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
* Copyright (c) 2002, 2003 Tuukka Toivonen
* Copyright (c) 2008 Erik Andrén
* Copyright (c) 2008 Chia-I Wu
*
* 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
*
* P/N 861037: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
* P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
* P/N 861075-0040: Sensor HDCS1000 ASIC
* P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
#ifndef STV06XX_HDCS_H_
#define STV06XX_HDCS_H_
#include "stv06xx_sensor.h"
#define HDCS_REG_CONFIG(sd) (IS_1020(sd) ? HDCS20_CONFIG : HDCS00_CONFIG)
#define HDCS_REG_CONTROL(sd) (IS_1020(sd) ? HDCS20_CONTROL : HDCS00_CONTROL)
#define HDCS_1X00_DEF_WIDTH 360
#define HDCS_1X00_DEF_HEIGHT 296
#define HDCS_1020_DEF_WIDTH 352
#define HDCS_1020_DEF_HEIGHT 292
#define HDCS_1020_BOTTOM_Y_SKIP 4
#define HDCS_CLK_FREQ_MHZ 25
#define HDCS_ADC_START_SIG_DUR 3
/* LSB bit of I2C or register address signifies write (0) or read (1) */
/* I2C Registers common for both HDCS-1000/1100 and HDCS-1020 */
/* Identifications Register */
#define HDCS_IDENT (0x00 << 1)
/* Status Register */
#define HDCS_STATUS (0x01 << 1)
/* Interrupt Mask Register */
#define HDCS_IMASK (0x02 << 1)
/* Pad Control Register */
#define HDCS_PCTRL (0x03 << 1)
/* Pad Drive Control Register */
#define HDCS_PDRV (0x04 << 1)
/* Interface Control Register */
#define HDCS_ICTRL (0x05 << 1)
/* Interface Timing Register */
#define HDCS_ITMG (0x06 << 1)
/* Baud Fraction Register */
#define HDCS_BFRAC (0x07 << 1)
/* Baud Rate Register */
#define HDCS_BRATE (0x08 << 1)
/* ADC Control Register */
#define HDCS_ADCCTRL (0x09 << 1)
/* First Window Row Register */
#define HDCS_FWROW (0x0a << 1)
/* First Window Column Register */
#define HDCS_FWCOL (0x0b << 1)
/* Last Window Row Register */
#define HDCS_LWROW (0x0c << 1)
/* Last Window Column Register */
#define HDCS_LWCOL (0x0d << 1)
/* Timing Control Register */
#define HDCS_TCTRL (0x0e << 1)
/* PGA Gain Register: Even Row, Even Column */
#define HDCS_ERECPGA (0x0f << 1)
/* PGA Gain Register: Even Row, Odd Column */
#define HDCS_EROCPGA (0x10 << 1)
/* PGA Gain Register: Odd Row, Even Column */
#define HDCS_ORECPGA (0x11 << 1)
/* PGA Gain Register: Odd Row, Odd Column */
#define HDCS_OROCPGA (0x12 << 1)
/* Row Exposure Low Register */
#define HDCS_ROWEXPL (0x13 << 1)
/* Row Exposure High Register */
#define HDCS_ROWEXPH (0x14 << 1)
/* I2C Registers only for HDCS-1000/1100 */
/* Sub-Row Exposure Low Register */
#define HDCS00_SROWEXPL (0x15 << 1)
/* Sub-Row Exposure High Register */
#define HDCS00_SROWEXPH (0x16 << 1)
/* Configuration Register */
#define HDCS00_CONFIG (0x17 << 1)
/* Control Register */
#define HDCS00_CONTROL (0x18 << 1)
/* I2C Registers only for HDCS-1020 */
/* Sub-Row Exposure Register */
#define HDCS20_SROWEXP (0x15 << 1)
/* Error Control Register */
#define HDCS20_ERROR (0x16 << 1)
/* Interface Timing 2 Register */
#define HDCS20_ITMG2 (0x17 << 1)
/* Interface Control 2 Register */
#define HDCS20_ICTRL2 (0x18 << 1)
/* Horizontal Blank Register */
#define HDCS20_HBLANK (0x19 << 1)
/* Vertical Blank Register */
#define HDCS20_VBLANK (0x1a << 1)
/* Configuration Register */
#define HDCS20_CONFIG (0x1b << 1)
/* Control Register */
#define HDCS20_CONTROL (0x1c << 1)
#define HDCS_RUN_ENABLE (1 << 2)
#define HDCS_SLEEP_MODE (1 << 1)
#define HDCS_DEFAULT_EXPOSURE 5000
#define HDCS_DEFAULT_GAIN 128
static int hdcs_probe_1x00(struct sd *sd);
static int hdcs_probe_1020(struct sd *sd);
static int hdcs_start(struct sd *sd);
static int hdcs_init(struct sd *sd);
static int hdcs_stop(struct sd *sd);
static int hdcs_dump(struct sd *sd);
static void hdcs_disconnect(struct sd *sd);
static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val);
static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = {
.name = "HP HDCS-1000/1100",
.i2c_flush = 0,
.i2c_addr = (0x55 << 1),
.i2c_len = 1,
.init = hdcs_init,
.probe = hdcs_probe_1x00,
.start = hdcs_start,
.stop = hdcs_stop,
.disconnect = hdcs_disconnect,
.dump = hdcs_dump,
.nctrls = 2,
.ctrls = {
{
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "exposure",
.minimum = 0x00,
.maximum = 0xffff,
.step = 0x1,
.default_value = HDCS_DEFAULT_EXPOSURE,
.flags = V4L2_CTRL_FLAG_SLIDER
},
.set = hdcs_set_exposure,
.get = hdcs_get_exposure
},
{
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "gain",
.minimum = 0x00,
.maximum = 0xff,
.step = 0x1,
.default_value = HDCS_DEFAULT_GAIN,
.flags = V4L2_CTRL_FLAG_SLIDER
},
.set = hdcs_set_gain,
.get = hdcs_get_gain
}
},
.nmodes = 1,
.modes = {
{
HDCS_1X00_DEF_WIDTH,
HDCS_1X00_DEF_HEIGHT,
V4L2_PIX_FMT_SBGGR8,
V4L2_FIELD_NONE,
.sizeimage =
HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
.bytesperline = HDCS_1X00_DEF_WIDTH,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1
}
}
};
const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = {
.name = "HDCS-1020",
.i2c_flush = 0,
.i2c_addr = (0x55 << 1),
.i2c_len = 1,
.nctrls = 0,
.ctrls = {},
.init = hdcs_init,
.probe = hdcs_probe_1020,
.start = hdcs_start,
.stop = hdcs_stop,
.dump = hdcs_dump,
.nmodes = 1,
.modes = {
{
HDCS_1020_DEF_WIDTH,
HDCS_1020_DEF_HEIGHT,
V4L2_PIX_FMT_SBGGR8,
V4L2_FIELD_NONE,
.sizeimage =
HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
.bytesperline = HDCS_1020_DEF_WIDTH,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1
}
}
};
static const u16 stv_bridge_init[][2] = {
{STV_ISO_ENABLE, 0},
{STV_REG23, 0},
{STV_REG00, 0x1d},
{STV_REG01, 0xb5},
{STV_REG02, 0xa8},
{STV_REG03, 0x95},
{STV_REG04, 0x07},
{STV_SCAN_RATE, 0x20},
{STV_ISO_SIZE_L, 847},
{STV_Y_CTRL, 0x01},
{STV_X_CTRL, 0x0a}
};
static const u8 stv_sensor_init[][2] = {
/* Clear status (writing 1 will clear the corresponding status bit) */
{HDCS_STATUS, BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
/* Disable all interrupts */
{HDCS_IMASK, 0x00},
{HDCS_PCTRL, BIT(6) | BIT(5) | BIT(1) | BIT(0)},
{HDCS_PDRV, 0x00},
{HDCS_ICTRL, BIT(5)},
{HDCS_ITMG, BIT(4) | BIT(1)},
/* ADC output resolution to 10 bits */
{HDCS_ADCCTRL, 10}
};
#endif
This diff is collapsed.
/*
* Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
* Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
* Copyright (c) 2002, 2003 Tuukka Toivonen
* Copyright (c) 2008 Erik Andrén
*
* 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
*
* P/N 861037: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
* P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
* P/N 861075-0040: Sensor HDCS1000 ASIC
* P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
#ifndef STV06XX_PB0100_H_
#define STV06XX_PB0100_H_
#include "stv06xx_sensor.h"
/* mode priv field flags */
#define PB0100_CROP_TO_VGA 0x01
#define PB0100_SUBSAMPLE 0x02
/* I2C Registers */
#define PB_IDENT 0x00 /* Chip Version */
#define PB_RSTART 0x01 /* Row Window Start */
#define PB_CSTART 0x02 /* Column Window Start */
#define PB_RWSIZE 0x03 /* Row Window Size */
#define PB_CWSIZE 0x04 /* Column Window Size */
#define PB_CFILLIN 0x05 /* Column Fill-In */
#define PB_VBL 0x06 /* Vertical Blank Count */
#define PB_CONTROL 0x07 /* Control Mode */
#define PB_FINTTIME 0x08 /* Integration Time/Frame Unit Count */
#define PB_RINTTIME 0x09 /* Integration Time/Row Unit Count */
#define PB_ROWSPEED 0x0a /* Row Speed Control */
#define PB_ABORTFRAME 0x0b /* Abort Frame */
#define PB_R12 0x0c /* Reserved */
#define PB_RESET 0x0d /* Reset */
#define PB_EXPGAIN 0x0e /* Exposure Gain Command */
#define PB_R15 0x0f /* Expose0 */
#define PB_R16 0x10 /* Expose1 */
#define PB_R17 0x11 /* Expose2 */
#define PB_R18 0x12 /* Low0_DAC */
#define PB_R19 0x13 /* Low1_DAC */
#define PB_R20 0x14 /* Low2_DAC */
#define PB_R21 0x15 /* Threshold11 */
#define PB_R22 0x16 /* Threshold0x */
#define PB_UPDATEINT 0x17 /* Update Interval */
#define PB_R24 0x18 /* High_DAC */
#define PB_R25 0x19 /* Trans0H */
#define PB_R26 0x1a /* Trans1L */
#define PB_R27 0x1b /* Trans1H */
#define PB_R28 0x1c /* Trans2L */
#define PB_R29 0x1d /* Reserved */
#define PB_R30 0x1e /* Reserved */
#define PB_R31 0x1f /* Wait to Read */
#define PB_PREADCTRL 0x20 /* Pixel Read Control Mode */
#define PB_R33 0x21 /* IREF_VLN */
#define PB_R34 0x22 /* IREF_VLP */
#define PB_R35 0x23 /* IREF_VLN_INTEG */
#define PB_R36 0x24 /* IREF_MASTER */
#define PB_R37 0x25 /* IDACP */
#define PB_R38 0x26 /* IDACN */
#define PB_R39 0x27 /* DAC_Control_Reg */
#define PB_R40 0x28 /* VCL */
#define PB_R41 0x29 /* IREF_VLN_ADCIN */
#define PB_R42 0x2a /* Reserved */
#define PB_G1GAIN 0x2b /* Green 1 Gain */
#define PB_BGAIN 0x2c /* Blue Gain */
#define PB_RGAIN 0x2d /* Red Gain */
#define PB_G2GAIN 0x2e /* Green 2 Gain */
#define PB_R47 0x2f /* Dark Row Address */
#define PB_R48 0x30 /* Dark Row Options */
#define PB_R49 0x31 /* Reserved */
#define PB_R50 0x32 /* Image Test Data */
#define PB_ADCMAXGAIN 0x33 /* Maximum Gain */
#define PB_ADCMINGAIN 0x34 /* Minimum Gain */
#define PB_ADCGLOBALGAIN 0x35 /* Global Gain */
#define PB_R54 0x36 /* Maximum Frame */
#define PB_R55 0x37 /* Minimum Frame */
#define PB_R56 0x38 /* Reserved */
#define PB_VOFFSET 0x39 /* VOFFSET */
#define PB_R58 0x3a /* Snap-Shot Sequence Trigger */
#define PB_ADCGAINH 0x3b /* VREF_HI */
#define PB_ADCGAINL 0x3c /* VREF_LO */
#define PB_R61 0x3d /* Reserved */
#define PB_R62 0x3e /* Reserved */
#define PB_R63 0x3f /* Reserved */
#define PB_R64 0x40 /* Red/Blue Gain */
#define PB_R65 0x41 /* Green 2/Green 1 Gain */
#define PB_R66 0x42 /* VREF_HI/LO */
#define PB_R67 0x43 /* Integration Time/Row Unit Count */
#define PB_R240 0xf0 /* ADC Test */
#define PB_R241 0xf1 /* Chip Enable */
#define PB_R242 0xf2 /* Reserved */
static int pb0100_probe(struct sd *sd);
static int pb0100_start(struct sd *sd);
static int pb0100_init(struct sd *sd);
static int pb0100_stop(struct sd *sd);
static int pb0100_dump(struct sd *sd);
/* V4L2 controls supported by the driver */
static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val);
static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val);
static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val);
static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val);
static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val);
static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val);
static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val);
const struct stv06xx_sensor stv06xx_sensor_pb0100 = {
.name = "PB-0100",
.i2c_flush = 1,
.i2c_addr = 0xba,
.i2c_len = 2,
.nctrls = 7,
.ctrls = {
#define GAIN_IDX 0
{
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Gain",
.minimum = 0,
.maximum = 255,
.step = 1,
.default_value = 128
},
.set = pb0100_set_gain,
.get = pb0100_get_gain
},
#define RED_BALANCE_IDX 1
{
{
.id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Red Balance",
.minimum = -255,
.maximum = 255,
.step = 1,
.default_value = 0
},
.set = pb0100_set_red_balance,
.get = pb0100_get_red_balance
},
#define BLUE_BALANCE_IDX 2
{
{
.id = V4L2_CID_BLUE_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Blue Balance",
.minimum = -255,
.maximum = 255,
.step = 1,
.default_value = 0
},
.set = pb0100_set_blue_balance,
.get = pb0100_get_blue_balance
},
#define EXPOSURE_IDX 3
{
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Exposure",
.minimum = 0,
.maximum = 511,
.step = 1,
.default_value = 12
},
.set = pb0100_set_exposure,
.get = pb0100_get_exposure
},
#define AUTOGAIN_IDX 4
{
{
.id = V4L2_CID_AUTOGAIN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Automatic Gain and Exposure",
.minimum = 0,
.maximum = 1,
.step = 1,
.default_value = 1
},
.set = pb0100_set_autogain,
.get = pb0100_get_autogain
},
#define AUTOGAIN_TARGET_IDX 5
{
{
.id = V4L2_CTRL_CLASS_USER + 0x1000,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Automatic Gain Target",
.minimum = 0,
.maximum = 255,
.step = 1,
.default_value = 128
},
.set = pb0100_set_autogain_target,
.get = pb0100_get_autogain_target
},
#define NATURAL_IDX 6
{
{
.id = V4L2_CTRL_CLASS_USER + 0x1001,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Natural Light Source",
.minimum = 0,
.maximum = 1,
.step = 1,
.default_value = 1
},
.set = pb0100_set_natural,
.get = pb0100_get_natural
},
},
.init = pb0100_init,
.probe = pb0100_probe,
.start = pb0100_start,
.stop = pb0100_stop,
.dump = pb0100_dump,
.nmodes = 2,
.modes = {
/* low res / subsample modes disabled as they are only half res horizontal,
halving the vertical resolution does not seem to work */
{
320,
240,
V4L2_PIX_FMT_SGRBG8,
V4L2_FIELD_NONE,
.sizeimage = 320 * 240,
.bytesperline = 320,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = PB0100_CROP_TO_VGA
},
{
352,
288,
V4L2_PIX_FMT_SGRBG8,
V4L2_FIELD_NONE,
.sizeimage = 352 * 288,
.bytesperline = 352,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0
},
}
};
#endif
/*
* Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
* Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
* Copyright (c) 2002, 2003 Tuukka Toivonen
* Copyright (c) 2008 Erik Andrén
*
* 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
*
* P/N 861037: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
* P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
* P/N 861075-0040: Sensor HDCS1000 ASIC
* P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
#ifndef STV06XX_SENSOR_H_
#define STV06XX_SENSOR_H_
#include "stv06xx.h"
#define IS_850(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x850)
#define IS_870(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x870)
#define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020)
extern const struct stv06xx_sensor stv06xx_sensor_vv6410;
extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00;
extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020;
extern const struct stv06xx_sensor stv06xx_sensor_pb0100;
#define STV06XX_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10)
struct stv06xx_sensor {
/* Defines the name of a sensor */
char name[32];
/* Sensor i2c address */
u8 i2c_addr;
/* Flush value*/
u8 i2c_flush;
/* length of an i2c word */
u8 i2c_len;
/* Probes if the sensor is connected */
int (*probe)(struct sd *sd);
/* Performs a initialization sequence */
int (*init)(struct sd *sd);
/* Executed at device disconnect */
void (*disconnect)(struct sd *sd);
/* Reads a sensor register */
int (*read_sensor)(struct sd *sd, const u8 address,
u8 *i2c_data, const u8 len);
/* Writes to a sensor register */
int (*write_sensor)(struct sd *sd, const u8 address,
u8 *i2c_data, const u8 len);
/* Instructs the sensor to start streaming */
int (*start)(struct sd *sd);
/* Instructs the sensor to stop streaming */
int (*stop)(struct sd *sd);
/* Instructs the sensor to dump all its contents */
int (*dump)(struct sd *sd);
int nctrls;
struct ctrl ctrls[STV06XX_MAX_CTRLS];
char nmodes;
struct v4l2_pix_format modes[];
};
#endif
/*
* Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
* Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
* Copyright (c) 2002, 2003 Tuukka Toivonen
* Copyright (c) 2008 Erik Andrén
*
* 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
*
* P/N 861037: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
* P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
* P/N 861075-0040: Sensor HDCS1000 ASIC
* P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
#include "stv06xx_vv6410.h"
static int vv6410_probe(struct sd *sd)
{
u16 data;
int err;
err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data);
if (err < 0)
return -ENODEV;
if (data == 0x19) {
info("vv6410 sensor detected");
sd->gspca_dev.cam.cam_mode = stv06xx_sensor_vv6410.modes;
sd->gspca_dev.cam.nmodes = stv06xx_sensor_vv6410.nmodes;
sd->desc.ctrls = stv06xx_sensor_vv6410.ctrls;
sd->desc.nctrls = stv06xx_sensor_vv6410.nctrls;
return 0;
}
return -ENODEV;
}
static int vv6410_init(struct sd *sd)
{
int err = 0, i;
for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
/* if NULL then len contains single value */
if (stv_bridge_init[i].data == NULL) {
err = stv06xx_write_bridge(sd,
stv_bridge_init[i].start,
stv_bridge_init[i].len);
} else {
int j;
for (j = 0; j < stv_bridge_init[i].len; j++)
err = stv06xx_write_bridge(sd,
stv_bridge_init[i].start + j,
stv_bridge_init[i].data[j]);
}
}
if (err < 0)
return err;
err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
ARRAY_SIZE(vv6410_sensor_init));
return (err < 0) ? err : 0;
}
static int vv6410_start(struct sd *sd)
{
int err;
struct cam *cam = &sd->gspca_dev.cam;
u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
if (priv & VV6410_CROP_TO_QVGA) {
PDEBUG(D_CONF, "Cropping to QVGA");
stv06xx_write_sensor(sd, VV6410_XENDH, 320 - 1);
stv06xx_write_sensor(sd, VV6410_YENDH, 240 - 1);
} else {
stv06xx_write_sensor(sd, VV6410_XENDH, 360 - 1);
stv06xx_write_sensor(sd, VV6410_YENDH, 294 - 1);
}
if (priv & VV6410_SUBSAMPLE) {
PDEBUG(D_CONF, "Enabling subsampling");
stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
} else {
stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
}
/* Turn on LED */
err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
if (err < 0)
return err;
err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0);
if (err < 0)
return err;
PDEBUG(D_STREAM, "Starting stream");
return 0;
}
static int vv6410_stop(struct sd *sd)
{
int err;
/* Turn off LED */
err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
if (err < 0)
return err;
err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE);
if (err < 0)
return err;
PDEBUG(D_STREAM, "Halting stream");
return (err < 0) ? err : 0;
}
static int vv6410_dump(struct sd *sd)
{
u8 i;
int err = 0;
info("Dumping all vv6410 sensor registers");
for (i = 0; i < 0xff && !err; i++) {
u16 data;
err = stv06xx_read_sensor(sd, i, &data);
info("Register 0x%x contained 0x%x", i, data);
}
return (err < 0) ? err : 0;
}
static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
{
int err;
u16 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
*val = (i2c_data & VV6410_HFLIP) ? 1 : 0;
PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
return (err < 0) ? err : 0;
}
static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u16 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
if (err < 0)
return err;
if (val)
i2c_data |= VV6410_HFLIP;
else
i2c_data &= ~VV6410_HFLIP;
PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
return (err < 0) ? err : 0;
}
static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
{
int err;
u16 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
*val = (i2c_data & VV6410_VFLIP) ? 1 : 0;
PDEBUG(D_V4L2, "Read vertical flip %d", *val);
return (err < 0) ? err : 0;
}
static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
u16 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
if (err < 0)
return err;
if (val)
i2c_data |= VV6410_VFLIP;
else
i2c_data &= ~VV6410_VFLIP;
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
return (err < 0) ? err : 0;
}
static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val)
{
int err;
u16 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
err = stv06xx_read_sensor(sd, VV6410_ANALOGGAIN, &i2c_data);
*val = i2c_data & 0xf;
PDEBUG(D_V4L2, "Read analog gain %d", *val);
return (err < 0) ? err : 0;
}
static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
{
int err;
struct sd *sd = (struct sd *) gspca_dev;
PDEBUG(D_V4L2, "Set analog gain to %d", val);
err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
return (err < 0) ? err : 0;
}
/*
* Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
* Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
* Copyright (c) 2002, 2003 Tuukka Toivonen
* Copyright (c) 2008 Erik Andrén
*
* 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
*
* P/N 861037: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
* P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
* P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
* P/N 861075-0040: Sensor HDCS1000 ASIC
* P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
* P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
*/
#ifndef STV06XX_VV6410_H_
#define STV06XX_VV6410_H_
#include "stv06xx_sensor.h"
#define VV6410_COLS 416
#define VV6410_ROWS 320
/* Status registers */
/* Chip identification number including revision indicator */
#define VV6410_DEVICEH 0x00
#define VV6410_DEVICEL 0x01
/* User can determine whether timed I2C data
has been consumed by interrogating flag states */
#define VV6410_STATUS0 0x02
/* Current line counter value */
#define VV6410_LINECOUNTH 0x03
#define VV6410_LINECOUNTL 0x04
/* End x coordinate of image size */
#define VV6410_XENDH 0x05
#define VV6410_XENDL 0x06
/* End y coordinate of image size */
#define VV6410_YENDH 0x07
#define VV6410_YENDL 0x08
/* This is the average pixel value returned from the
dark line offset cancellation algorithm */
#define VV6410_DARKAVGH 0x09
#define VV6410_DARKAVGL 0x0a
/* This is the average pixel value returned from the
black line offset cancellation algorithm */
#define VV6410_BLACKAVGH 0x0b
#define VV6410_BLACKAVGL 0x0c
/* Flags to indicate whether the x or y image coordinates have been clipped */
#define VV6410_STATUS1 0x0d
/* Setup registers */
/* Low-power/sleep modes & video timing */
#define VV6410_SETUP0 0x10
/* Various parameters */
#define VV6410_SETUP1 0x11
/* Contains pixel counter reset value used by external sync */
#define VV6410_SYNCVALUE 0x12
/* Frame grabbing modes (FST, LST and QCK) */
#define VV6410_FGMODES 0x14
/* FST and QCK mapping modes. */
#define VV6410_PINMAPPING 0x15
/* Data resolution */
#define VV6410_DATAFORMAT 0x16
/* Output coding formats */
#define VV6410_OPFORMAT 0x17
/* Various mode select bits */
#define VV6410_MODESELECT 0x18
/* Exposure registers */
/* Fine exposure. */
#define VV6410_FINEH 0x20
#define VV6410_FINEL 0x21
/* Coarse exposure */
#define VV6410_COARSEH 0x22
#define VV6410_COARSEL 0x23
/* Analog gain setting */
#define VV6410_ANALOGGAIN 0x24
/* Clock division */
#define VV6410_CLKDIV 0x25
/* Dark line offset cancellation value */
#define VV6410_DARKOFFSETH 0x2c
#define VV6410_DARKOFFSETL 0x2d
/* Dark line offset cancellation enable */
#define VV6410_DARKOFFSETSETUP 0x2e
/* Video timing registers */
/* Line Length (Pixel Clocks) */
#define VV6410_LINELENGTHH 0x52
#define VV6410_LINELENGTHL 0x53
/* X-co-ordinate of top left corner of region of interest (x-offset) */
#define VV6410_XOFFSETH 0x57
#define VV6410_XOFFSETL 0x58
/* Y-coordinate of top left corner of region of interest (y-offset) */
#define VV6410_YOFFSETH 0x59
#define VV6410_YOFFSETL 0x5a
/* Field length (Lines) */
#define VV6410_FIELDLENGTHH 0x61
#define VV6410_FIELDLENGTHL 0x62
/* System registers */
/* Black offset cancellation default value */
#define VV6410_BLACKOFFSETH 0x70
#define VV6410_BLACKOFFSETL 0x71
/* Black offset cancellation setup */
#define VV6410_BLACKOFFSETSETUP 0x72
/* Analog Control Register 0 */
#define VV6410_CR0 0x75
/* Analog Control Register 1 */
#define VV6410_CR1 0x76
/* ADC Setup Register */
#define VV6410_AS0 0x77
/* Analog Test Register */
#define VV6410_AT0 0x78
/* Audio Amplifier Setup Register */
#define VV6410_AT1 0x79
#define VV6410_HFLIP (1 << 3)
#define VV6410_VFLIP (1 << 4)
#define VV6410_LOW_POWER_MODE (1 << 0)
#define VV6410_SOFT_RESET (1 << 2)
#define VV6410_PAL_25_FPS (0 << 3)
#define VV6410_CLK_DIV_2 (1 << 1)
#define VV6410_FINE_EXPOSURE 320
#define VV6410_COARSE_EXPOSURE 192
#define VV6410_DEFAULT_GAIN 5
#define VV6410_SUBSAMPLE 0x01
#define VV6410_CROP_TO_QVGA 0x02
static int vv6410_probe(struct sd *sd);
static int vv6410_start(struct sd *sd);
static int vv6410_init(struct sd *sd);
static int vv6410_stop(struct sd *sd);
static int vv6410_dump(struct sd *sd);
/* V4L2 controls supported by the driver */
static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val);
static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
.name = "ST VV6410",
.i2c_flush = 5,
.i2c_addr = 0x20,
.i2c_len = 1,
.init = vv6410_init,
.probe = vv6410_probe,
.start = vv6410_start,
.stop = vv6410_stop,
.dump = vv6410_dump,
.nctrls = 3,
.ctrls = {
{
{
.id = V4L2_CID_HFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "horizontal flip",
.minimum = 0,
.maximum = 1,
.step = 1,
.default_value = 0
},
.set = vv6410_set_hflip,
.get = vv6410_get_hflip
}, {
{
.id = V4L2_CID_VFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "vertical flip",
.minimum = 0,
.maximum = 1,
.step = 1,
.default_value = 0
},
.set = vv6410_set_vflip,
.get = vv6410_get_vflip
}, {
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "analog gain",
.minimum = 0,
.maximum = 15,
.step = 1,
.default_value = 0
},
.set = vv6410_set_analog_gain,
.get = vv6410_get_analog_gain
}
},
.nmodes = 1,
.modes = {
{
356,
292,
V4L2_PIX_FMT_SGRBG8,
V4L2_FIELD_NONE,
.sizeimage =
356 * 292,
.bytesperline = 356,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0
}
}
};
/* If NULL, only single value to write, stored in len */
struct stv_init {
const u8 *data;
u16 start;
u8 len;
};
static const u8 x1500[] = { /* 0x1500 - 0x150f */
0x0b, 0xa7, 0xb7, 0x00, 0x00
};
static const u8 x1536[] = { /* 0x1536 - 0x153b */
0x02, 0x00, 0x60, 0x01, 0x20, 0x01
};
static const u8 x15c1[] = { /* 0x15c1 - 0x15c2 */
0xff, 0x03 /* Output word 0x03ff = 1023 (ISO size) */
};
static const struct stv_init stv_bridge_init[] = {
/* This reg is written twice. Some kind of reset? */
{NULL, 0x1620, 0x80},
{NULL, 0x1620, 0x00},
{NULL, 0x1423, 0x04},
{x1500, 0x1500, ARRAY_SIZE(x1500)},
{x1536, 0x1536, ARRAY_SIZE(x1536)},
{x15c1, 0x15c1, ARRAY_SIZE(x15c1)}
};
static const u8 vv6410_sensor_init[][2] = {
/* Setup registers */
{VV6410_SETUP0, VV6410_SOFT_RESET},
{VV6410_SETUP0, VV6410_LOW_POWER_MODE},
/* Use shuffled read-out mode */
{VV6410_SETUP1, BIT(6)},
/* All modes to 1 */
{VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
{VV6410_PINMAPPING, 0x00},
/* Pre-clock generator divide off */
{VV6410_DATAFORMAT, BIT(7) | BIT(0)},
/* Exposure registers */
{VV6410_FINEH, VV6410_FINE_EXPOSURE >> 8},
{VV6410_FINEL, VV6410_FINE_EXPOSURE & 0xff},
{VV6410_COARSEH, VV6410_COARSE_EXPOSURE >> 8},
{VV6410_COARSEL, VV6410_COARSE_EXPOSURE & 0xff},
{VV6410_ANALOGGAIN, 0xf0 | VV6410_DEFAULT_GAIN},
{VV6410_CLKDIV, VV6410_CLK_DIV_2},
/* System registers */
/* Enable voltage doubler */
{VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
{VV6410_AT0, 0x00},
/* Power up audio, differential */
{VV6410_AT1, BIT(4)|BIT(0)},
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment