sonixb.c

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

C
1,309
字号
	/* Color Gain B Pixel 5 a */	{ 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },	/* Color Gain G1 Pixel 1 5 */	{ 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },	/* Color Gain G2 Pixel 1 0 5 */	{ 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },	/* Color Gain R Pixel 3 1 */	{ 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },	/* Color GainH  Pixel */	{ 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },	/* Global Gain */	{ 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },	/* Contrast */	{ 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },	/* H&V synchro polarity */	{ 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },	/* ?default */	{ 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },	/* DAC scale */	{ 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },	/* ?default */	{ 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },	/* Validate Settings */	{ 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },};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,	0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c};static const __u8 pas202_sensor_init[][8] = {	{0xa0, 0x40, 0x02, 0x03, 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, 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[] = {	0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,	0x00, 0x00,	0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,	0x16, 0x12, 0x60, 0x86, 0x2b,	0x14, 0x0a, 0x02, 0x02, 0x09, 0x07};static const __u8 tas5110_sensor_init[][8] = {	{0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},	{0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},	{0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},};static const __u8 initTas5130[] = {	0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,	0x00, 0x00,	0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,	0x28, 0x1e, 0x60, COMP, MCK_INIT,	0x18, 0x10, 0x04, 0x03, 0x11, 0x0c};static const __u8 tas5130_sensor_init[][8] = {/* 	{0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},					* shutter 0x47 short exposure? */	{0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},					/* shutter 0x01 long exposure */	{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},};static struct sensor_data sensor_data[] = {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,	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(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,	0),};/* get one byte in gspca_dev->usb_buf */static void reg_r(struct gspca_dev *gspca_dev,		  __u16 value){	usb_control_msg(gspca_dev->dev,			usb_rcvctrlpipe(gspca_dev->dev, 0),			0,			/* request */			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,			value,			0,			/* index */			gspca_dev->usb_buf, 1,			500);}static void reg_w(struct gspca_dev *gspca_dev,		  __u16 value,		  const __u8 *buffer,		  int len){#ifdef GSPCA_DEBUG	if (len > USB_BUF_SZ) {		PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");		return;	}#endif	memcpy(gspca_dev->usb_buf, buffer, len);	usb_control_msg(gspca_dev->dev,			usb_sndctrlpipe(gspca_dev->dev, 0),			0x08,			/* request */			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,			value,			0,			/* index */			gspca_dev->usb_buf, len,			500);}static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer){	int retry = 60;	/* is i2c ready */	reg_w(gspca_dev, 0x08, buffer, 8);	while (retry--) {		msleep(10);		reg_r(gspca_dev, 0x08);		if (gspca_dev->usb_buf[0] & 0x04) {			if (gspca_dev->usb_buf[0] & 0x08)				return -1;			return 0;		}	}	return -1;}static void i2c_w_vector(struct gspca_dev *gspca_dev,			const __u8 buffer[][8], int len){	for (;;) {		reg_w(gspca_dev, 0x08, *buffer, 8);		len -= 8;		if (len <= 0)			break;		buffer++;	}}static void setbrightness(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	__u8 value;	switch (sd->sensor) {	case  SENSOR_OV6650:	case  SENSOR_OV7630: {		__u8 i2cOV[] =			{0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};		/* change reg 0x06 */		i2cOV[1] = sensor_data[sd->sensor].sensor_addr;		i2cOV[3] = sd->brightness;		if (i2c_w(gspca_dev, i2cOV) < 0)			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_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)			goto err;		if (i2c_w(gspca_dev, i2cpdoit) < 0)			goto err;		break;	    }	case SENSOR_TAS5130CXX: {		__u8 i2c[] =			{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};		value = 0xff - sd->brightness;		i2c[4] = value;		PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);		if (i2c_w(gspca_dev, i2c) < 0)			goto err;		break;	    }	}	return;err:	PDEBUG(D_ERR, "i2c error brightness");}static void setsensorgain(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	unsigned char gain = sd->gain;	switch (sd->sensor) {	case SENSOR_TAS5110: {		__u8 i2c[] =			{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};		i2c[4] = 255 - gain;		if (i2c_w(gspca_dev, i2c) < 0)			goto err;		break;	    }	case SENSOR_OV6650:		gain >>= 1;		/* fall thru */	case SENSOR_OV7630: {		__u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};		i2c[1] = sensor_data[sd->sensor].sensor_addr;		i2c[3] = gain >> 2;		if (i2c_w(gspca_dev, i2c) < 0)			goto err;		break;	    }	}	return;err:	PDEBUG(D_ERR, "i2c error gain");}static void setgain(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	__u8 gain;	__u8 rgb_value;	gain = sd->gain >> 4;	/* red and blue gain */	rgb_value = gain << 4 | gain;	reg_w(gspca_dev, 0x10, &rgb_value, 1);	/* green gain */	rgb_value = gain;	reg_w(gspca_dev, 0x11, &rgb_value, 1);	if (sensor_data[sd->sensor].flags & F_GAIN)		setsensorgain(gspca_dev);}static void setexposure(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	switch (sd->sensor) {	case SENSOR_TAS5110: {		__u8 reg;		/* 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;		reg = (reg << 4) | 0x0b;		reg_w(gspca_dev, 0x19, &reg, 1);		break;	    }	case SENSOR_OV6650:	case SENSOR_OV7630: {		/* The ov6650 / ov7630 have 2 registers which both influence		   exposure, register 11, whose low nibble sets the nr off fps		   according to: fps = 30 / (low_nibble + 1)		   The fps configures the maximum exposure setting, but it is		   possible to use less exposure then what the fps maximum		   allows by setting register 10. register 10 configures the		   actual exposure as quotient of the full exposure, with 0		   being no exposure at all (not very usefull) and reg10_max		   being max exposure possible at that framerate.		   The code maps our 0 - 510 ms exposure ctrl to these 2		   registers, trying to keep fps as high as possible.		*/		__u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};		int reg10, reg11, reg10_max;		/* ov6645 datasheet says reg10_max is 9a, but that uses		   tline * 2 * reg10 as formula for calculating texpo, the		   ov6650 probably uses the same formula as the 7730 which uses		   tline * 4 * reg10, which explains why the reg10max we've		   found experimentally for the ov6650 is exactly half that of		   the ov6645. The ov7630 datasheet says the max is 0x41. */		if (sd->sensor == SENSOR_OV6650) {			reg10_max = 0x4d;			i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */		} else			reg10_max = 0x41;		reg11 = (60 * 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;		/* 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);		/* Don't allow this to get below 10 when using autogain, the		   steps become very large (relatively) when below 10 causing		   the image to oscilate from much too dark, to much too bright		   and back again. */		if (sd->autogain && reg10 < 10)			reg10 = 10;		else if (reg10 > reg10_max)			reg10 = reg10_max;		/* Write reg 10 and reg11 low nibble */		i2c[1] = sensor_data[sd->sensor].sensor_addr;		i2c[3] = reg10;		i2c[4] |= reg11 - 1;		/* If register 11 didn't change, don't change it */		if (sd->reg11 == reg11 )			i2c[0] = 0xa0;		if (i2c_w(gspca_dev, i2c) == 0)			sd->reg11 = reg11;		else			PDEBUG(D_ERR, "i2c error exposure");		break;	    }	}}static void setfreq(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	switch (sd->sensor) {	case SENSOR_OV6650:	case SENSOR_OV7630: {		/* Framerate adjust register for artificial light 50 hz flicker		   compensation, for the ov6650 this is identical to ov6630		   0x2b register, see ov6630 datasheet.		   0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */		__u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};		switch (sd->freq) {		default:/*		case 0:			 * no filter*//*		case 2:			 * 60 hz */			i2c[3] = 0;			break;		case 1:			/* 50 hz */			i2c[3] = (sd->sensor == SENSOR_OV6650)					? 0x4f : 0x8a;			break;		}		i2c[1] = sensor_data[sd->sensor].sensor_addr;		if (i2c_w(gspca_dev, i2c) < 0)			PDEBUG(D_ERR, "i2c error setfreq");		break;	    }	}}static void do_autogain(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	int avg_lum = atomic_read(&sd->avg_lum);	if (avg_lum == -1)		return;	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,			AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {		PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",			(int)sd->gain, (int)sd->exposure);		sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;	}

⌨️ 快捷键说明

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