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

📄 cam_interface1.c

📁 这是一个用c语言编写的摄像头驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#define MODULE
#define __KERNEL__

#include <linux/module.h>
#include <linux/kernel.h>#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/dma.h>#include <asm/io.h>
#include <linux/fs.h>
#include <linux/sched.h>

#include <linux/types.h>
#include <linux/errno.h>

#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <asm/arch/S3C2440.h>#include <asm/arch/irqs.h>
#include "cam_interface.h"
MODULE_LICENSE("GPL");MODULE_AUTHOR("Cuijinbird");

#define CAM_MAJOR 0

#define CAM_BASE_ADD	0x4F000000	//Camera Interface.  Edited for 2440A#define CISRCFMT            __REG(CAM_BASE_ADD+0x00) // RW Input Source Format
#define CIWDOFST            __REG(CAM_BASE_ADD+0x04) // Window offset register
#define CIGCTRL             __REG(CAM_BASE_ADD+0x08) // Global control register
#define CICOYSA0            __REG(CAM_BASE_ADD+0x18) // Y 1 st frame start address 
#define CICOYSA1            __REG(CAM_BASE_ADD+0x1C) // Y 2 nd frame start address 
#define CICOYSA2            __REG(CAM_BASE_ADD+0x20) // Y 3 rd frame start address 
#define CICOYSA3            __REG(CAM_BASE_ADD+0x24) // Y 4 th frame start address 
#define CICOCBSA0           __REG(CAM_BASE_ADD+0x28) // Cb 1 st frame start address 
#define CICOCBSA1           __REG(CAM_BASE_ADD+0x2C) // Cb 2 nd frame start address 
#define CICOCBSA2           __REG(CAM_BASE_ADD+0x30) // Cb 3 rd frame start address 
#define CICOCBSA3           __REG(CAM_BASE_ADD+0x34) // Cb 4 th frame start address 
#define CICOCRSA0           __REG(CAM_BASE_ADD+0x38) // Cr 1 st frame start address 
#define CICOCRSA1           __REG(CAM_BASE_ADD+0x3C) // Cr 2 nd frame start address 
#define CICOCRSA2           __REG(CAM_BASE_ADD+0x40) // Cr 3 rd frame start address 
#define CICOCRSA3           __REG(CAM_BASE_ADD+0x44) // Cr 4 th frame start address 
#define CICOTRGFMT          __REG(CAM_BASE_ADD+0x48) // Target image format of codec
#define CICOCTRL            __REG(CAM_BASE_ADD+0x4C) // Codec DMA control related
#define CICOSCPRERATIO      __REG(CAM_BASE_ADD+0x50) // Codec pre-scaler ratio control
#define CICOSCPREDST        __REG(CAM_BASE_ADD+0x54) // Codec pre-scaler destination
#define CICOSCCTRL          __REG(CAM_BASE_ADD+0x58) // Codec main-scaler control
#define CICOTAREA           __REG(CAM_BASE_ADD+0x5C) // Codec pre-scaler destination
#define CICOSTATUS          __REG(CAM_BASE_ADD+0x64) // Codec path status
#define CIPRCLRSA0          __REG(CAM_BASE_ADD+0x6C) // RGB 1 st frame start address 
#define CIPRCLRSA1          __REG(CAM_BASE_ADD+0x70) // RGB 2 nd frame start address 
#define CIPRCLRSA2          __REG(CAM_BASE_ADD+0x74) // RGB 3 rd frame start address 
#define CIPRCLRSA3          __REG(CAM_BASE_ADD+0x78) // RGB 4 th frame start address 
#define CIPRTRGFMT          __REG(CAM_BASE_ADD+0x7C) // Target image format of preview
#define CIPRCTRL            __REG(CAM_BASE_ADD+0x80) // Preview DMA control related
#define CIPRSCPRERATIO      __REG(CAM_BASE_ADD+0x84) // Preview pre-scaler ratio control
#define CIPRSCPREDST        __REG(CAM_BASE_ADD+0x88) // Preview pre-scaler destination
#define CIPRSCCTRL          __REG(CAM_BASE_ADD+0x8C) // Preview main-scaler control
#define CIPRTAREA           __REG(CAM_BASE_ADD+0x90) // Preview pre-scaler destination
#define CIPRSTATUS          __REG(CAM_BASE_ADD+0x98) // Preview path status
#define CIIMGCPT            __REG(CAM_BASE_ADD+0xA0) // Image capture enable command#define CICOYSA(__x)        __REG(CAM_BASE_ADD+0x18 + (__x)*4 ) 
#define CICOCBSA(__x)       __REG(CAM_BASE_ADD+0x28 + (__x)*4 )
#define CICOCRSA(__x)       __REG(CAM_BASE_ADD+0x38 + (__x)*4 ) 
#define CIPRCLRSA(__x)      __REG(CAM_BASE_ADD+0x6C + (__x)*4 )

typedef struct {
	unsigned int sa[4]; //dma start address register. The 4 elements denotes the 4 pingpong memories and 4 frames.
} cam_dma_addr;

