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

📄 h3600_backpaq_camera.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Driver for the Compaq iPAQ Mercury Backpaq camera * Video4Linux interface * * Copyright 2001 Compaq Computer Corporation. * * Use consistent with the GNU GPL is permitted, * provided that this copyright notice is * preserved in its entirety in all copies and derived works. * * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS * FITNESS FOR ANY PARTICULAR PURPOSE. * * Author: Andrew Christian  *         <andyc@handhelds.org> *         4 May 2001 * * Driver for Mercury BackPAQ camera * * Issues to be addressed: *    1. Writing to the FPGA when we need to do a functionality change *    2. Sampling the pixels correctly and building a pixel array *    3. Handling different pixel formats correctly *    4. Changing the contrast, brightness, white balance, and so forth. *    5. Specifying a subregion (i.e., setting "top, left" and SUBCAPTURE) */#include <linux/module.h>#include <linux/version.h>#include <linux/init.h>#include <asm/uaccess.h>         /* get_user,copy_to_user*/#include <linux/vmalloc.h>#include <linux/proc_fs.h>#include <linux/pm.h>#include <asm/io.h>#include <linux/wrapper.h>/* #include <asm/arch/hardware.h>*/  /* Included in <asm/io.h> */#include <asm/arch/backpaq.h>#include <asm/arch/h3600_backpaq_camera.h>#include <asm/irq.h>#include <linux/kmod.h>/* Actual chip specifications */#define HC_TRUE_WIDTH           644    /* Last two columns are black */#define HC_TRUE_HEIGHT          482#define HC_RAW_BUFFER_SIZE      ((u32) HC_TRUE_WIDTH * (u32) HC_TRUE_HEIGHT )#define HC_DECIMATED_WIDTH      320#define HC_DECIMATED_HEIGHT     240#define HC_DECIMATED_BUFFER_SIZE ((u32) HC_DECIMATED_WIDTH * (u32) HC_DECIMATED_HEIGHT )/* Largest frame buffer for 24 bit color (we don't do 32 bit color */#define HC_MAX_ALLOWED_WIDTH        640#define HC_MAX_ALLOWED_HEIGHT       480#define HC_MIN_ALLOWED_WIDTH        160#define HC_MIN_ALLOWED_HEIGHT       120/* Memory-mapped frame size */#define HC_MAX_PROCESSED_FRAME_UNALIGNED   (HC_MAX_ALLOWED_WIDTH * HC_MAX_ALLOWED_HEIGHT * 3)#define HC_MAX_PROCESSED_FRAME_SIZE        ((HC_MAX_PROCESSED_FRAME_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))/* Control locations for setting camera parameters */#define IMAGER_CTL_SPECIAL_MODES       0x10#define IMAGER_CTL_AUTOBRIGHT          0x60#define IMAGER_CTL_GAIN_FORMAT         0x70#define IMAGER_CTL_POWER_SETTING       0x80#define IMAGER_CTL_POWER_MANAGEMENT    0x90 /* Shouldn't need to set this *//* Mask definition so we only change modified parameters */#define PARAM_IMAGER_SPECIAL_MODES  (1 << 0)#define PARAM_IMAGER_AUTOBRIGHT     (1 << 1)#define PARAM_IMAGER_GAIN_FORMAT    (1 << 2)#define PARAM_IMAGER_POWER_SETTING  (1 << 3)#define PARAM_IMAGER_POWER_MGMT     (1 << 4)#define PARAM_FPGA_INTEGRATION_TIME (1 << 8)#define PARAM_FPGA_CLOCK_DIVISOR    (1 << 9)#define PARAM_FPGA_INTERRUPT_FIFO   (1 << 10)#define PARAM_FPGA_LIVE_MODE        (1 << 11)#define PARAM_FPGA_DECIMATION_MODE  (1 << 12)  /* Not a true parameter *//* Allow exterior control of decimation  */static int decimate_mode = 1;MODULE_PARM(decimate_mode, "i");MODULE_PARM_DESC(decimate_mode, "Use FPGA-based decimation");/* Camera modes */enum hc_camera_mode {	HC_MODE_RAW = 0,	HC_MODE_RAW_DECIMATED,	HC_MODE_DECIMATION_1,	HC_MODE_DECIMATION_2,	HC_MODE_DECIMATION_4,	HC_MODE_CIF,	HC_MODE_QCIF};static int fpga_mode_to_decimation[] = { 0, 1, 0, 1, 1, 0, 1 };struct h3600_mode_to_rawsize {	int width;	int height;	int bytes;};/* Use this table to convert a mode into a size */static struct h3600_mode_to_rawsize hc_raw[] = {	{ HC_TRUE_WIDTH, HC_TRUE_HEIGHT, HC_RAW_BUFFER_SIZE },	{ HC_DECIMATED_WIDTH, HC_DECIMATED_HEIGHT, HC_DECIMATED_BUFFER_SIZE }};/* We scan this table when setting a requested resolution */struct h3600_size_mode {	int width;	int height;	int mode;};static struct h3600_size_mode hc_default_resolutions[] = {	{ 160, 120, HC_MODE_DECIMATION_4 },	{ 176, 144, HC_MODE_QCIF },	{ 320, 240, HC_MODE_DECIMATION_2 },	{ 352, 288, HC_MODE_CIF },	{ 640, 480, HC_MODE_DECIMATION_1 },	{ 0, 0, 0 }};static struct h3600_size_mode hc_raw_resolutions[] = {	{ HC_DECIMATED_WIDTH, HC_DECIMATED_HEIGHT, HC_MODE_RAW_DECIMATED },	{ HC_TRUE_WIDTH, HC_TRUE_HEIGHT, HC_MODE_RAW },	{ 0, 0, 0 }};/* A single frame of raw data from the camera       *//* We can always tell the active mode from the size */enum frame_state {	FRAME_DONE = 0,	FRAME_PENDING,	FRAME_ACTIVE,	FRAME_FULL};struct frame {	unsigned char *data;           /* May point to true_data OR to shared memory segment */	unsigned char *local_data;     /* Our local storage area for raw frames */	unsigned char *shared_data;    /* Points into shared memory "frame_buf" */	int            bytes_read;     /* How full it is          */	int            bytes_to_read;  /* Normally width * height */	int            width;	int            height;	volatile enum frame_state state;	struct frame *next;    /* Linked list */};#define NUMBER_OF_FRAMES  2/* Core states */enum hc_v4l_state {	HC_V4L_IDLE = 0,	HC_V4L_GRABBING,          /* A "read" command has been issued */	HC_V4L_STREAMING          /* VIDIOCMCAPTURE active and there is an available buffer */};/* Capture states */  enum capture_state {	CAPTURE_OFF = 0,	CAPTURE_WAIT_FOR_REFRESH,    /* Waiting for a VBLANK                 */	CAPTURE_WAIT_FOR_FIFO,       /* Waiting for our first FIFO request   */	CAPTURE_ACTIVE               /* Actively receiving FIFO interrupts   */};struct capture_stats {	int  fifo_high;	int  fifo_low;	int  vblank_count;	int  fifo_count;	int  complete_frames;   /* Successfully captured frames */	int  ef_extra_vblank;      /* VBLANK while waiting for FIFO interrupt */	int  ef_fifo_overrun;      /* Miss because of fifo overrun */	int  ef_incomplete_frames; /* Miss because we didn't read all of the data */                   	int  ef_no_capture_buffer;    /* Miss because we didn't have an available capture buffer */	int  camera_writethru_wait;   /* Count how many "spins" of the writethru we blocked on */};struct h3600_camera_struct {	struct video_device     vdev;   /* This must be first */	struct video_picture    vpic;   /* v4l camera settings */	struct video_window     vwin;   /* v4l capture area */	struct h3600_backpaq_camera_params params;   /* Our special settings */	int param_mask;                              /* Which parameters need to be updated */	volatile enum hc_v4l_state  state;	/* v4l current state = IDLE, GRABBING, STREAMING */	/* Capture data */	struct frame *active;     /* List of capture frames that need filling */	volatile enum capture_state  capture_state;       /* Active capture mode */	struct frame                 frame[NUMBER_OF_FRAMES];	struct capture_stats         capture_stats;	wait_queue_head_t            capq;	/* Processing data */	enum hc_camera_mode mode;              /* Mode index selection (RAW, DECIMATE_1, etc...)  */	struct semaphore        lock;          /* Force single access */	int                     usage_count;   /* How many are open */	/* mmap interface */	unsigned char *         frame_buf;      /* frame buffer data (raw bits stored here) */};#define BACKPAQ_CAMERA_DEBUG// #undef BACKPAQ_CAMERA_DEBUG#ifdef BACKPAQ_CAMERA_DEBUG#define CAMDEBUG(format,args...)  printk(KERN_ALERT __FILE__ format, ## args)#else#define CAMDEBUG(x)     do { } while(0)#endif#define CAMERROR(format,args...)  printk(KERN_ERR  __FILE__ format, ## args)/* Global variables */static struct h3600_camera_struct hc_camera;     /* We only have a single camera */static struct proc_dir_entry     *proc_backpaq_camera = NULL;unsigned int h3600_camera_debug = 0;/* Useful externals */int h3600_backpaq_fpga_status(void);/* insmod options */MODULE_PARM(h3600_camera_debug,"i");MODULE_PARM_DESC(h3600_camera_debug,"debug messages, default is 0 (no)");#define BANNER "Compaq iPAQ H3600 Mercury BackPAQ Camera for Video4Linux"MODULE_DESCRIPTION(BANNER);MODULE_AUTHOR("Andrew Christian <andyc@handhelds.org>");/******************************* *  Utility routines  *******************************/static void set_camera_resolution( struct h3600_camera_struct *cam,				  int palette, int width, int height ){	struct h3600_size_mode *m = hc_default_resolutions;	enum hc_camera_mode old_mode = cam->mode;	cam->vpic.palette = palette;	switch (palette) {	case VIDEO_PALETTE_RAW:		cam->vpic.depth = 8;		m = hc_raw_resolutions;		break;	case VIDEO_PALETTE_RGB24:		cam->vpic.depth = 24;		break;	case VIDEO_PALETTE_GREY:		cam->vpic.depth = 8;		break;	case VIDEO_PALETTE_YUV422:		cam->vpic.depth = 16;		break;	}	do {		cam->vwin.width = m->width;		cam->vwin.height = m->height;		cam->mode = m->mode;		m++;	} while ( m->width > 0 && width >= m->width && height >= m->height );//	printk(KERN_ALERT __FILE__ ": " __FUNCTION__  ": Setting to %d x %d, mode %d (%d)\n", //	       cam->vwin.width, cam->vwin.height, cam->mode,//	       fpga_mode_to_decimation[cam->mode]);	// Set the param_mask field if we need to change decimation modes */	if ( fpga_mode_to_decimation[cam->mode] != fpga_mode_to_decimation[old_mode] )		cam->param_mask |= PARAM_FPGA_DECIMATION_MODE;}static unsigned long required_buf_size( struct h3600_camera_struct *cam ){	unsigned long pixel_count = cam->vwin.width * cam->vwin.height;	switch (cam->vpic.palette) {	case VIDEO_PALETTE_RGB24:		pixel_count *= 3;		break;	case VIDEO_PALETTE_YUV422:		pixel_count *= 2;		break;	}	return pixel_count;}/********************************************************************** * * Memory management * * This is a shameless copy from the cpia driver (linux kernel * version 2.3.29 or so, I have no idea what this code actually does ;). * Actually it seems to be a copy of a shameless copy of the bttv-driver. * **********************************************************************//* Given PGD from the address space's page table, return the kernel * virtual mapping of the physical memory mapped at ADR. */static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr){	unsigned long ret = 0UL;	pmd_t *pmd;	pte_t *ptep, pte;	if (!pgd_none(*pgd)) {		pmd = pmd_offset(pgd, adr);		if (!pmd_none(*pmd)) {			ptep = pte_offset(pmd, adr);			pte = *ptep;			if (pte_present(pte)) {				ret = (unsigned long) page_address(pte_page(pte));				ret |= (adr & (PAGE_SIZE-1));			}		}	}	return ret;}/* Here we want the physical address of the memory. * This is used when initializing the contents of the * area and marking the pages as reserved. */static inline unsigned long kvirt_to_pa(unsigned long adr){	unsigned long va, kva, ret;	va = VMALLOC_VMADDR(adr);	kva = uvirt_to_kva(pgd_offset_k(va), va);	ret = __pa(kva);	return ret;}static void *rvmalloc(unsigned long size){	void *mem;	unsigned long adr, page;	/* Round it off to PAGE_SIZE */	size += (PAGE_SIZE - 1);	size &= ~(PAGE_SIZE - 1);	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) {		page = kvirt_to_pa(adr);		mem_map_reserve(virt_to_page(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	return mem;}static void rvfree(void *mem, unsigned long size){	unsigned long adr, page;	if (!mem)		return;	size += (PAGE_SIZE - 1);	size &= ~(PAGE_SIZE - 1);	adr = (unsigned long) mem;	while (size > 0) {		page = kvirt_to_pa(adr);		mem_map_unreserve(virt_to_page(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	vfree(mem);}static int allocate_frame_buf(struct h3600_camera_struct *cam){	int i;	cam->frame_buf = rvmalloc(NUMBER_OF_FRAMES * HC_MAX_PROCESSED_FRAME_SIZE);

⌨️ 快捷键说明

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