?? cam_interface1.c
字號:
#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 + -