tv8532.c

来自「trident tm5600的linux驱动」· C语言 代码 · 共 670 行 · 第 1/2 页

C
670
字号
/* * Quickcam cameras initialization data * * 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 "tv8532"#include "gspca.h"MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");MODULE_DESCRIPTION("TV8532 USB Camera Driver");MODULE_LICENSE("GPL");/* specific webcam descriptor */struct sd {	struct gspca_dev gspca_dev;	/* !! must be the first item */	int buflen;			/* current length of tmpbuf */	__u8 tmpbuf[352 * 288 + 10 * 288];	/* no protection... */	__u8 tmpbuf2[352 * 288];		/* no protection... */	unsigned short brightness;	unsigned short contrast;	char packet;	char synchro;};/* 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 struct ctrl sd_ctrls[] = {#define SD_BRIGHTNESS 0	{	 {	  .id = V4L2_CID_BRIGHTNESS,	  .type = V4L2_CTRL_TYPE_INTEGER,	  .name = "Brightness",	  .minimum = 1,	  .maximum = 0x2ff,	  .step = 1,	  .default_value = 0x18f,	  },	 .set = sd_setbrightness,	 .get = sd_getbrightness,	 },#define SD_CONTRAST 1	{	 {	  .id = V4L2_CID_CONTRAST,	  .type = V4L2_CTRL_TYPE_INTEGER,	  .name = "Contrast",	  .minimum = 0,	  .maximum = 0xffff,	  .step = 1,	  .default_value = 0x7fff,	  },	 .set = sd_setcontrast,	 .get = sd_getcontrast,	 },};static struct v4l2_pix_format sif_mode[] = {	{176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,		.bytesperline = 176,		.sizeimage = 176 * 144,		.colorspace = V4L2_COLORSPACE_SRGB,		.priv = 1},	{352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,		.bytesperline = 352,		.sizeimage = 352 * 288,		.colorspace = V4L2_COLORSPACE_SRGB,		.priv = 0},};/* * Initialization data: this is the first set-up data written to the * device (before the open data). */#define TESTCLK 0x10		/* reg 0x2c -> 0x12 //10 */#define TESTCOMP 0x90		/* reg 0x28 -> 0x80 */#define TESTLINE 0x81		/* reg 0x29 -> 0x81 */#define QCIFLINE 0x41		/* reg 0x29 -> 0x81 */#define TESTPTL 0x14		/* reg 0x2D -> 0x14 */#define TESTPTH 0x01		/* reg 0x2E -> 0x01 */#define TESTPTBL 0x12		/* reg 0x2F -> 0x0a */#define TESTPTBH 0x01		/* reg 0x30 -> 0x01 */#define ADWIDTHL 0xe8		/* reg 0x0c -> 0xe8 */#define ADWIDTHH 0x03		/* reg 0x0d -> 0x03 */#define ADHEIGHL 0x90		/* reg 0x0e -> 0x91 //93 */#define ADHEIGHH 0x01		/* reg 0x0f -> 0x01 */#define EXPOL 0x8f		/* reg 0x1c -> 0x8f */#define EXPOH 0x01		/* reg 0x1d -> 0x01 */#define ADCBEGINL 0x44		/* reg 0x10 -> 0x46 //47 */#define ADCBEGINH 0x00		/* reg 0x11 -> 0x00 */#define ADRBEGINL 0x0a		/* reg 0x14 -> 0x0b //0x0c */#define ADRBEGINH 0x00		/* reg 0x15 -> 0x00 */#define TV8532_CMD_UPDATE 0x84#define TV8532_EEprom_Add 0x03#define TV8532_EEprom_DataL 0x04#define TV8532_EEprom_DataM 0x05#define TV8532_EEprom_DataH 0x06#define TV8532_EEprom_TableLength 0x07#define TV8532_EEprom_Write 0x08#define TV8532_PART_CTRL 0x00#define TV8532_CTRL 0x01#define TV8532_CMD_EEprom_Open 0x30#define TV8532_CMD_EEprom_Close 0x29#define TV8532_UDP_UPDATE 0x31#define TV8532_GPIO 0x39#define TV8532_GPIO_OE 0x3B#define TV8532_REQ_RegWrite 0x02#define TV8532_REQ_RegRead 0x03#define TV8532_ADWIDTH_L 0x0C#define TV8532_ADWIDTH_H 0x0D#define TV8532_ADHEIGHT_L 0x0E#define TV8532_ADHEIGHT_H 0x0F#define TV8532_EXPOSURE 0x1C#define TV8532_QUANT_COMP 0x28#define TV8532_MODE_PACKET 0x29#define TV8532_SETCLK 0x2C#define TV8532_POINT_L 0x2D#define TV8532_POINT_H 0x2E#define TV8532_POINTB_L 0x2F#define TV8532_POINTB_H 0x30#define TV8532_BUDGET_L 0x2A#define TV8532_BUDGET_H 0x2B#define TV8532_VID_L 0x34#define TV8532_VID_H 0x35#define TV8532_PID_L 0x36#define TV8532_PID_H 0x37#define TV8532_DeviceID 0x83#define TV8532_AD_SLOPE 0x91#define TV8532_AD_BITCTRL 0x94#define TV8532_AD_COLBEGIN_L 0x10#define TV8532_AD_COLBEGIN_H 0x11#define TV8532_AD_ROWBEGIN_L 0x14#define TV8532_AD_ROWBEGIN_H 0x15static const __u32 tv_8532_eeprom_data[] = {/*	add		dataL	   dataM	dataH */	0x00010001, 0x01018011, 0x02050014, 0x0305001c,	0x040d001e, 0x0505001f, 0x06050519, 0x0705011b,	0x0805091e, 0x090d892e, 0x0a05892f, 0x0b050dd9,	0x0c0509f1, 0};static int reg_r(struct gspca_dev *gspca_dev,		 __u16 index){	usb_control_msg(gspca_dev->dev,			usb_rcvctrlpipe(gspca_dev->dev, 0),			TV8532_REQ_RegRead,			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,			0,	/* value */			index, gspca_dev->usb_buf, 1,			500);	return gspca_dev->usb_buf[0];}/* write 1 byte */static void reg_w_1(struct gspca_dev *gspca_dev,		  __u16 index, __u8 value){	gspca_dev->usb_buf[0] = value;	usb_control_msg(gspca_dev->dev,			usb_sndctrlpipe(gspca_dev->dev, 0),			TV8532_REQ_RegWrite,			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,			0,	/* value */			index, gspca_dev->usb_buf, 1, 500);}/* write 2 bytes */static void reg_w_2(struct gspca_dev *gspca_dev,		  __u16 index, __u8 val1, __u8 val2){	gspca_dev->usb_buf[0] = val1;	gspca_dev->usb_buf[1] = val2;	usb_control_msg(gspca_dev->dev,			usb_sndctrlpipe(gspca_dev->dev, 0),			TV8532_REQ_RegWrite,			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,			0,	/* value */			index, gspca_dev->usb_buf, 2, 500);}static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev){	int i = 0;	__u8 reg, data0, data1, data2;	reg_w_1(gspca_dev, TV8532_GPIO, 0xb0);	reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Open);/*	msleep(1); */	while (tv_8532_eeprom_data[i]) {		reg = (tv_8532_eeprom_data[i] & 0xff000000) >> 24;		reg_w_1(gspca_dev, TV8532_EEprom_Add, reg);		/* msleep(1); */		data0 = (tv_8532_eeprom_data[i] & 0x000000ff);		reg_w_1(gspca_dev, TV8532_EEprom_DataL, data0);		/* msleep(1); */		data1 = (tv_8532_eeprom_data[i] & 0x0000ff00) >> 8;		reg_w_1(gspca_dev, TV8532_EEprom_DataM, data1);		/* msleep(1); */		data2 = (tv_8532_eeprom_data[i] & 0x00ff0000) >> 16;		reg_w_1(gspca_dev, TV8532_EEprom_DataH, data2);		/* msleep(1); */		reg_w_1(gspca_dev, TV8532_EEprom_Write, 0);		/* msleep(10); */		i++;	}	reg_w_1(gspca_dev, TV8532_EEprom_TableLength, i);/*	msleep(1); */	reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Close);	msleep(10);}/* 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;	tv_8532WriteEEprom(gspca_dev);	cam = &gspca_dev->cam;	cam->epaddr = 1;	cam->cam_mode = sif_mode;	cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];	sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;	sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;	return 0;}static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev){	__u8 data;	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);	reg_r(gspca_dev, TV8532_ADWIDTH_L);	reg_r(gspca_dev, TV8532_ADWIDTH_H);	reg_r(gspca_dev, TV8532_QUANT_COMP);	reg_r(gspca_dev, TV8532_MODE_PACKET);	reg_r(gspca_dev, TV8532_SETCLK);	reg_r(gspca_dev, TV8532_POINT_L);	reg_r(gspca_dev, TV8532_POINT_H);	reg_r(gspca_dev, TV8532_POINTB_L);	reg_r(gspca_dev, TV8532_POINTB_H);	reg_r(gspca_dev, TV8532_BUDGET_L);	reg_r(gspca_dev, TV8532_BUDGET_H);	reg_r(gspca_dev, TV8532_VID_L);	reg_r(gspca_dev, TV8532_VID_H);	reg_r(gspca_dev, TV8532_PID_L);	reg_r(gspca_dev, TV8532_PID_H);	reg_r(gspca_dev, TV8532_DeviceID);	reg_r(gspca_dev, TV8532_AD_COLBEGIN_L);	reg_r(gspca_dev, TV8532_AD_COLBEGIN_H);	reg_r(gspca_dev, TV8532_AD_ROWBEGIN_L);	reg_r(gspca_dev, TV8532_AD_ROWBEGIN_H);}static void tv_8532_setReg(struct gspca_dev *gspca_dev){	reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L,			ADCBEGINL);			/* 0x10 */	reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H,			ADCBEGINH);			/* also digital gain */	reg_w_1(gspca_dev, TV8532_PART_CTRL,			TV8532_CMD_UPDATE);		/* 0x00<-0x84 */	reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0a);	/******************************************************/	reg_w_1(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL); /* 0e */	reg_w_1(gspca_dev, TV8532_ADHEIGHT_H, ADHEIGHH); /* 0f */	reg_w_2(gspca_dev, TV8532_EXPOSURE,			EXPOL, EXPOH);			/* 350d 0x014c; 1c */	reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L,			ADCBEGINL);			/* 0x10 */	reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H,			ADCBEGINH);			/* also digital gain */	reg_w_1(gspca_dev, TV8532_AD_ROWBEGIN_L,			ADRBEGINL);			/* 0x14 */	reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00);	/* 0x91 */	reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x02);	/* 0x94 */	reg_w_1(gspca_dev, TV8532_CTRL,			TV8532_CMD_EEprom_Close);	/* 0x01 */	reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00);	/* 0x91 */	reg_w_1(gspca_dev, TV8532_PART_CTRL,			TV8532_CMD_UPDATE);		/* 0x00<-0x84 */}static void tv_8532_PollReg(struct gspca_dev *gspca_dev){	int i;	/* strange polling from tgc */	for (i = 0; i < 10; i++) {		reg_w_1(gspca_dev, TV8532_SETCLK,			TESTCLK);		/* 0x48; //0x08; 0x2c */		reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE);		reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01);	/* 0x31 */	}}/* this function is called at probe and resume time */static int sd_init(struct gspca_dev *gspca_dev)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?