typedef struct {	
	unsigned int pre_ratio;
	unsigned int pre_destination;
	unsigned int main_control;
	unsigned int target_area;
} cam_scaler_regs;

typedef struct {
	cam_dma_addr Y;
	cam_dma_addr Cb;
	cam_dma_addr Cr;
	unsigned int target_format;
	unsigned int dma_control;
	cam_scaler_regs scaler;	unsigned int empty; //empty address
	unsigned int status;
} cam_codec;

typedef struct {
	cam_dma_addr RGB;
	unsigned int target_format;
	unsigned int dma_control;
	cam_scaler_regs scaler;	unsigned int empty;  //empty address
	unsigned int status;
} cam_prev;

typedef struct {
	unsigned int source_format;
	unsigned int window_offset;
	unsigned int global_control;	unsigned int empty1[3];   //empty address
	cam_codec codec;	unsigned int empty2;	//empty address
	cam_prev prev;	unsigned int empty3;    //empty address
	unsigned int image_capture;
} cam_interface_regs;

/* Parameters
CoDstWidth: Destination Width of Codec Path
CoDstHeight: Destination Height of Codec Path
PrDstWidth: Destination Width of Preview Path
PrDstHeight: Destination Height of Preview Path
WinHorOffset: Size of Window Offset for Horizontal Direction
WinVerOffset: Size of Window Offset for Vertical Direction
CoFrameBuffer: Start Address for Codec DMA
PrFrameBuffer: Start Address for Previe DMA
*/enum camif_capturing {
        CAMIF_BOTH_DMA_ON  = 0x10,
	CAMIF_DMA_ON   	   = 0x8,
	CAMIF_BOTH_DMA_OFF = 0x2,
	CAMIF_DMA_OFF      = 0x1,
	/*------------------------*/
	CAMIF_DMA_OFF_L_IRQ= 0x20,
};
enum cap_status {	PREPARE = 0x1,	CAPTURING = 0x2,	FINISH =0x3,};

typedef struct {
	char name[6];	int major;
	
	cam_interface_regs *regs;
	
	unsigned int CodecMode, PrevMode;
	
	char *cbuf;
	char *pbuf;
	dma_addr_t c_phyaddr, p_phyaddr;
	unsigned int cbuf_size, pbuf_size;
	
	int c_irq, p_irq;
	
	unsigned int c_format, p_format;
	unsigned int c_pp_num, p_pp_num;

	unsigned int camCodecStatus, camPrevStatus;
	unsigned int CoDstWidth, CoDstHeight;
	unsigned int PrDstWidth, PrDstHeight;
	unsigned int WinHorOffset, WinVerOffset;
	enum camif_capturing exec;	enum cap_status status;
	unsigned int now_frame_no;
	
	struct semaphore sem;
	wait_queue_head_t wq;

} cam_dev;

ssize_t cam_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
struct file_operations cam_fops = {
	read:	cam_read,//cam_read,
	ioctl:	NULL,//cam_ioctl,
	open:	NULL,//cam_open,
	release:NULL,//cam_release,
};

cam_dev Cam_Dev = {
	name:				"video",	major:				CAM_MAJOR,
	cbuf:				NULL,
	pbuf:				NULL,
	c_phyaddr:			CAM_FRAMEBUFFER_C,
	p_phyaddr:			CAM_FRAMEBUFFER_P,
	CodecMode:			1,
	PrevMode:			0,
	c_irq:				IRQ_CAM_C,	p_irq:				IRQ_CAM_P,
	c_format:			CAM_CCIR422,
	p_format:			CAM_RGB24B,
	c_pp_num:			1,
	p_pp_num:			1,
	CoDstWidth:			720,
	CoDstHeight:		540,
	PrDstWidth:			720,
	PrDstHeight:		540,
	WinHorOffset:		0,
	WinVerOffset:		0,
	now_frame_no:		0,
};

/********************************************************
 cam_codec_irq - camara interface codec interrupt handler
 
 Description:	
 - irq : interrupt number
 - dev : cam_dev structure
*/
static void cam_codec_irq(int irq, void *dev_id, struct pt_regs *regs)
{	cam_dev *dev = (cam_dev *)dev_id;
	unsigned int ov = fld_v(dev->regs->codec.status, 29, 3);
	if (ov)
	{
		printk("CODEC: FIFO error(0x%08x) and corrected\n",ov);
		dev->regs->window_offset |= (1<<30) | (1<<15) | (1<<14);
		dev->regs->window_offset &= ~((1<<30) | (1<<15) | (1<<14));
	}
	dev->now_frame_no = (fld_v(dev->regs->codec.status, 26, 2) + 2) % 4;	if (dev->status == PREPARE)	{		dev->status = CAPTURING;		printk("Start capturing...\n");		return ;	}
	if (dev->status == CAPTURING)	{		wake_up_interruptible(&dev->wq);		dev->status = FINISH;	}
}

