ov519.c

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

C
2,231
字号
	 * output mode */	/* OV7640 is 8-bit only */	if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640)		i2c_w_mask(sd, 0x13, 0x00, 0x20);	/******** Clock programming ********/	/* The OV6620 needs special handling. This prevents the	 * severe banding that normally occurs */	if (sd->sensor == SEN_OV6620) {		/* Clock down */		i2c_w(sd, 0x2a, 0x04);		i2c_w(sd, 0x11, sd->clockdiv);		i2c_w(sd, 0x2a, 0x84);		/* This next setting is critical. It seems to improve		 * the gain or the contrast. The "reserved" bits seem		 * to have some effect in this case. */		i2c_w(sd, 0x2d, 0x85);	} else if (sd->clockdiv >= 0) {		i2c_w(sd, 0x11, sd->clockdiv);	}	/******** Special Features ********//* no evidence this is possible with OV7670, either */	/* Test Pattern */	if (sd->sensor != SEN_OV7640 && sd->sensor != SEN_OV7670)		i2c_w_mask(sd, 0x12, 0x00, 0x02);	/* Enable auto white balance */	if (sd->sensor == SEN_OV7670)		i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB,				OV7670_COM8_AWB);	else		i2c_w_mask(sd, 0x12, 0x04, 0x04);	/* This will go away as soon as ov51x_mode_init_sensor_regs() */	/* is fully tested. */	/* 7620/6620/6630? don't have register 0x35, so play it safe */	if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {		if (!qvga)			i2c_w(sd, 0x35, 0x9e);		else			i2c_w(sd, 0x35, 0x1e);	}	return 0;}static void sethvflip(struct sd *sd){	if (sd->sensor != SEN_OV7670)		return;	if (sd->gspca_dev.streaming)		ov51x_stop(sd);	i2c_w_mask(sd, OV7670_REG_MVFP,		OV7670_MVFP_MIRROR * sd->hflip			| OV7670_MVFP_VFLIP * sd->vflip,		OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);	if (sd->gspca_dev.streaming)		ov51x_restart(sd);}static int set_ov_sensor_window(struct sd *sd){	struct gspca_dev *gspca_dev;	int qvga;	int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;	int ret, hstart, hstop, vstop, vstart;	__u8 v;	gspca_dev = &sd->gspca_dev;	qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;	/* The different sensor ICs handle setting up of window differently.	 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */	switch (sd->sensor) {	case SEN_OV8610:		hwsbase = 0x1e;		hwebase = 0x1e;		vwsbase = 0x02;		vwebase = 0x02;		break;	case SEN_OV7610:	case SEN_OV76BE:		hwsbase = 0x38;		hwebase = 0x3a;		vwsbase = vwebase = 0x05;		break;	case SEN_OV6620:	case SEN_OV6630:		hwsbase = 0x38;		hwebase = 0x3a;		vwsbase = 0x05;		vwebase = 0x06;		break;	case SEN_OV7620:		hwsbase = 0x2f;		/* From 7620.SET (spec is wrong) */		hwebase = 0x2f;		vwsbase = vwebase = 0x05;		break;	case SEN_OV7640:		hwsbase = 0x1a;		hwebase = 0x1a;		vwsbase = vwebase = 0x03;		break;	case SEN_OV7670:		/*handling of OV7670 hardware sensor start and stop values		 * is very odd, compared to the other OV sensors */		vwsbase = vwebase = hwebase = hwsbase = 0x00;		break;	default:		return -EINVAL;	}	switch (sd->sensor) {	case SEN_OV6620:	case SEN_OV6630:		if (qvga) {		/* QCIF */			hwscale = 0;			vwscale = 0;		} else {		/* CIF */			hwscale = 1;			vwscale = 1;	/* The datasheet says 0;					 * it's wrong */		}		break;	case SEN_OV8610:		if (qvga) {		/* QSVGA */			hwscale = 1;			vwscale = 1;		} else {		/* SVGA */			hwscale = 2;			vwscale = 2;		}		break;	default:			/* SEN_OV7xx0 */		if (qvga) {		/* QVGA */			hwscale = 1;			vwscale = 0;		} else {		/* VGA */			hwscale = 2;			vwscale = 1;		}	}	ret = mode_init_ov_sensor_regs(sd);	if (ret < 0)		return ret;	if (sd->sensor == SEN_OV8610) {		i2c_w_mask(sd, 0x2d, 0x05, 0x40);				/* old 0x95, new 0x05 from windrv 090403 */						/* bits 5-7: reserved */		i2c_w_mask(sd, 0x28, 0x20, 0x20);					/* bit 5: progressive mode on */	}	/* The below is wrong for OV7670s because their window registers	 * only store the high bits in 0x17 to 0x1a */	/* SRH Use sd->max values instead of requested win values */	/* SCS Since we're sticking with only the max hardware widths	 * for a given mode */	/* I can hard code this for OV7670s */	/* Yes, these numbers do look odd, but they're tested and work! */	if (sd->sensor == SEN_OV7670) {		if (qvga) {		/* QVGA from ov7670.c by					 * Jonathan Corbet */			hstart = 164;			hstop = 20;			vstart = 14;			vstop = 494;		} else {		/* VGA */			hstart = 158;			hstop = 14;			vstart = 10;			vstop = 490;		}		/* OV7670 hardware window registers are split across		 * multiple locations */		i2c_w(sd, OV7670_REG_HSTART, hstart >> 3);		i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3);		v = i2c_r(sd, OV7670_REG_HREF);		v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07);		msleep(10);	/* need to sleep between read and write to				 * same reg! */		i2c_w(sd, OV7670_REG_HREF, v);		i2c_w(sd, OV7670_REG_VSTART, vstart >> 2);		i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2);		v = i2c_r(sd, OV7670_REG_VREF);		v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03);		msleep(10);	/* need to sleep between read and write to				 * same reg! */		i2c_w(sd, OV7670_REG_VREF, v);		sethvflip(sd);	} else {		i2c_w(sd, 0x17, hwsbase);		i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale));		i2c_w(sd, 0x19, vwsbase);		i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale));	}	return 0;}/* -- start the camera -- */static int sd_start(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	int ret;	ret = ov519_mode_init_regs(sd);	if (ret < 0)		goto out;	ret = set_ov_sensor_window(sd);	if (ret < 0)		goto out;	ret = ov51x_restart(sd);	if (ret < 0)		goto out;	PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);	ov51x_led_control(sd, 1);	return 0;out:	PDEBUG(D_ERR, "camera start error:%d", ret);	return ret;}static void sd_stopN(struct gspca_dev *gspca_dev){	ov51x_stop((struct sd *) gspca_dev);	ov51x_led_control((struct sd *) gspca_dev, 0);}static void sd_pkt_scan(struct gspca_dev *gspca_dev,			struct gspca_frame *frame,	/* target */			__u8 *data,			/* isoc packet */			int len)			/* iso packet length */{	/* Header of ov519 is 16 bytes:	 *     Byte     Value      Description	 *	0	0xff	magic	 *	1	0xff	magic	 *	2	0xff	magic	 *	3	0xXX	0x50 = SOF, 0x51 = EOF	 *	9	0xXX	0x01 initial frame without data,	 *			0x00 standard frame with image	 *	14	Lo	in EOF: length of image data / 8	 *	15	Hi	 */	if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {		switch (data[3]) {		case 0x50:		/* start of frame */#define HDRSZ 16			data += HDRSZ;			len -= HDRSZ;#undef HDRSZ			if (data[0] == 0xff || data[1] == 0xd8)				gspca_frame_add(gspca_dev, FIRST_PACKET, frame,						data, len);			else				gspca_dev->last_packet_type = DISCARD_PACKET;			return;		case 0x51:		/* end of frame */			if (data[9] != 0)				gspca_dev->last_packet_type = DISCARD_PACKET;			gspca_frame_add(gspca_dev, LAST_PACKET, frame,					data, 0);			return;		}	}	/* intermediate packet */	gspca_frame_add(gspca_dev, INTER_PACKET, frame,			data, len);}/* -- management routines -- */static void setbrightness(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	int val;	val = sd->brightness;	PDEBUG(D_CONF, "brightness:%d", val);/*	if (gspca_dev->streaming) *		ov51x_stop(sd); */	switch (sd->sensor) {	case SEN_OV8610:	case SEN_OV7610:	case SEN_OV76BE:	case SEN_OV6620:	case SEN_OV6630:	case SEN_OV7640:		i2c_w(sd, OV7610_REG_BRT, val);		break;	case SEN_OV7620:		/* 7620 doesn't like manual changes when in auto mode *//*fixme *		if (!sd->auto_brt) */			i2c_w(sd, OV7610_REG_BRT, val);		break;	case SEN_OV7670:/*win trace *		i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */		i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val));		break;	}/*	if (gspca_dev->streaming) *		ov51x_restart(sd); */}static void setcontrast(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	int val;	val = sd->contrast;	PDEBUG(D_CONF, "contrast:%d", val);/*	if (gspca_dev->streaming)		ov51x_stop(sd); */	switch (sd->sensor) {	case SEN_OV7610:	case SEN_OV6620:		i2c_w(sd, OV7610_REG_CNT, val);		break;	case SEN_OV6630:		i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);	case SEN_OV8610: {		static const __u8 ctab[] = {			0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f		};		/* Use Y gamma control instead. Bit 0 enables it. */		i2c_w(sd, 0x64, ctab[val >> 5]);		break;	    }	case SEN_OV7620: {		static const __u8 ctab[] = {			0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,			0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff		};		/* Use Y gamma control instead. Bit 0 enables it. */		i2c_w(sd, 0x64, ctab[val >> 4]);		break;	    }	case SEN_OV7640:		/* Use gain control instead. */		i2c_w(sd, OV7610_REG_GAIN, val >> 2);		break;	case SEN_OV7670:		/* check that this isn't just the same as ov7610 */		i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);		break;	}/*	if (gspca_dev->streaming)		ov51x_restart(sd); */}static void setcolors(struct gspca_dev *gspca_dev){	struct sd *sd = (struct sd *) gspca_dev;	int val;	val = sd->colors;	PDEBUG(D_CONF, "saturation:%d", val);/*	if (gspca_dev->streaming)		ov51x_stop(sd); */	switch (sd->sensor) {	case SEN_OV8610:	case SEN_OV7610:	case SEN_OV76BE:	case SEN_OV6620:	case SEN_OV6630:		i2c_w(sd, OV7610_REG_SAT, val);		break;	case SEN_OV7620:		/* Use UV gamma control instead. Bits 0 & 7 are reserved. *//*		rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);		if (rc < 0)			goto out; */		i2c_w(sd, OV7610_REG_SAT, val);		break;	case SEN_OV7640:		i2c_w(sd, OV7610_REG_SAT, val & 0xf0);		break;	case SEN_OV7670:		/* supported later once I work out how to do it		 * transparently fail now! */		/* set REG_COM13 values for UV sat auto mode */		break;	}/*	if (gspca_dev->streaming)		ov51x_restart(sd); */}static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val){	struct sd *sd = (struct sd *) gspca_dev;	sd->brightness = val;	setbrightness(gspca_dev);	return 0;}static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val){	struct sd *sd = (struct sd *) gspca_dev;	*val = sd->brightness;	return 0;}static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val){	struct sd *sd = (struct sd *) gspca_dev;	sd->contrast = val;	setcontrast(gspca_dev);	return 0;}static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val){	struct sd *sd = (struct sd *) gspca_dev;	*val = sd->contrast;	return 0;}static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val){	struct sd *sd = (struct sd *) gspca_dev;	sd->colors = val;	setcolors(gspca_dev);	return 0;}static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val){	struct sd *sd = (struct sd *) gspca_dev;	*val = sd->colors;	return 0;}static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val){	struct sd *sd = (struct sd *) gspca_dev;	sd->hflip = val;	sethvflip(sd);	return 0;}static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val){	struct sd *sd = (struct sd *) gspca_dev;	*val = sd->hflip;	return 0;}static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val){	struct sd *sd = (struct sd *) gspca_dev;	sd->vflip = val;	sethvflip(sd);	return 0;}static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val){	struct sd *sd = (struct sd *) gspca_dev;	*val = sd->vflip;	return 0;}/* sub-driver description */static const struct sd_desc sd_desc = {	.name = MODULE_NAME,	.ctrls = sd_ctrls,	.nctrls = ARRAY_SIZE(sd_ctrls),	.config = sd_config,	.init = sd_init,	.start = sd_start,	.stopN = sd_stopN,	.pkt_scan = sd_pkt_scan,};/* -- module initialisation -- */static const __devinitdata struct usb_device_id device_table[] = {	{USB_DEVICE(0x041e, 0x4052)},	{USB_DEVICE(0x041e, 0x405f)},	{USB_DEVICE(0x041e, 0x4060)},	{USB_DEVICE(0x041e, 0x4061)},	{USB_DEVICE(0x041e, 0x4064)},	{USB_DEVICE(0x041e, 0x4068)},	{USB_DEVICE(0x045e, 0x028c)},	{USB_DEVICE(0x054c, 0x0154)},	{USB_DEVICE(0x054c, 0x0155)},	{USB_DEVICE(0x05a9, 0x0519)},	{USB_DEVICE(0x05a9, 0x0530)},	{USB_DEVICE(0x05a9, 0x4519)},	{USB_DEVICE(0x05a9, 0x8519)},	{}};#undef DVNAMEMODULE_DEVICE_TABLE(usb, device_table);/* -- device connect -- */static int sd_probe(struct usb_interface *intf,			const struct usb_device_id *id){	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),				THIS_MODULE);}static struct usb_driver sd_driver = {	.name = MODULE_NAME,	.id_table = device_table,	.probe = sd_probe,	.disconnect = gspca_disconnect,#ifdef CONFIG_PM	.suspend = gspca_suspend,	.resume = gspca_resume,#endif};/* -- module insert / remove -- */static int __init sd_mod_init(void){	if (usb_register(&sd_driver) < 0)		return -1;	PDEBUG(D_PROBE, "registered");	return 0;}static void __exit sd_mod_exit(void){	usb_deregister(&sd_driver);	PDEBUG(D_PROBE, "deregistered");}module_init(sd_mod_init);module_exit(sd_mod_exit);module_param(frame_rate, int, 0644);MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");

⌨️ 快捷键说明

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