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

📄 h3600_backpaq_core.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 * * Support for Philips imagers added February, 2002 * * 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/irq.h>#include <linux/kmod.h>#include <asm/arch/backpaq.h>#include "h3600_backpaq_common.h"#include "philips_image_sensor.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 *//*  Definitions for Smallcam image sensor */#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) /* Actually used for Smallcam */#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 }};#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 */};static char * camera_type_names[] = {	"smal",	"philips"};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 */	enum h3600_camera_type  ctype;  /* Type of camera */		/* General parameters common to all camera types */		unsigned short clock_divisor;      /* 0x100 = 5 fps */	unsigned short interrupt_fifo;	unsigned char  read_polling_mode;  /* Force "read" to use polling mode */	unsigned char  flip;               /* Set to TRUE to invert image */	/* Parameters specific to SMaL camera */	unsigned char  power_setting;	unsigned char  gain_format;	unsigned char  power_mgmt;	unsigned char  special_modes;	unsigned char  autobright;	/* Parameters specific to the Philips camera */          enum Philips_sub_type   cam_sub_type;        /* Sub type for philips cameras */	unsigned short          electronic_shutter;	unsigned char           subrow;              /* negative subrow means switch it off */	/* Which parameters need to be updated */	int param_mask;		/* I2C data for Philips sensors */	unsigned char           i2c_status;          /* interrupt status */	wait_queue_head_t       i2cq;                /* Wait queue for i2c transaction */	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)#define PRINTDEBUG(format,args...)  printk(__FUNCTION__ format, ## args)#else#define CAMDEBUG(format,args...)#define PRINTDEBUG(format,args...)#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;/* Initial register settings for UPA1021 sensor */static unsigned char upa1021_i2c_regs[] =       {0xA8,0x19,0x07,0x06,0xF5,0x18,0xe4,0x3C,0x02,0x80,0x80,0x40,0x80,0x00,0x67,0x01,        0x00,0x00,0x14,0x20,0x48,0x58,0x07,0x27,0x27,0x37,0x05,0x39,0x1F,0xF3,0x31,0x4F,        0xD3,0x20,0x01,0x01,0x00,0xEa,0x08,0x01,0x00,0x00,0x00,0x00};/* Initial register settings for UPA1022 sensor */static unsigned char upa1022_i2c_regs[] = {/*00*/0x68, /*01*/0x19, /*02*/0x07, /*03*/0x0e, /*04*/0xf2, /*05*/0x18, /*06*/0xff, /*07*/0x6b, /*08*/0x42, /*09*/0x80, /*0a*/0x80, /*0b*/0x20, /*0c*/0x80, /*0d*/0x00, /*0e*/0xe6, /*0f*/0x00,/*10*/0x00, /*11*/0x00, /*12*/0x14, /*13*/0x10, /*14*/0x4d, /*15*/0x5d, /*16*/0x08, /*17*/0x28,/*18*/0x28, /*19*/0x38, /*1a*/0x06, /*1b*/0x3a, /*1c*/0x1f, /*1d*/0xf3, /*1e*/0x31, /*1f*/0x6e,/*20*/0xf2, /*21*/0x20, /*22*/0x01, /*23*/0x01, /*24*/0x00, /*25*/0xe4, /*26*/0x02, /*27*/0x01,/*28*/0x1d, /*29*/0x4c, /*2a*/0xae, /*2b*/0x13, /*2c*/0x00, /*2d*/0x00};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>");/* Functions defined in h3600_backpaq_camera__algo.c */void decimate( struct frame *frame );unsigned long write_vga( struct frame *frame, unsigned char *buf, 			 int streaming, int flipped, int palette );unsigned long write_qvga( struct frame *frame, unsigned char *buf, 			  int streaming, int flipped, int palette );unsigned long write_cif( struct frame *frame, unsigned char *buf, 			 int streaming, int flipped, int palette );unsigned long write_qcif( struct frame *frame, unsigned char *buf, 			  int streaming, int flipped, int palette );/******************************* *  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);	if (!cam->frame_buf)

⌨️ 快捷键说明

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