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 + -
显示快捷键?