?? cam_interface1.c
字號:
divisor = 2; //CCIR-422
else
divisor = 4; //CCIR-420
//constant for calculating preview dma address
if(Cam_Dev.p_format == CAM_RGB24B)
multiplier = 4;
else
multiplier = 2;
if(Cam_Dev.WinHorOffset == 0 && Cam_Dev.WinVerOffset == 0)
WinOfsEn = 0;
else
WinOfsEn = 1;
SrcWidth = CAM_SRC_HSIZE - Cam_Dev.WinHorOffset*2;
SrcHeight = CAM_SRC_VSIZE - Cam_Dev.WinVerOffset*2;
if(SrcWidth >= Cam_Dev.CoDstWidth) ScaleUp_H_Co=0; //down
else ScaleUp_H_Co=1; //up
if(SrcHeight >= Cam_Dev.CoDstHeight) ScaleUp_V_Co=0;
else ScaleUp_V_Co=1;
if(SrcWidth >= Cam_Dev.PrDstWidth) ScaleUp_H_Pr=0; //down
else ScaleUp_H_Pr=1; //up
if(SrcHeight >= Cam_Dev.PrDstHeight) ScaleUp_V_Pr=0; // edited 040225
else ScaleUp_V_Pr=1;
////////////////// common control setting
Cam_Dev.regs->global_control = (1<<29)|(1<<26)|(0<<27); // inverse PCLK, test pattern
Cam_Dev.regs->window_offset = (1<<30)|(0xf<<12); // clear overflow
Cam_Dev.regs->window_offset = 0;
Cam_Dev.regs->window_offset = (WinOfsEn<<31)|(Cam_Dev.WinHorOffset<<16)|(Cam_Dev.WinVerOffset);
Cam_Dev.regs->source_format = (1<<30)|(0<<29)|(CAM_SRC_HSIZE<<16)|(CAM_ORDER_YCBYCR<<14)|(CAM_SRC_VSIZE);
if (Cam_Dev.CodecMode) {
////////////////// codec dma setting
CbFrameInterval = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight;
CrFrameInterval = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight / divisor;
if (Cam_Dev.c_pp_num == 4)
{
int i;
YFrameInterval = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight + 2 * Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight / divisor;
for (i = 0; i < 4; i++)
{
Cam_Dev.regs->codec.Y.sa[i] = CoFrameBuffer + i * YFrameInterval;
Cam_Dev.regs->codec.Cb.sa[i] = Cam_Dev.regs->codec.Y.sa[i] + CbFrameInterval;
Cam_Dev.regs->codec.Cr.sa[i] = Cam_Dev.regs->codec.Cb.sa[i] + CrFrameInterval;
}
}
else
{
int i;
for (i = 0; i < 4; i++)
{
Cam_Dev.regs->codec.Y.sa[i] = CoFrameBuffer;
Cam_Dev.regs->codec.Cb.sa[i] = CoFrameBuffer + CbFrameInterval;
Cam_Dev.regs->codec.Cr.sa[i] = Cam_Dev.regs->codec.Cb.sa[i] + CrFrameInterval;
}
}
////////////////// codec target regs setting
Cam_Dev.regs->codec.target_format = (CAM_CODEC_IN_422<<31)|(CAM_CODEC_OUTPUT<<30)|(Cam_Dev.CoDstWidth<<16)|(CAM_FLIP_NORMAL<<14)|(Cam_Dev.CoDstHeight);
CalculateBurstSize(Cam_Dev.CoDstWidth, &MainBurstSizeY, &RemainedBurstSizeY);
CalculateBurstSize(Cam_Dev.CoDstWidth / 2, &MainBurstSizeC, &RemainedBurstSizeC);
Cam_Dev.regs->codec.dma_control = (MainBurstSizeY<<19)|(RemainedBurstSizeY<<14)|(MainBurstSizeC<<9)|(RemainedBurstSizeC<<4);
////////////////// codec scaler regs setting
CalculatePrescalerRatioShift(SrcWidth, Cam_Dev.CoDstWidth, &PreHorRatio, &H_Shift);
CalculatePrescalerRatioShift(SrcHeight, Cam_Dev.CoDstHeight, &PreVerRatio, &V_Shift);
MainHorRatio=(SrcWidth<<8)/(Cam_Dev.CoDstWidth<<H_Shift);
MainVerRatio=(SrcHeight<<8)/(Cam_Dev.CoDstHeight<<V_Shift);
Cam_Dev.regs->codec.scaler.pre_ratio = ((10-H_Shift-V_Shift)<<28)|(PreHorRatio<<16)|(PreVerRatio);
Cam_Dev.regs->codec.scaler.pre_destination = ((SrcWidth/PreHorRatio)<<16)|(SrcHeight/PreVerRatio);
Cam_Dev.regs->codec.scaler.main_control=(CAM_SCALER_BYPASS_OFF<<31)|(ScaleUp_H_Co<<30)|(ScaleUp_V_Co<<29)|(MainHorRatio<<16)|(MainVerRatio);
Cam_Dev.regs->codec.scaler.target_area = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight;
} if (Cam_Dev.PrevMode) {
///////////////// preview dma regs setting
RGBFrameInterval = Cam_Dev.PrDstWidth * Cam_Dev.PrDstHeight * multiplier;
if (Cam_Dev.p_pp_num == 4) // codec view mode
{
int i;
for (i = 0; i < 4; i++)
Cam_Dev.regs->prev.RGB.sa[i] = PrFrameBuffer + i * RGBFrameInterval;
}
else // direct preview mode
{
int i;
for (i = 0; i < 4; i++)
Cam_Dev.regs->prev.RGB.sa[i] = PrFrameBuffer; //LCDFRAMEBUFFER
}
////////////////// preview target regs setting
Cam_Dev.regs->prev.target_format = (Cam_Dev.PrDstWidth<<16)|(CAM_FLIP_NORMAL<<14)|(Cam_Dev.PrDstHeight);
if (Cam_Dev.p_format == CAM_RGB24B)
CalculateBurstSize(Cam_Dev.PrDstWidth*4, &MainBurstSizeRGB, &RemainedBurstSizeRGB);
else // RGB16B
CalculateBurstSize(Cam_Dev.PrDstWidth*2, &MainBurstSizeRGB, &RemainedBurstSizeRGB);
Cam_Dev.regs->prev.dma_control = (MainBurstSizeRGB<<19)|(RemainedBurstSizeRGB<<14);
///////////////// preview scaler regs setting
CalculatePrescalerRatioShift(SrcWidth, Cam_Dev.PrDstWidth, &PreHorRatio, &H_Shift);
CalculatePrescalerRatioShift(SrcHeight, Cam_Dev.PrDstHeight, &PreVerRatio, &V_Shift);
MainHorRatio=(SrcWidth<<8)/(Cam_Dev.PrDstWidth<<H_Shift);
MainVerRatio=(SrcHeight<<8)/(Cam_Dev.PrDstHeight<<V_Shift);
Cam_Dev.regs->prev.scaler.pre_ratio = ((10-H_Shift-V_Shift)<<28)|(PreHorRatio<<16)|(PreVerRatio);
Cam_Dev.regs->prev.scaler.pre_destination = ((SrcWidth/PreHorRatio)<<16)|(SrcHeight/PreVerRatio);
Cam_Dev.regs->prev.scaler.main_control = (1<<31)|(CAM_PVIEW_OUTPUT<<30)|(ScaleUp_H_Pr<<29)|(ScaleUp_V_Pr<<28)|(MainHorRatio<<16)|(MainVerRatio);
Cam_Dev.regs->prev.scaler.target_area = Cam_Dev.PrDstWidth * Cam_Dev.PrDstHeight; }
return 0;
}
static int cam_dma_malloc()
{
unsigned int t_size;
unsigned int daon = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight;
if(Cam_Dev.CodecMode)
{
if (Cam_Dev.c_format == CAM_CCIR420)
{
t_size = daon * 3 / 2 ;
}
else
{
t_size = daon * 2; /* CAMIF_OUT_YCBCR422 */
t_size = t_size * Cam_Dev.c_pp_num;
}
Cam_Dev.cbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, t_size, &Cam_Dev.c_phyaddr);
if (!Cam_Dev.cbuf) {
printk("CAMERA:Failed to request YCBCR MEM\n");
return -ENOMEM;
} printk("vaddr=0x%x,paddr=0x%x\n", Cam_Dev.cbuf, Cam_Dev.c_phyaddr);
memset(Cam_Dev.cbuf, 0, t_size);
Cam_Dev.cbuf_size = t_size;
}
if (Cam_Dev.PrevMode)
{
if (Cam_Dev.p_format == CAM_RGB16B)
t_size = daon * 2; /* 4byte per two pixel*/
else
{
t_size = daon * 4; /* 4byte per one pixel */
}
t_size = t_size * Cam_Dev.p_pp_num;
Cam_Dev.pbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, t_size, &Cam_Dev.p_phyaddr);
if (!Cam_Dev.pbuf) {
printk(KERN_ERR"CAMERA:Failed to request RGB MEM\n");
return -ENOMEM;
}
memset(Cam_Dev.pbuf, 0, t_size);
Cam_Dev.pbuf_size = t_size;
}
return 0;
}
static int cam_dma_free()
{
if(Cam_Dev.CodecMode)
{
consistent_free(Cam_Dev.cbuf, Cam_Dev.cbuf_size, Cam_Dev.c_phyaddr);
Cam_Dev.cbuf = NULL;
}
if (Cam_Dev.PrevMode)
{
consistent_free(Cam_Dev.pbuf, Cam_Dev.pbuf_size, Cam_Dev.p_phyaddr);
Cam_Dev.pbuf = NULL;
}
return 0;
}
/* Image Capture Enable Regiser */
#define CAMIF_CAP_ON (1<<31)
#define CAMIF_CAP_CODEC_ON (1<<30)
#define CAMIF_CAP_PREVIEW_ON (1<<29)int camif_capture_start(){ u32 n_cmd = 0; /* Next Command */ int i; switch(Cam_Dev.exec) { case CAMIF_BOTH_DMA_ON: Cam_Dev.regs->codec.scaler.main_control |= (1<<15); Cam_Dev.regs->prev.scaler.main_control |= (1<<15); n_cmd = CAMIF_CAP_PREVIEW_ON|CAMIF_CAP_CODEC_ON; break; case CAMIF_DMA_ON: Cam_Dev.status = PREPARE; Cam_Dev.regs->source_format |= (1<<31); Cam_Dev.regs->global_control |= (1<<31); for (i=0;i<=100000000;i++); Cam_Dev.regs->global_control &= ~(1<<31); cam_interface_init(); Cam_Dev.regs->source_format &= ~(1<<31); if (Cam_Dev.CodecMode) { Cam_Dev.regs->codec.scaler.main_control |= (1<<15); n_cmd = CAMIF_CAP_CODEC_ON; }else { Cam_Dev.regs->prev.scaler.main_control |= (1<<15); n_cmd = CAMIF_CAP_PREVIEW_ON; } /* wait until Sync Time expires */ /* First settting, to wait VSYNC fall */ /* By VESA spec,in 640x480 @60Hz MAX Delay Time is around 64us which "while" has.*/ while(fld_v(Cam_Dev.regs->codec.status, 28, 1)); break; default: break; } Cam_Dev.regs->window_offset |= (1<<30); Cam_Dev.regs->window_offset |= (0xf<<12); Cam_Dev.regs->window_offset &= ~(1<<30); Cam_Dev.regs->window_offset &= ~(0xf<<12); Cam_Dev.regs->image_capture = n_cmd|CAMIF_CAP_ON; return 0;}int camif_capture_stop()
{
u32 n_cmd = Cam_Dev.regs->image_capture; /* Next Command */
switch(Cam_Dev.exec) {
case CAMIF_BOTH_DMA_OFF:
Cam_Dev.regs->codec.scaler.main_control &= ~(1<<15); Cam_Dev.regs->prev.scaler.main_control &= ~(1<<15);
n_cmd = 0;
break;
case CAMIF_DMA_OFF_L_IRQ: /* fall thru */
case CAMIF_DMA_OFF:
if (Cam_Dev.CodecMode) {
Cam_Dev.regs->codec.scaler.main_control &= ~(1<<15);
n_cmd &= ~CAMIF_CAP_CODEC_ON;
if (!(n_cmd & CAMIF_CAP_PREVIEW_ON))
n_cmd = 0;
}else {
Cam_Dev.regs->prev.scaler.main_control &= ~(1<<15);
n_cmd &= ~CAMIF_CAP_PREVIEW_ON;
if (!(n_cmd & CAMIF_CAP_CODEC_ON))
n_cmd = 0;
}
break;
default:
printk("Unexpected \n");
}
Cam_Dev.regs->image_capture = n_cmd;
if(Cam_Dev.exec == CAMIF_DMA_OFF_L_IRQ) { /* Last IRQ */
if (Cam_Dev.CodecMode)
Cam_Dev.regs->codec.dma_control |= (1<<2);
else
Cam_Dev.regs->prev.dma_control |= (1<<2);
}
return 0;
}/* LastIRQEn is autoclear */
void camif_last_irq_en()
{
if(Cam_Dev.exec == CAMIF_BOTH_DMA_ON) {
Cam_Dev.regs->codec.dma_control |= (1<<2);
Cam_Dev.regs->prev.dma_control |= (1<<2);
}
else {
if (Cam_Dev.CodecMode)
Cam_Dev.regs->codec.dma_control |= (1<<2);
else
Cam_Dev.regs->prev.dma_control |= (1<<2);
}
}/////////////////////////////////////////////clock setting////////////////////////////void ChangeUPllValue(int mdiv,int pdiv,int sdiv)
{
UPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv;
}void SetCAMClockDivider(int divn)
{
CAMDIVN = (CAMDIVN & ~(0xf))|(1<<4)|(divn); // CAMCLK is divided..
}int camif_clock_init()
{
CLKCON |= CLKCON_CAMIF;
ChangeUPllValue(60, 4, 1);
CLKDIVN |= DIVN_UPLL; /* For USB */
SetCAMClockDivider(1);
return 0;
}///////////////////////////////////////////GPIO setting///////////////////////////////static int camif_gpio_init(void)
{
set_gpio_ctrl(GPIO_CAMDATA0);
set_gpio_ctrl(GPIO_CAMDATA1);
set_gpio_ctrl(GPIO_CAMDATA2);
set_gpio_ctrl(GPIO_CAMDATA3);
set_gpio_ctrl(GPIO_CAMDATA4);
set_gpio_ctrl(GPIO_CAMDATA5);
set_gpio_ctrl(GPIO_CAMDATA6);
set_gpio_ctrl(GPIO_CAMDATA7);
set_gpio_ctrl(GPIO_CAMPCLKIN);
set_gpio_ctrl(GPIO_CAMVSYNC);
set_gpio_ctrl(GPIO_CAMHREF);
set_gpio_ctrl(GPIO_CAMPCLKOUT);
set_gpio_ctrl(GPIO_CAMRESET);
return 0;
}/////////////////////////////////////////////file operation///////////////////////////ssize_t cam_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){ printk("camera reading...(0x%x)\n", Cam_Dev.cbuf); Cam_Dev.exec = CAMIF_DMA_ON; camif_capture_start(); interruptible_sleep_on(&Cam_Dev.wq); if (Cam_Dev.status==FINISH) printk("Capture completed!\n"); Cam_Dev.exec = CAMIF_DMA_OFF; camif_capture_stop(); if (copy_to_user(buf, Cam_Dev.cbuf, count)) return -EFAULT; printk("camera read completed!\n"); return count;}///////////////////////////////////////////module initialization///////////////////////////
int init_module(void)
{
int result,i;
result = register_chrdev(Cam_Dev.major, "video", &cam_fops); if (result<0) { printk("camif: can't get major %d\n",CAM_MAJOR); return result; } if (Cam_Dev.major==0) Cam_Dev.major = result; camif_gpio_init(); camif_clock_init();
Cam_Dev.regs = (cam_interface_regs *)io_p2v(CAM_BASE_ADD);
sema_init(&Cam_Dev.sem, 1);
init_waitqueue_head(&Cam_Dev.wq);
cam_request_irq();
cam_dma_malloc();
cam_interface_init(); printk("Camera interface initialization completed!\n"); /* printk("checking register value(0x%x):\n",Cam_Dev.regs); printk("0x%x:0x%x\n",&(Cam_Dev.regs->source_format), Cam_Dev.regs->source_format); printk("0x%x:0x%x\n",&(Cam_Dev.regs->window_offset), Cam_Dev.regs->window_offset); printk("0x%x:0x%x\n",&(Cam_Dev.regs->global_control), Cam_Dev.regs->global_control); for (i=0;i<4;i++) printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.Y.sa[i]), Cam_Dev.regs->codec.Y.sa[i]); for (i=0;i<4;i++) printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.Cb.sa[i]), Cam_Dev.regs->codec.Cb.sa[i]); for (i=0;i<4;i++) printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.Cr.sa[i]), Cam_Dev.regs->codec.Cr.sa[i]); printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.target_format), Cam_Dev.regs->codec.target_format); printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.dma_control), Cam_Dev.regs->codec.dma_control); printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.scaler.main_control), Cam_Dev.regs->codec.scaler.main_control); printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.status), Cam_Dev.regs->codec.status); printk("0x%x:0x%x\n",&(Cam_Dev.regs->image_capture), Cam_Dev.regs->image_capture); */
return 0;
}
void cleanup_module(void)
{
//iounmap(Cam_Dev.regs);
cam_release_irq();
cam_dma_free(); unregister_chrdev(Cam_Dev.major, "video");
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -