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

📄 ov511.c

📁 用于ARM S3C44B0/S3C4510嵌入式系统的ov511驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			rc = i2c_r(ov, 0x10);			if (rc < 0)				return rc;			else				*val = rc;			break;		case SEN_KS0127:		case SEN_KS0127B:		case SEN_SAA7111A:			val = 0;			PDEBUG(3, "Unsupported with this sensor");			return -EPERM;		default:			err("Sensor not supported for get_exposure");			return -EINVAL;		}		PDEBUG(3, "%d", *val);		ov->exposure = *val;		return 0;	}#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */	/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */	static inline void	ov51x_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	 *	 * Tested with: OV7610, OV7620, OV76BE, OV6620	 * Unsupported: KS0127, KS0127B, SAA7111A	 * Returns: 0 for success	 */	static int	sensor_set_light_freq(struct usb_ov511 *ov, int freq)	{		int sixty;		PDEBUG(4, "%d Hz", freq);		if (freq == 60)			sixty = 1;		else if (freq == 50)			sixty = 0;		else {			err("Invalid light freq (%d Hz)", freq);			return -EINVAL;		}		switch (ov->sensor) {		case SEN_OV7610:			i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);			i2c_w(ov, 0x2b, sixty?0x00:0xac);			i2c_w_mask(ov, 0x13, 0x10, 0x10);			i2c_w_mask(ov, 0x13, 0x00, 0x10);			break;		case SEN_OV7620:		case SEN_OV76BE:		case SEN_OV8600:			i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);			i2c_w(ov, 0x2b, sixty?0x00:0xac);			i2c_w_mask(ov, 0x76, 0x01, 0x01);			break;		case SEN_OV6620:		case SEN_OV6630:			i2c_w(ov, 0x2b, sixty?0xa8:0x28);			i2c_w(ov, 0x2a, sixty?0x84:0xa4);			break;		case SEN_KS0127:		case SEN_KS0127B:		case SEN_SAA7111A:			PDEBUG(5, "Unsupported with this sensor");			return -EPERM;		default:			err("Sensor not supported for set_light_freq");			return -EINVAL;		}		ov->lightfreq = freq;		return 0;	}	/* If enable is true, turn on the sensor's banding filter, otherwise turn it	 * off. This filter tries to reduce the pattern of horizontal light/dark bands	 * caused by some (usually fluorescent) lighting. The light frequency must be	 * set either before or after enabling it with ov51x_set_light_freq().	 *	 * Tested with: OV7610, OV7620, OV76BE, OV6620.	 * Unsupported: KS0127, KS0127B, SAA7111A	 * Returns: 0 for success	 */	static inline int	sensor_set_banding_filter(struct usb_ov511 *ov, int enable)	{		int rc;		PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");		if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B			|| ov->sensor == SEN_SAA7111A) {			PDEBUG(5, "Unsupported with this sensor");			return -EPERM;		}		rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04);		if (rc < 0)			return rc;		ov->bandfilt = enable;		return 0;	}	/* If enable is true, turn on the sensor's auto brightness control, otherwise	 * turn it off.	 *	 * Unsupported: KS0127, KS0127B, SAA7111A	 * Returns: 0 for success	 */	static inline int	sensor_set_auto_brightness(struct usb_ov511 *ov, int enable)	{		int rc;		PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");		if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B			|| ov->sensor == SEN_SAA7111A) {			PDEBUG(5, "Unsupported with this sensor");			return -EPERM;		}		rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10);		if (rc < 0)			return rc;		ov->auto_brt = enable;		return 0;	}	/* If enable is true, turn on the sensor's auto exposure control, otherwise	 * turn it off.	 *	 * Unsupported: KS0127, KS0127B, SAA7111A	 * Returns: 0 for success	 */	static inline int	sensor_set_auto_exposure(struct usb_ov511 *ov, int enable)	{		PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");		switch (ov->sensor) {		case SEN_OV7610:			i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80);			break;		case SEN_OV6620:		case SEN_OV7620:		case SEN_OV76BE:		case SEN_OV8600:			i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01);			break;		case SEN_OV6630:			i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10);			break;		case SEN_KS0127:		case SEN_KS0127B:		case SEN_SAA7111A:			PDEBUG(5, "Unsupported with this sensor");			return -EPERM;		default:			err("Sensor not supported for set_auto_exposure");			return -EINVAL;		}		ov->auto_exp = enable;		return 0;	}	/* Modifies the sensor's exposure algorithm to allow proper exposure of objects	 * that are illuminated from behind.	 *	 * Tested with: OV6620, OV7620	 * Unsupported: OV7610, OV76BE, KS0127, KS0127B, SAA7111A	 * Returns: 0 for success	 */	static int	sensor_set_backlight(struct usb_ov511 *ov, int enable)	{		PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");		switch (ov->sensor) {		case SEN_OV7620:		case SEN_OV8600:			i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0);			i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);			i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);			break;		case SEN_OV6620:			i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0);			i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);			i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80);			break;		case SEN_OV6630:			i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0);			i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);			i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);			break;		case SEN_OV7610:		case SEN_OV76BE:		case SEN_KS0127:		case SEN_KS0127B:		case SEN_SAA7111A:			PDEBUG(5, "Unsupported with this sensor");			return -EPERM;		default:			err("Sensor not supported for set_backlight");			return -EINVAL;		}		ov->backlight = enable;		return 0;	}	static inline int	sensor_set_mirror(struct usb_ov511 *ov, int enable)	{		PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");		switch (ov->sensor) {		case SEN_OV6620:		case SEN_OV6630:		case SEN_OV7610:		case SEN_OV7620:		case SEN_OV76BE:		case SEN_OV8600:			i2c_w_mask(ov, 0x12, enable?0x40:0x00, 0x40);			break;		case SEN_KS0127:		case SEN_KS0127B:		case SEN_SAA7111A:			PDEBUG(5, "Unsupported with this sensor");			return -EPERM;		default:			err("Sensor not supported for set_mirror");			return -EINVAL;		}		ov->mirror = enable;		return 0;	}	/* Returns number of bits per pixel (regardless of where they are located;	 * planar or not), or zero for unsupported format.	 */	static inline int	get_depth(int palette)	{		switch (palette) {		case VIDEO_PALETTE_GREY:    return 8;		case VIDEO_PALETTE_YUV420:  return 12;		case VIDEO_PALETTE_YUV420P: return 12; /* Planar */		case VIDEO_PALETTE_RGB565:  return 16;		case VIDEO_PALETTE_RGB24:   return 24;		case VIDEO_PALETTE_YUV422:  return 16;		case VIDEO_PALETTE_YUYV:    return 16;		case VIDEO_PALETTE_YUV422P: return 16; /* Planar */		default:		    return 0;  /* Invalid format */		}	}	/* Bytes per frame. Used by read(). Return of 0 indicates error */	static inline long int	get_frame_length(struct ov511_frame *frame)	{		if (!frame)			return 0;		else			return ((frame->width * frame->height				 * get_depth(frame->format)) >> 3);	}	static int	mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,				 int mode, int sub_flag, int qvga)	{		int clock;		/******** Mode (VGA/QVGA) and sensor specific regs ********/		switch (ov->sensor) {		case SEN_OV7610:			i2c_w(ov, 0x14, qvga?0x24:0x04);	// FIXME: Does this improve the image quality or frame rate?#if 0			i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);			i2c_w(ov, 0x24, 0x10);			i2c_w(ov, 0x25, qvga?0x40:0x8a);			i2c_w(ov, 0x2f, qvga?0x30:0xb0);			i2c_w(ov, 0x35, qvga?0x1c:0x9c);#endif			break;		case SEN_OV7620:	//		i2c_w(ov, 0x2b, 0x00);			i2c_w(ov, 0x14, qvga?0xa4:0x84);			i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);			i2c_w(ov, 0x24, qvga?0x20:0x3a);			i2c_w(ov, 0x25, qvga?0x30:0x60);			i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);			i2c_w_mask(ov, 0x67, qvga?0xf0:0x90, 0xf0);			i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);			break;		case SEN_OV76BE:	//		i2c_w(ov, 0x2b, 0x00);			i2c_w(ov, 0x14, qvga?0xa4:0x84);	// FIXME: Enable this once 7620AE uses 7620 initial settings#if 0			i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);			i2c_w(ov, 0x24, qvga?0x20:0x3a);			i2c_w(ov, 0x25, qvga?0x30:0x60);			i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);			i2c_w_mask(ov, 0x67, qvga?0xb0:0x90, 0xf0);			i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);#endif			break;		case SEN_OV6620:		case SEN_OV6630:			i2c_w(ov, 0x14, qvga?0x24:0x04);			/* No special settings yet */			break;		default:			err("Invalid sensor");			return -EINVAL;		}		/******** Palette-specific regs ********/		if (mode == VIDEO_PALETTE_GREY) {			if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) {				/* these aren't valid on the OV6620/OV7620/6630? */				i2c_w_mask(ov, 0x0e, 0x40, 0x40);			}			i2c_w_mask(ov, 0x13, 0x20, 0x20);		} else {			if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) {				/* not valid on the OV6620/OV7620/6630? */				i2c_w_mask(ov, 0x0e, 0x00, 0x40);			}			i2c_w_mask(ov, 0x13, 0x00, 0x20);		}		/******** Clock programming ********/		// FIXME: Test this with OV6630		/* The OV6620 needs special handling. This prevents the 		 * severe banding that normally occurs */		if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630)		{			/* Clock down */			i2c_w(ov, 0x2a, 0x04);			if (ov->compress) {	//			clock = 0;    /* This ensures the highest frame rate */				clock = 3;			} else if (clockdiv == -1) {   /* If user didn't override it */				clock = 3;    /* Gives better exposure time */			} else {				clock = clockdiv;			}			PDEBUG(4, "Setting clock divisor to %d", clock);			i2c_w(ov, 0x11, clock);			i2c_w(ov, 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(ov, 0x2d, 0x85);		}		else		{			if (ov->compress) {				clock = 1;    /* This ensures the highest frame rate */			} else if (clockdiv == -1) {   /* If user didn't override it */				/* Calculate and set the clock divisor */				clock = ((sub_flag ? ov->subw * ov->subh					  : width * height)					 * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2)					 / 66000;			} else {				clock = clockdiv;			}			PDEBUG(4, "Setting clock divisor to %d", clock);			i2c_w(ov, 0x11, clock);		}		/******** Special Features ********/		if (framedrop >= 0)			i2c_w(ov, 0x16, framedrop);		if (sensor_gbr)			i2c_w_mask(ov, 0x12, 0x08, 0x08);		else			i2c_w_mask(ov, 0x12, 0x00, 0x08);		/* Test Pattern */		i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02);		/* Auto white balance */	//	if (awb)			i2c_w_mask(ov, 0x12, 0x04, 0x04);	//	else	//		i2c_w_mask(ov, 0x12, 0x00, 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 (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) {			if (width == 640 && height == 480)				i2c_w(ov, 0x35, 0x9e);			else				i2c_w(ov, 0x35, 0x1e);		}		return 0;	}	static int	set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode,			     int sub_flag)	{		int ret;		int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; 		int hoffset, voffset, hwscale = 0, vwscale = 0;		/* 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 (ov->sensor) {		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;		default:			err("Invalid sensor");			return -EINVAL;		}		if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) {			/* Note: OV518(+) does downsample on its own) */			if ((width > 176 && height > 144)			    || ov->bclass == BCL_OV518) {  /* CIF */				ret = mode_init_ov_sensor_regs(ov, width, height,					mode, sub_flag, 0);				if (ret < 0)					return ret;				hwscale = 1;				vwscale = 1;  /* The datasheet says 0; it's wrong */				hwsize = 352;				vwsize = 288;			} else if (width > 176 || height > 144) {				err("Illegal dimensions");				return -EINVAL;			} else {			    /* QCIF */				ret = mode_init_ov_sensor_regs(ov, width, height,					mode, sub_flag, 1);				if (ret < 0)					return ret;				hwsize = 176;				vwsize = 144;			}		} else {			if (width > 320 && height > 240) {  /* VGA */				ret = mode_init_ov_sensor_regs(ov, width, height,					mode, sub_flag, 0);				if (ret < 0)					return ret;				hwscale = 2;				vwscale = 1;				hwsize = 640;				vwsize = 480;			} else if (width > 320 || height > 240) {				err("Ill

⌨️ 快捷键说明

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