/********************************************************
 cam_prev_irq - camara interface preview interrupt handler
 
 Description:	
 - irq : interrupt number
 - dev : cam_dev structure
*/
static void cam_prev_irq(int irq, void *dev_id, struct pt_regs *regs)
{	cam_dev *dev = (cam_dev *)dev_id;
	unsigned int ov = fld_v(dev->regs->prev.status, 30, 2);
	if (ov)
	{
		printk("PREVIEW: FIFO error(0x%08x) and corrected\n",ov);
		dev->regs->window_offset |= (1<<13) | (1<<12);
		dev->regs->window_offset &= ~((1<<13) | (1<<12));
	}
	dev->now_frame_no = (fld_v(dev->regs->prev.status, 26, 2) + 2) % 4;
	wake_up_interruptible(&dev->wq);
}

static void cam_release_irq()
{
	if (Cam_Dev.CodecMode)	{		disable_irq(Cam_Dev.c_irq);
		free_irq(Cam_Dev.c_irq, (void *)&Cam_Dev);	}	if (Cam_Dev.PrevMode)	{		disable_irq(Cam_Dev.p_irq);
		free_irq(Cam_Dev.p_irq, (void *)&Cam_Dev);	}
}

/********************************************************
 cam_irq_request - camara interface interrupt register function
					request the system interrupt line number
*/
static int cam_request_irq()
{
	int ret = 0;
	if (Cam_Dev.CodecMode) 
	{
		if ((ret = request_irq(Cam_Dev.c_irq, cam_codec_irq, SA_INTERRUPT, Cam_Dev.name, &Cam_Dev))) {
			printk("request_irq(CAM_C) failed.\n");			return ret;
		}
	}
	if (Cam_Dev.PrevMode)
	{
		if ((ret = request_irq(Cam_Dev.p_irq, cam_prev_irq, SA_INTERRUPT, Cam_Dev.name, &Cam_Dev))) {
			printk("request_irq(CAM_P) failed.\n");			return ret;
		}
	}
	return 0;
}

/********************************************************
 CalculateBurstSize - Calculate the busrt lengths
 
 Description:	
 - dstHSize: the number of the byte of H Size.
 
*/
void CalculateBurstSize(unsigned int hSize, unsigned int *mainBurstSize, unsigned int *remainedBurstSize)
{
	unsigned int tmp;	
	tmp=(hSize/4)%16;
	switch(tmp) {
		case 0:
			*mainBurstSize=16;
			*remainedBurstSize=16;
			break;
		case 4:
			*mainBurstSize=16;
			*remainedBurstSize=4;
			break;
		case 8:
			*mainBurstSize=16;
			*remainedBurstSize=8;
			break;
		default: 
			tmp=(hSize/4)%8;
			switch(tmp) {
				case 0:
					*mainBurstSize=8;
					*remainedBurstSize=8;
					break;
				case 4:
					*mainBurstSize=8;
					*remainedBurstSize=4;
				default:
					*mainBurstSize=4;
					tmp=(hSize/4)%4;
					*remainedBurstSize= (tmp) ? tmp: 4;
					break;
			}
			break;
	}		    	    		
}

/********************************************************
 CalculatePrescalerRatioShift - none
 
 Description:	
 - none
 
*/
void CalculatePrescalerRatioShift(unsigned int SrcSize, unsigned int DstSize, unsigned int *ratio,unsigned int *shift)
{
	if(SrcSize>=64*DstSize) {
		while(1);
	}
	else if(SrcSize>=32*DstSize) {
		*ratio=32;
		*shift=5;
	}
	else if(SrcSize>=16*DstSize) {
		*ratio=16;
		*shift=4;
	}
	else if(SrcSize>=8*DstSize) {
		*ratio=8;
		*shift=3;
	}
	else if(SrcSize>=4*DstSize) {
		*ratio=4;
		*shift=2;
	}
	else if(SrcSize>=2*DstSize) {
		*ratio=2;
		*shift=1;
	}
	else {
		*ratio=1;
		*shift=0;
	}    	
}

/********************************************************
 cam_interface_init - all camera interface registers initialize
*/
int cam_interface_init(void)
{
	unsigned int WinOfsEn;
	unsigned int divisor, multiplier;
	unsigned int MainBurstSizeY, RemainedBurstSizeY, MainBurstSizeC, RemainedBurstSizeC, MainBurstSizeRGB, RemainedBurstSizeRGB;
	unsigned int H_Shift, V_Shift, PreHorRatio, PreVerRatio, MainHorRatio, MainVerRatio;
	unsigned int SrcWidth, SrcHeight;
	unsigned int ScaleUp_H_Co, ScaleUp_V_Co, ScaleUp_H_Pr, ScaleUp_V_Pr;
	unsigned int YFrameInterval, CbFrameInterval, CrFrameInterval, RGBFrameInterval;
	
	unsigned int CoFrameBuffer = Cam_Dev.c_phyaddr, PrFrameBuffer = Cam_Dev.p_phyaddr;

	//constant for calculating codec dma address
	if(Cam_Dev.c_format == CAM_CCIR422)

⌨️ 快捷键说明

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