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

📄 ov511.c

📁 用于ARM S3C44B0/S3C4510嵌入式系统的ov511驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * OmniVision OV511 Camera-to-USB Bridge Driver	 *	 * Copyright (c) 1999-2002 Mark W. McClelland	 * Original decompression code Copyright 1998-2000 OmniVision Technologies	 * Many improvements by Bret Wallach <bwallac1@san.rr.com>	 * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)	 * Snapshot code by Kevin Moore	 * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>	 * Changes by Claudio Matsuoka <claudio@conectiva.com>	 * Original SAA7111A code by Dave Perks <dperks@ibm.net>	 * URB error messages from pwc driver by Nemosoft	 * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox	 *	 * Based on the Linux CPiA driver written by Peter Pregler,	 * Scott J. Bertin and Johannes Erdfelt.	 * 	 * Please see the file: linux/Documentation/usb/ov511.txt 	 * and the website at:  http://alpha.dyndns.org/ov511	 * for more info.	 *	 * 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 (at your	 * option) 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., 675 Mass Ave, Cambridge, MA 02139, USA.	 */#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/ctype.h>#include <linux/pagemap.h>#include <asm/io.h>#include <asm/semaphore.h>#include <asm/processor.h>#include <linux/wrapper.h>#if defined (__i386__)		#include <asm/cpufeature.h>#endif#include "ov511.h"	/*	 * Version Information	 */#define DRIVER_VERSION "v1.61 for Linux 2.4"#define EMAIL "mark@alpha.dyndns.org"#define DRIVER_AUTHOR "Mark McClelland <mmcclell@bigfoot.com> & Bret Wallach \		& Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \		<cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"#define DRIVER_DESC "ov511 USB Camera Driver"#define OV511_I2C_RETRIES 3#define ENABLE_Y_QUANTABLE 1#define ENABLE_UV_QUANTABLE 1#define OV511_MAX_UNIT_VIDEO 16	/* Pixel count * 3 bytes for RGB */#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3)#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval))	/* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */#define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024)#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)	/**********************************************************************	 * Module Parameters	 * (See ov511.txt for detailed descriptions of these)	 **********************************************************************/	/* These variables (and all static globals) default to zero */	static int autobright		= 1;	static int autogain		= 1;	static int autoexp		= 1;	static int debug		= 1;	static int snapshot;	static int fix_rgb_offset;	static int force_rgb;	static int cams			= 5;	static int compress;	static int testpat;	static int sensor_gbr;	static int dumppix;	static int led 			= 1;	static int dump_bridge;	static int dump_sensor;	static int printph;	static int phy			= 0x1f;	static int phuv			= 0x05;	static int pvy			= 0x06;	static int pvuv			= 0x06;	static int qhy			= 0x14;	static int qhuv			= 0x03;	static int qvy			= 0x04;	static int qvuv			= 0x04;	static int lightfreq;	static int bandingfilter;	static int clockdiv		= -1;	static int packetsize		= -1;	static int framedrop		= -1;	static int fastset;	static int force_palette;	static int backlight;	static int unit_video[OV511_MAX_UNIT_VIDEO];	static int remove_zeros;	static int mirror;	MODULE_PARM(autobright, "i");	MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");	MODULE_PARM(autogain, "i");	MODULE_PARM_DESC(autogain, "Sensor automatically changes gain");	MODULE_PARM(autoexp, "i");	MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure");	MODULE_PARM(debug, "i");	MODULE_PARM_DESC(debug,	  "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");	MODULE_PARM(snapshot, "i");	MODULE_PARM_DESC(snapshot, "Enable snapshot mode");	MODULE_PARM(fix_rgb_offset, "i");	MODULE_PARM_DESC(fix_rgb_offset,	  "Fix vertical misalignment of red and blue at 640x480");	MODULE_PARM(force_rgb, "i");	MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");	MODULE_PARM(cams, "i");	MODULE_PARM_DESC(cams, "Number of simultaneous cameras");	MODULE_PARM(compress, "i");	MODULE_PARM_DESC(compress, "Turn on compression (not reliable yet)");	MODULE_PARM(testpat, "i");	MODULE_PARM_DESC(testpat,	  "Replace image with vertical bar testpattern (only partially working)");	MODULE_PARM(dumppix, "i");	MODULE_PARM_DESC(dumppix, "Dump raw pixel data");	MODULE_PARM(led, "i");	MODULE_PARM_DESC(led,	  "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)");	MODULE_PARM(dump_bridge, "i");	MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");	MODULE_PARM(dump_sensor, "i");	MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers");	MODULE_PARM(printph, "i");	MODULE_PARM_DESC(printph, "Print frame start/end headers");	MODULE_PARM(phy, "i");	MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)");	MODULE_PARM(phuv, "i");	MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)");	MODULE_PARM(pvy, "i");	MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)");	MODULE_PARM(pvuv, "i");	MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)");	MODULE_PARM(qhy, "i");	MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)");	MODULE_PARM(qhuv, "i");	MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)");	MODULE_PARM(qvy, "i");	MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)");	MODULE_PARM(qvuv, "i");	MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)");	MODULE_PARM(lightfreq, "i");	MODULE_PARM_DESC(lightfreq,	  "Light frequency. Set to 50 or 60 Hz, or zero for default settings");	MODULE_PARM(bandingfilter, "i");	MODULE_PARM_DESC(bandingfilter,	  "Enable banding filter (to reduce effects of fluorescent lighting)");	MODULE_PARM(clockdiv, "i");	MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value");	MODULE_PARM(packetsize, "i");	MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size");	MODULE_PARM(framedrop, "i");	MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting");	MODULE_PARM(fastset, "i");	MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately");	MODULE_PARM(force_palette, "i");	MODULE_PARM_DESC(force_palette, "Force the palette to a specific value");	MODULE_PARM(backlight, "i");	MODULE_PARM_DESC(backlight, "For objects that are lit from behind");	MODULE_PARM(unit_video, "1-" __MODULE_STRING(OV511_MAX_UNIT_VIDEO) "i");	MODULE_PARM_DESC(unit_video,	  "Force use of specific minor number(s). 0 is not allowed.");	MODULE_PARM(remove_zeros, "i");	MODULE_PARM_DESC(remove_zeros,	  "Remove zero-padding from uncompressed incoming data");	MODULE_PARM(mirror, "i");	MODULE_PARM_DESC(mirror, "Reverse image horizontally");	MODULE_AUTHOR(DRIVER_AUTHOR);	MODULE_DESCRIPTION(DRIVER_DESC);	MODULE_LICENSE("GPL");	/**********************************************************************	 * Miscellaneous Globals	 **********************************************************************/	static struct usb_driver ov511_driver;	static struct ov51x_decomp_ops *ov511_decomp_ops;	static struct ov51x_decomp_ops *ov511_mmx_decomp_ops;	static struct ov51x_decomp_ops *ov518_decomp_ops;	static struct ov51x_decomp_ops *ov518_mmx_decomp_ops;	/* Number of times to retry a failed I2C transaction. Increase this if you	 * are getting "Failed to read sensor ID..." */	static int i2c_detect_tries = 5;	/* MMX support is present in kernel and CPU. Checked upon decomp module load. */	static int ov51x_mmx_available;	static /*__devinitdata*/ struct usb_device_id device_table [] = {		{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },		{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },		{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },		{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },		{ USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },		{ }  /* Terminating entry */	};	MODULE_DEVICE_TABLE (usb, device_table);	static unsigned char yQuanTable511[] = OV511_YQUANTABLE;	static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE;	static unsigned char yQuanTable518[] = OV518_YQUANTABLE;	static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;	/**********************************************************************	 * Symbolic Names	 **********************************************************************/	/* Known OV511-based cameras */	static struct symbolic_list camlist[] = {		{   0, "Generic Camera (no ID)" },		{   1, "Mustek WCam 3X" },		{   3, "D-Link DSB-C300" },		{   4, "Generic OV511/OV7610" },		{   5, "Puretek PT-6007" },		{   6, "Lifeview USB Life TV (NTSC)" },		{  21, "Creative Labs WebCam 3" },		{  22, "Lifeview USB Life TV (PAL D/K+B/G)" },		{  36, "Koala-Cam" },		{  38, "Lifeview USB Life TV (PAL)" },		{  41, "Samsung Anycam MPC-M10" },		{  43, "Mtekvision Zeca MV402" },		{  46, "Suma eON" },		{  70, "Lifeview USB Life TV (PAL/SECAM)" },		{ 100, "Lifeview RoboCam" },		{ 102, "AverMedia InterCam Elite" },		{ 112, "MediaForte MV300" },	/* or OV7110 evaluation kit */		{ 108, "Webeye 2000B" },		{  -1, NULL }	};	/* Video4Linux1 Palettes */	static struct symbolic_list v4l1_plist[] = {		{ VIDEO_PALETTE_GREY,	"GREY" },		{ VIDEO_PALETTE_HI240,	"HI240" },		{ VIDEO_PALETTE_RGB565,	"RGB565" },		{ VIDEO_PALETTE_RGB24,	"RGB24" },		{ VIDEO_PALETTE_RGB32,	"RGB32" },		{ VIDEO_PALETTE_RGB555,	"RGB555" },		{ VIDEO_PALETTE_YUV422,	"YUV422" },		{ VIDEO_PALETTE_YUYV,	"YUYV" },		{ VIDEO_PALETTE_UYVY,	"UYVY" },		{ VIDEO_PALETTE_YUV420,	"YUV420" },		{ VIDEO_PALETTE_YUV411,	"YUV411" },		{ VIDEO_PALETTE_RAW,	"RAW" },		{ VIDEO_PALETTE_YUV422P,"YUV422P" },		{ VIDEO_PALETTE_YUV411P,"YUV411P" },		{ VIDEO_PALETTE_YUV420P,"YUV420P" },		{ VIDEO_PALETTE_YUV410P,"YUV410P" },		{ -1, NULL }	};	static struct symbolic_list brglist[] = {		{ BRG_OV511,		"OV511" },		{ BRG_OV511PLUS,	"OV511+" },		{ BRG_OV518,		"OV518" },		{ BRG_OV518PLUS,	"OV518+" },		{ -1, NULL }	};	static struct symbolic_list senlist[] = {		{ SEN_OV76BE,	"OV76BE" },		{ SEN_OV7610,	"OV7610" },		{ SEN_OV7620,	"OV7620" },		{ SEN_OV7620AE,	"OV7620AE" },		{ SEN_OV6620,	"OV6620" },		{ SEN_OV6630,	"OV6630" },		{ SEN_OV6630AE,	"OV6630AE" },		{ SEN_OV6630AF,	"OV6630AF" },		{ SEN_OV8600,	"OV8600" },		{ SEN_KS0127,	"KS0127" },		{ SEN_KS0127B,	"KS0127B" },		{ SEN_SAA7111A,	"SAA7111A" },		{ -1, NULL }	};	/* URB error codes: */	static struct symbolic_list urb_errlist[] = {		{ -ENOSR,	"Buffer error (overrun)" },		{ -EPIPE,	"Stalled (device not responding)" },		{ -EOVERFLOW,	"Babble (bad cable?)" },		{ -EPROTO,	"Bit-stuff error (bad cable?)" },		{ -EILSEQ,	"CRC/Timeout" },		{ -ETIMEDOUT,	"NAK (device does not respond)" },		{ -1, NULL }	};	/**********************************************************************	 * Prototypes	 **********************************************************************/	static void ov51x_clear_snapshot(struct usb_ov511 *);	static inline int sensor_get_picture(struct usb_ov511 *,					     struct video_picture *);#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)	static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);	static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,				       unsigned long);	static int ov51x_check_snapshot(struct usb_ov511 *);#endif	/**********************************************************************	 * Memory management	 **********************************************************************/	/* Here we want the physical address of the memory.	 * This is used when initializing the contents of the area.	 */	static inline unsigned long	kvirt_to_pa(unsigned long adr)	{		unsigned long kva, ret;		kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));		kva |= adr & (PAGE_SIZE-1); /* restore the offset */		ret = __pa(kva);		return ret;	}	static void *	rvmalloc(unsigned long size)	{		void *mem;		unsigned long adr;		size = PAGE_ALIGN(size);		mem = vmalloc_32(size);		if (!mem)			return NULL;		memset(mem, 0, size); /* Clear the ram out, no junk to the user */		adr = (unsigned long) mem;		while (size > 0) {			mem_map_reserve(vmalloc_to_page((void *)adr));			adr += PAGE_SIZE;			size -= PAGE_SIZE;		}		return mem;	}	static void	rvfree(void *mem, unsigned long size)	{		unsigned long adr;		if (!mem)			return;		adr = (unsigned long) mem;		while ((long) size > 0) {			mem_map_unreserve(vmalloc_to_page((void *)adr));			adr += PAGE_SIZE;			size -= PAGE_SIZE;		}		vfree(mem);	}	/**********************************************************************	 * /proc interface	 * Based on the CPiA driver version 0.7.4 -claudio	 **********************************************************************/#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)	static struct proc_dir_entry *ov511_proc_entry = NULL;	extern struct proc_dir_entry *video_proc_entry;	static struct file_operations ov511_control_fops = {		ioctl:		ov51x_control_ioctl,	};#define YES_NO(x) ((x) ? "yes" : "no")	/* /proc/video/ov511/<minor#>/info */	static int	ov511_read_proc_info(char *page, char **start, off_t off, int count, int *eof,			     void *data)	{		char *out = page;		int i, len;		struct usb_ov511 *ov = data;		struct video_picture p;		unsigned char exp;		if (!ov || !ov->dev)			return -ENODEV;		sensor_get_picture(ov, &p);		sensor_get_exposure(ov, &exp);		/* IMPORTANT: This output MUST be kept under PAGE_SIZE		 *            or we need to get more sophisticated. */		out += sprintf(out, "driver_version  : %s\n", DRIVER_VERSION);		out += sprintf(out, "custom_id       : %d\n", ov->customid);		out += sprintf(out, "model           : %s\n", ov->desc);		out += sprintf(out, "streaming       : %s\n", YES_NO(ov->streaming));		out += sprintf(out, "grabbing        : %s\n", YES_NO(ov->grabbing));		out += sprintf(out, "compress        : %s\n", YES_NO(ov->compress));		out += sprintf(out, "subcapture      : %s\n", YES_NO(ov->sub_flag));		out += sprintf(out, "sub_size        : %d %d %d %d\n",			       ov->subx, ov->suby, ov->subw, ov->subh);		out += sprintf(out, "data_format     : %s\n",			       force_rgb ? "RGB" : "BGR");		out += sprintf(out, "brightness      : %d\n", p.brightness >> 8);		out += sprintf(out, "colour          : %d\n", p.colour >> 8);		out += sprintf(out, "contrast        : %d\n", p.contrast >> 8);		out += sprintf(out, "hue             : %d\n", p.hue >> 8);		out += sprintf(out, "exposure        : %d\n", exp);		out += sprintf(out, "num_frames      : %d\n", OV511_NUMFRAMES);		for (i = 0; i < OV511_NUMFRAMES; i++) {			out += sprintf(out, "frame           : %d\n", i);			out += sprintf(out, "  depth         : %d\n",				       ov->frame[i].depth);			out += sprintf(out, "  size          : %d %d\n",				       ov->frame[i].width, ov->frame[i].height);			out += sprintf(out, "  format        : %s\n",				       symbolic(v4l1_plist, ov->frame[i].format));			out += sprintf(out, "  data_buffer   : 0x%p\n",				       ov->frame[i].data);		}		out += sprintf(out, "snap_enabled    : %s\n", YES_NO(ov->snap_enabled));		out += sprintf(out, "bridge          : %s\n",			       symbolic(brglist, ov->bridge));		out += sprintf(out, "sensor          : %s\n",			       symbolic(senlist, ov->sensor));		out += sprintf(out, "packet_size     : %d\n", ov->packet_size);		out += sprintf(out, "framebuffer     : 0x%p\n", ov->fbuf);		len = out - page;		len -= off;		if (len < count) {			*eof = 1;			if (len <= 0)				return 0;		} else			len = count;		*start = page + off;		return len;	}	/* /proc/video/ov511/<minor#>/button	 *	 * When the camera's button is pressed, the output of this will change from a	 * 0 to a 1 (ASCII). It will retain this value until it is read, after which	 * it will reset to zero.	 *	 * SECURITY NOTE: Since reading this file can change the state of the snapshot	 * status, it is important for applications that open it to keep it locked	 * against access by other processes, using flock() or a similar mechanism. No	 * locking is provided by this driver.	 */	static int	ov511_read_proc_button(char *page, char **start, off_t off, int count, int *eof,			       void *data)	{		char *out = page;		int len, status;		struct usb_ov511 *ov = data;		if (!ov || !ov->dev)			return -ENODEV;		status = ov51x_check_snapshot(ov);		out += sprintf(out, "%d", status);		if (status)			ov51x_clear_snapshot(ov);		len = out - page;		len -= off;		if (len < count) {			*eof = 1;			if (len <= 0)				return 0;		} else {			len = count;		}		*start = page + off;		return len;

⌨️ 快捷键说明

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