⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ov511_core.c

📁 支持linux2.6和linux2.4的ov511摄像头驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
static intsensor_get_picture(struct usb_ov511 *ov, struct video_picture *p){	int rc, v;	PDEBUG(4, "sensor_get_picture");	if (ov->has_decoder) {		call_i2c_clients(ov, VIDIOCGPICT, p);		return 0;	}	/* Don't return error if a setting is unsupported, or rest of settings         * will not be performed */	rc = sensor_get_control(ov, OVCAMCHIP_CID_CONT, &v);	if (FATAL_ERROR(rc))		return rc;	p->contrast = v;	rc = sensor_get_control(ov, OVCAMCHIP_CID_BRIGHT, &v);	if (FATAL_ERROR(rc))		return rc;	p->brightness = v;	rc = sensor_get_control(ov, OVCAMCHIP_CID_SAT, &v);	if (FATAL_ERROR(rc))		return rc;	p->colour = v;	rc = sensor_get_control(ov, OVCAMCHIP_CID_HUE, &v);	if (FATAL_ERROR(rc))		return rc;	p->hue = v;	p->whiteness = 105 << 8;	return 0;}/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */static voidov51x_led_control(struct usb_ov511 *ov, int enable){	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");	if (ov->bridge == BRG_OV511PLUS)		reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0);	else if (ov->bclass == BCL_OV518)		reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02);	return;}/* Matches the sensor's internal frame rate to the lighting frequency. * Valid frequencies are: *	50 - 50Hz, for European and Asian lighting *	60 - 60Hz, for American lighting * * Returns: 0 for success */static intsensor_set_light_freq(struct usb_ov511 *ov, int freq){	if (freq != 50 && freq != 60) {		err("Invalid light freq (%d Hz)", freq);		return -EINVAL;	}	return sensor_set_control(ov, OVCAMCHIP_CID_FREQ, freq);}/* Returns number of bits per pixel (regardless of where they are located; * planar or not), or zero for unsupported format. */static inline intget_depth(int palette){	switch (palette) {	case VIDEO_PALETTE_GREY:    return 8;	case VIDEO_PALETTE_YUV420:  return 12;	case VIDEO_PALETTE_YUV420P: return 12; /* Planar */	default:		    return 0;  /* Invalid format */	}}/* Bytes per frame. Used by read(). Return of 0 indicates error */static inline long intget_frame_length(struct ov511_frame *frame){	if (!frame)		return 0;	else		return ((frame->width * frame->height			 * get_depth(frame->format)) >> 3);}static intset_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode,		     int sub_flag){	struct ovcamchip_window win;	int half_w = ov->maxwidth / 2;	int half_h = ov->maxheight / 2;	int rc;	win.format = mode;	/* Unless subcapture is enabled, center the image window and downsample	 * if possible to increase the field of view */	if (sub_flag) {		win.x = ov->subx;		win.y = ov->suby;		win.width = ov->subw;		win.height = ov->subh;		win.quarter = 0;	} else {		/* NOTE: OV518(+) does downsampling on its own */		if ((width > half_w && height > half_h)		    || ov->bclass == BCL_OV518) {			win.width = ov->maxwidth;			win.height = ov->maxheight;			win.quarter = 0;		} else if (width > half_w || height > half_h) {			err("Illegal dimensions");			return -EINVAL;		} else {			win.width = half_w;			win.height = half_h;			win.quarter = 1;		}		/* Center it */		win.x = (win.width - width) / 2;		win.y = (win.height - height) / 2;	}	if (ov->clockdiv >= 0) {		/* Manual override */		win.clockdiv = ov->clockdiv;	} else if (ov->bridge == BRG_OV518) {		/* OV518 controls the clock externally */		win.clockdiv = 0;	} else if (ov->bridge == BRG_OV518PLUS) {		/* OV518+ controls the clock externally */		win.clockdiv = 1;	} else if (ov->compress) {		/* Use the highest possible rate, to maximize FPS */		switch (ov->sensor) {		case CC_OV6620:			/* ...except with this sensor, which doesn't like			 * higher rates yet */			win.clockdiv = 3;			break;		case CC_OV6630:			win.clockdiv = 0;			break;		case CC_OV76BE:		case CC_OV7610:		case CC_OV7620:			win.clockdiv = 1;			break;		default:			err("Invalid sensor");			return -EINVAL;		}	} else {		switch (ov->sensor) {		case CC_OV6620:		case CC_OV6630:			win.clockdiv = 3;			break;		case CC_OV76BE:		case CC_OV7610:		case CC_OV7620:			/* Use slowest possible clock without sacrificing			 * frame rate */			win.clockdiv = ((sub_flag ? ov->subw * ov->subh			      : width * height)			     * (win.format == VIDEO_PALETTE_GREY ? 2 : 3) / 2)			    / 66000;			break;		default:			err("Invalid sensor");			return -EINVAL;		}	}	PDEBUG(4, "Setting clock divider to %d", win.clockdiv);	rc = sensor_cmd(ov, OVCAMCHIP_CMD_S_MODE, &win);	if (rc < 0)		return rc;	/* A setting of 0x06 reduces frame corruption with certain sensors, in	 * scenes with moving objects */	if (framedrop >= 0) {		i2c_w(ov, 0x16, framedrop);	} else if (ov->sensor == CC_OV6620 || ov->sensor == CC_OV76BE ||	         ov->sensor == CC_OV7610) {		i2c_w(ov, 0x16, 0x06);	}	return 0;}/* Set up the OV511/OV511+ with the given image parameters. * * Do not put any sensor-specific code in here (including I2C I/O functions) */static intov511_mode_init_regs(struct usb_ov511 *ov,		     int width, int height, int mode, int sub_flag){	int hsegs, vsegs;	if (sub_flag) {		width = ov->subw;		height = ov->subh;	}	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",	       width, height, mode, sub_flag);	// FIXME: This should be moved to a 7111a-specific function once	// subcapture is dealt with properly	if (ov->sensor == SEN_SAA7111A) {		if (width == 320 && height == 240) {			/* No need to do anything special */		} else if (width == 640 && height == 480) {			/* Set the OV511 up as 320x480, but keep the			 * V4L resolution as 640x480 */			width = 320;		} else {			err("SAA7111A only allows 320x240 or 640x480");			return -EINVAL;		}	}	/* Make sure width and height are a multiple of 8 */	if (width % 8 || height % 8) {		err("Invalid size (%d, %d) (mode = %d)", width, height, mode);		return -EINVAL;	}	if (width < ov->minwidth || height < ov->minheight) {		err("Requested dimensions are too small");		return -EINVAL;	}	if (ov51x_stop(ov) < 0)		return -EIO;	if (mode == VIDEO_PALETTE_GREY) {		reg_w(ov, R511_CAM_UV_EN, 0x00);		reg_w(ov, R511_SNAP_UV_EN, 0x00);		reg_w(ov, R511_SNAP_OPTS, 0x01);	} else {		reg_w(ov, R511_CAM_UV_EN, 0x01);		reg_w(ov, R511_SNAP_UV_EN, 0x01);		reg_w(ov, R511_SNAP_OPTS, 0x03);	}	/* Here I'm assuming that snapshot size == image size.	 * I hope that's always true. --claudio	 */	hsegs = (width >> 3) - 1;	vsegs = (height >> 3) - 1;	reg_w(ov, R511_CAM_PXCNT, hsegs);	reg_w(ov, R511_CAM_LNCNT, vsegs);	reg_w(ov, R511_CAM_PXDIV, 0x00);	reg_w(ov, R511_CAM_LNDIV, 0x00);	/* YUV420, low pass filter on */	reg_w(ov, R511_CAM_OPTS, 0x03);	/* Snapshot additions */	reg_w(ov, R511_SNAP_PXCNT, hsegs);	reg_w(ov, R511_SNAP_LNCNT, vsegs);	reg_w(ov, R511_SNAP_PXDIV, 0x00);	reg_w(ov, R511_SNAP_LNDIV, 0x00);	if (ov->compress) {		/* Enable Y and UV quantization and compression */		reg_w(ov, R511_COMP_EN, 0x07);		reg_w(ov, R511_COMP_LUT_EN, 0x03);		ov51x_reset(ov, OV511_RESET_OMNICE);	}	if (ov51x_restart(ov) < 0)		return -EIO;	return 0;}/* Sets up the OV518/OV518+ with the given image parameters * * OV518 needs a completely different approach, until we can figure out what * the individual registers do. Also, only 15 FPS is supported now. * * Do not put any sensor-specific code in here (including I2C I/O functions) */static intov518_mode_init_regs(struct usb_ov511 *ov,		     int width, int height, int mode, int sub_flag){	int hsegs, vsegs, hi_res;	if (sub_flag) {		width = ov->subw;		height = ov->subh;	}	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",	       width, height, mode, sub_flag);	if (width % 16 || height % 8) {		err("Invalid size (%d, %d)", width, height);		return -EINVAL;	}	if (width < ov->minwidth || height < ov->minheight) {		err("Requested dimensions are too small");		return -EINVAL;	}	if (width >= 320 && height >= 240) {		hi_res = 1;	} else if (width >= 320 || height >= 240) {		err("Invalid width/height combination (%d, %d)", width, height);		return -EINVAL;	} else {		hi_res = 0;	}	if (ov51x_stop(ov) < 0)		return -EIO;	/******** Set the mode ********/	reg_w(ov, 0x2b, 0);	reg_w(ov, 0x2c, 0);	reg_w(ov, 0x2d, 0);	reg_w(ov, 0x2e, 0);	reg_w(ov, 0x3b, 0);	reg_w(ov, 0x3c, 0);	reg_w(ov, 0x3d, 0);	reg_w(ov, 0x3e, 0);	if (ov->bridge == BRG_OV518 && ov518_color) {	 	if (mode == VIDEO_PALETTE_GREY) {			/* Set 16-bit input format (UV data are ignored) */			reg_w_mask(ov, 0x20, 0x00, 0x08);			/* Set 8-bit (4:0:0) output format */			reg_w_mask(ov, 0x28, 0x00, 0xf0);			reg_w_mask(ov, 0x38, 0x00, 0xf0);		} else {			/* Set 8-bit (YVYU) input format */			reg_w_mask(ov, 0x20, 0x08, 0x08);			/* Set 12-bit (4:2:0) output format */			reg_w_mask(ov, 0x28, 0x80, 0xf0);			reg_w_mask(ov, 0x38, 0x80, 0xf0);		}	} else {		reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80);		reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80);	}	hsegs = width / 16;	vsegs = height / 4;	reg_w(ov, 0x29, hsegs);	reg_w(ov, 0x2a, vsegs);	reg_w(ov, 0x39, hsegs);	reg_w(ov, 0x3a, vsegs);	/* Windows driver does this here; who knows why */	reg_w(ov, 0x2f, 0x80);	/******** Set the framerate (to maximum) ********/	/* Mode independent, but framerate dependent, regs */	/* Clock divider; lower==faster */	if (ov->bridge == BRG_OV518PLUS)		reg_w(ov, 0x51, 0x02);	else		reg_w(ov, 0x51, 0x04);	reg_w(ov, 0x22, 0x18);	reg_w(ov, 0x23, 0xff);	if (ov->bridge == BRG_OV518PLUS)		reg_w(ov, 0x21, 0x1f);	else		reg_w(ov, 0x71, 0x17);	/* Compression-related? */	// FIXME: Sensor-specific	/* Bit 5 is what matters here. Of course, it is "reserved" */	i2c_w(ov, 0x54, 0x23);	reg_w(ov, 0x2f, 0x80);	if (ov->bridge == BRG_OV518PLUS) {		reg_w(ov, 0x24, 0x9f);		reg_w(ov, 0x25, 0x90);		ov518_reg_w32(ov, 0xc4,    700, 2);	/* 2bch   */		ov518_reg_w32(ov, 0xc6,    498, 2);	/* 1f2h   */		ov518_reg_w32(ov, 0xc7,    498, 2);	/* 1f2h   */		ov518_reg_w32(ov, 0xc8,    100, 2);	/* 64h    */		ov518_reg_w32(ov, 0xca, 183331, 3);	/* 2cc23h */		ov518_reg_w32(ov, 0xcb,    895, 2);	/* 37fh   */		ov518_reg_w32(ov, 0xcc,   3000, 2);	/* bb8h   */		ov518_reg_w32(ov, 0xcd,     45, 2);	/* 2dh    */		ov518_reg_w32(ov, 0xce,    851, 2);	/* 353h   */	} else {		reg_w(ov, 0x24, 0x9f);		reg_w(ov, 0x25, 0x90);		ov518_reg_w32(ov, 0xc4,    400, 2);	/* 190h   */		ov518_reg_w32(ov, 0xc6,    381, 2);	/* 17dh   */		ov518_reg_w32(ov, 0xc7,    381, 2);	/* 17dh   */		ov518_reg_w32(ov, 0xc8,    128, 2);	/* 80h    */		ov518_reg_w32(ov, 0xca, 183331, 3);	/* 2cc23h */		ov518_reg_w32(ov, 0xcb,    746, 2);	/* 2eah   */		ov518_reg_w32(ov, 0xcc,   1750, 2);	/* 6d6h   */		ov518_reg_w32(ov, 0xcd,     45, 2);	/* 2dh    */		ov518_reg_w32(ov, 0xce,    851, 2);	/* 353h   */	}	reg_w(ov, 0x2f, 0x80);	if (ov51x_restart(ov) < 0)		return -EIO;	/* Reset it just for good measure */	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)		return -EIO;	return 0;}/* This is a wrapper around the OV511, OV518, and sensor specific functions */static intmode_init_regs(struct usb_ov511 *ov,	       int width, int height, int mode, int sub_flag){	int rc = 0;	if (ov->bclass == BCL_OV518) {		rc = ov518_mode_init_regs(ov, width, height, mode, sub_flag);	} else {		rc = ov511_mode_init_regs(ov, width, height, mode, sub_flag);	}	if (FATAL_ERROR(rc))		return rc;	switch (ov->sensor) {	case CC_OV7610:	case CC_OV7620:	case CC_OV76BE:	case CC_OV6620:	case CC_OV6630:	{		rc = set_ov_sensor_window(ov, width, height, mode, sub_flag);		break;	}	case SEN_SAA7111A:	{//		rc = mode_init_saa_sensor_regs(ov, width, height, mode,//					       sub_flag);		PDEBUG(1, "SAA status = 0x%02X", i2c_r(ov, 0x1f));		break;	}	default:		err("Unknown sensor");		rc = -EINVAL;	}	if (FATAL_ERROR(rc))		return rc;	return 0;}/* Set up the camera chip with the options provided by the module params */static intcamchip_init_settings(struct usb_ov511 *ov){	int rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_AUTOBRIGHT, autobright);	if (FATAL_ERROR(rc))		return rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_AUTOEXP, autoexp);	if (FATAL_ERROR(rc))		return rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_BANDFILT, bandingfilter);	if (FATAL_ERROR(rc))		return rc;	if (lightfreq) {		rc = sensor_set_light_freq(ov, lightfreq);		if (FATAL_ERROR(rc))			return rc;	}	rc = sensor_set_control(ov, OVCAMCHIP_CID_BACKLIGHT, backlight);	if (FATAL_ERROR(rc))		return rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_MIRROR, mirror);	if (FATAL_ERROR(rc))		return rc;	return 0;}/* This sets the default image parameters. This is useful for apps that use * read() and do not set 

⌨️ 快捷键说明

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