spca561.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 1,264 行 · 第 1/3 页
C
1,264 行
/* * Sunplus spca561 subdriver * * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr * * V4L2 by 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 "spca561"#include "gspca.h"MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");MODULE_LICENSE("GPL");/* specific webcam descriptor */struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ __u16 contrast; /* rev72a only */#define CONTRAST_MIN 0x0000#define CONTRAST_DEF 0x2000#define CONTRAST_MAX 0x3fff __u16 exposure; /* rev12a only */#define EXPOSURE_MIN 1#define EXPOSURE_DEF 200#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */ __u8 brightness; /* rev72a only */#define BRIGHTNESS_MIN 0#define BRIGHTNESS_DEF 32#define BRIGHTNESS_MAX 63 __u8 white; /* rev12a only */#define WHITE_MIN 1#define WHITE_DEF 0x40#define WHITE_MAX 0x7f __u8 autogain;#define AUTOGAIN_MIN 0#define AUTOGAIN_DEF 1#define AUTOGAIN_MAX 1 __u8 gain; /* rev12a only */#define GAIN_MIN 0x0#define GAIN_DEF 0x24#define GAIN_MAX 0x24#define EXPO12A_DEF 3 __u8 expo12a; /* expo/gain? for rev 12a */ __u8 chip_revision;#define Rev012A 0#define Rev072A 1 signed char ag_cnt;#define AG_CNT_START 13};static struct v4l2_pix_format sif_012a_mode[] = { {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 3}, {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 2}, {320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 4 / 8, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, {352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE, .bytesperline = 352, .sizeimage = 352 * 288 * 4 / 8, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0},};static struct v4l2_pix_format sif_072a_mode[] = { {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 3}, {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 2}, {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 352, .sizeimage = 352 * 288, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0},};/* * Initialization data * I'm not very sure how to split initialization from open data * chunks. For now, we'll consider everything as initialization *//* Frame packet header offsets for the spca561 */#define SPCA561_OFFSET_SNAP 1#define SPCA561_OFFSET_TYPE 2#define SPCA561_OFFSET_COMPRESS 3#define SPCA561_OFFSET_FRAMSEQ 4#define SPCA561_OFFSET_GPIO 5#define SPCA561_OFFSET_USBBUFF 6#define SPCA561_OFFSET_WIN2GRAVE 7#define SPCA561_OFFSET_WIN2RAVE 8#define SPCA561_OFFSET_WIN2BAVE 9#define SPCA561_OFFSET_WIN2GBAVE 10#define SPCA561_OFFSET_WIN1GRAVE 11#define SPCA561_OFFSET_WIN1RAVE 12#define SPCA561_OFFSET_WIN1BAVE 13#define SPCA561_OFFSET_WIN1GBAVE 14#define SPCA561_OFFSET_FREQ 15#define SPCA561_OFFSET_VSYNC 16#define SPCA561_OFFSET_DATA 1#define SPCA561_INDEX_I2C_BASE 0x8800#define SPCA561_SNAPBIT 0x20#define SPCA561_SNAPCTRL 0x40static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value){ int ret; ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, NULL, 0, 500); PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value); if (ret < 0) PDEBUG(D_ERR, "reg write: error %d", ret);}static void write_vector(struct gspca_dev *gspca_dev, const __u16 data[][2]){ struct usb_device *dev = gspca_dev->dev; int i; i = 0; while (data[i][1] != 0) { reg_w_val(dev, data[i][1], data[i][0]); i++; }}/* read 'len' bytes to gspca_dev->usb_buf */static void reg_r(struct gspca_dev *gspca_dev, __u16 index, __u16 length){ usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), 0, /* request */ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, length, 500);}static void reg_w_buf(struct gspca_dev *gspca_dev, __u16 index, const __u8 *buffer, __u16 len){ memcpy(gspca_dev->usb_buf, buffer, len); usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, len, 500);}static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg){ int retry = 60; __u8 DataLow; __u8 DataHight; DataLow = valeur; DataHight = valeur >> 8; reg_w_val(gspca_dev->dev, 0x8801, reg); reg_w_val(gspca_dev->dev, 0x8805, DataLow); reg_w_val(gspca_dev->dev, 0x8800, DataHight); while (retry--) { reg_r(gspca_dev, 0x8803, 1); if (!gspca_dev->usb_buf[0]) break; }}static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode){ int retry = 60; __u8 value; __u8 vallsb; reg_w_val(gspca_dev->dev, 0x8804, 0x92); reg_w_val(gspca_dev->dev, 0x8801, reg); reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01)); do { reg_r(gspca_dev, 0x8803, 1); if (!gspca_dev->usb_buf[0]) break; } while (--retry); if (retry == 0) return -1; reg_r(gspca_dev, 0x8800, 1); value = gspca_dev->usb_buf[0]; reg_r(gspca_dev, 0x8805, 1); vallsb = gspca_dev->usb_buf[0]; return ((int) value << 8) | vallsb;}static const __u16 spca561_init_data[][2] = { {0x0000, 0x8114}, /* Software GPIO output data */ {0x0001, 0x8114}, /* Software GPIO output data */ {0x0000, 0x8112}, /* Some kind of reset */ {0x0003, 0x8701}, /* PCLK clock delay adjustment */ {0x0001, 0x8703}, /* HSYNC from cmos inverted */ {0x0011, 0x8118}, /* Enable and conf sensor */ {0x0001, 0x8118}, /* Conf sensor */ {0x0092, 0x8804}, /* I know nothing about these */ {0x0010, 0x8802}, /* 0x88xx registers, so I won't */ /***************/ {0x000d, 0x8805}, /* sensor default setting */ {0x0001, 0x8801}, /* 1 <- 0x0d */ {0x0000, 0x8800}, {0x0018, 0x8805}, {0x0002, 0x8801}, /* 2 <- 0x18 */ {0x0000, 0x8800}, {0x0065, 0x8805}, {0x0004, 0x8801}, /* 4 <- 0x01 0x65 */ {0x0001, 0x8800}, {0x0021, 0x8805}, {0x0005, 0x8801}, /* 5 <- 0x21 */ {0x0000, 0x8800}, {0x00aa, 0x8805}, {0x0007, 0x8801}, /* 7 <- 0xaa */ {0x0000, 0x8800}, {0x0004, 0x8805}, {0x0020, 0x8801}, /* 0x20 <- 0x15 0x04 */ {0x0015, 0x8800}, {0x0002, 0x8805}, {0x0039, 0x8801}, /* 0x39 <- 0x02 */ {0x0000, 0x8800}, {0x0010, 0x8805}, {0x0035, 0x8801}, /* 0x35 <- 0x10 */ {0x0000, 0x8800}, {0x0049, 0x8805}, {0x0009, 0x8801}, /* 0x09 <- 0x10 0x49 */ {0x0010, 0x8800}, {0x000b, 0x8805}, {0x0028, 0x8801}, /* 0x28 <- 0x0b */ {0x0000, 0x8800}, {0x000f, 0x8805}, {0x003b, 0x8801}, /* 0x3b <- 0x0f */ {0x0000, 0x8800}, {0x0000, 0x8805}, {0x003c, 0x8801}, /* 0x3c <- 0x00 */ {0x0000, 0x8800}, /***************/ {0x0018, 0x8601}, /* Pixel/line selection for color separation */ {0x0000, 0x8602}, /* Optical black level for user setting */ {0x0060, 0x8604}, /* Optical black horizontal offset */ {0x0002, 0x8605}, /* Optical black vertical offset */ {0x0000, 0x8603}, /* Non-automatic optical black level */ {0x0002, 0x865b}, /* Horizontal offset for valid pixels */ {0x0000, 0x865f}, /* Vertical valid pixels window (x2) */ {0x00b0, 0x865d}, /* Horizontal valid pixels window (x2) */ {0x0090, 0x865e}, /* Vertical valid lines window (x2) */ {0x00e0, 0x8406}, /* Memory buffer threshold */ {0x0000, 0x8660}, /* Compensation memory stuff */ {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 */ {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 */ {0x0004, 0x8611}, /* R offset for white balance */ {0x0004, 0x8612}, /* Gr offset for white balance */ {0x0007, 0x8613}, /* B offset for white balance */ {0x0000, 0x8614}, /* Gb offset for white balance */ {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 */ {0x0002, 0x8502}, /* Maximum average bit rate stuff */ {0x0011, 0x8802}, {0x0087, 0x8700}, /* Set master clock (96Mhz????) */ {0x0081, 0x8702}, /* Master clock output enable */ {0x0000, 0x8500}, /* Set image type (352x288 no compression) */ /* Originally was 0x0010 (352x288 compression) */ {0x0002, 0x865b}, /* Horizontal offset for valid pixels */ {0x0003, 0x865c}, /* Vertical offset for valid lines */ /***************//* sensor active */ {0x0003, 0x8801}, /* 0x03 <- 0x01 0x21 //289 */ {0x0021, 0x8805}, {0x0001, 0x8800}, {0x0004, 0x8801}, /* 0x04 <- 0x01 0x65 //357 */ {0x0065, 0x8805}, {0x0001, 0x8800}, {0x0005, 0x8801}, /* 0x05 <- 0x2f */ {0x002f, 0x8805}, {0x0000, 0x8800}, {0x0006, 0x8801}, /* 0x06 <- 0 */ {0x0000, 0x8805}, {0x0000, 0x8800}, {0x000a, 0x8801}, /* 0x0a <- 2 */ {0x0002, 0x8805}, {0x0000, 0x8800}, {0x0009, 0x8801}, /* 0x09 <- 0x1061 */ {0x0061, 0x8805}, {0x0010, 0x8800}, {0x0035, 0x8801}, /* 0x35 <-0x14 */ {0x0014, 0x8805}, {0x0000, 0x8800}, {0x0030, 0x8112}, /* ISO and drop packet enable */ {0x0000, 0x8112}, /* Some kind of reset ???? */ {0x0009, 0x8118}, /* Enable sensor and set standby */ {0x0000, 0x8114}, /* Software GPIO output data */ {0x0000, 0x8114}, /* Software GPIO output data */ {0x0001, 0x8114}, /* Software GPIO output data */ {0x0000, 0x8112}, /* Some kind of reset ??? */ {0x0003, 0x8701}, {0x0001, 0x8703}, {0x0011, 0x8118}, {0x0001, 0x8118}, /***************/ {0x0092, 0x8804}, {0x0010, 0x8802}, {0x000d, 0x8805}, {0x0001, 0x8801}, {0x0000, 0x8800}, {0x0018, 0x8805}, {0x0002, 0x8801}, {0x0000, 0x8800}, {0x0065, 0x8805}, {0x0004, 0x8801}, {0x0001, 0x8800}, {0x0021, 0x8805}, {0x0005, 0x8801}, {0x0000, 0x8800}, {0x00aa, 0x8805}, {0x0007, 0x8801}, /* mode 0xaa */ {0x0000, 0x8800}, {0x0004, 0x8805}, {0x0020, 0x8801}, {0x0015, 0x8800}, /* mode 0x0415 */ {0x0002, 0x8805}, {0x0039, 0x8801}, {0x0000, 0x8800}, {0x0010, 0x8805}, {0x0035, 0x8801}, {0x0000, 0x8800}, {0x0049, 0x8805}, {0x0009, 0x8801}, {0x0010, 0x8800}, {0x000b, 0x8805}, {0x0028, 0x8801}, {0x0000, 0x8800}, {0x000f, 0x8805}, {0x003b, 0x8801}, {0x0000, 0x8800}, {0x0000, 0x8805}, {0x003c, 0x8801}, {0x0000, 0x8800}, {0x0002, 0x8502}, {0x0039, 0x8801}, {0x0000, 0x8805}, {0x0000, 0x8800}, {0x0087, 0x8700}, /* overwrite by start */ {0x0081, 0x8702}, {0x0000, 0x8500},/* {0x0010, 0x8500}, -- Previous line was this */ {0x0002, 0x865b}, {0x0003, 0x865c}, /***************/ {0x0003, 0x8801}, /* 0x121-> 289 */ {0x0021, 0x8805}, {0x0001, 0x8800}, {0x0004, 0x8801}, /* 0x165 -> 357 */ {0x0065, 0x8805}, {0x0001, 0x8800}, {0x0005, 0x8801}, /* 0x2f //blanking control colonne */ {0x002f, 0x8805}, {0x0000, 0x8800}, {0x0006, 0x8801}, /* 0x00 //blanking mode row */ {0x0000, 0x8805}, {0x0000, 0x8800},
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?