📄 camif.c
字号:
/* * Copyright (C) 2004 Samsung Electronics * SW.LEE <hitchcar@samsung.com> * * This file is subject to the terms and conditions of the GNU General Public * License 2. See the file COPYING in the main directory of this archive * for more details. */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/irq.h>//#include <linux/tqueue.h> /* Helios 2.4 侩 Helios 2.6俊绰 绝栏骨肺 力芭窃 by lovejin *///#include <linux/locks.h> /* Helios 2.4 侩 Helios 2.6俊绰 绝栏骨肺 力芭窃 by lovejin */#include <linux/completion.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/miscdevice.h>#include <linux/wait.h>#include <linux/miscdevice.h>#include <asm/io.h>#include <asm/semaphore.h>#include <asm/hardware.h>#include <asm/uaccess.h>//#include <asm/arch/s3c2410.h>//#include <asm/arch/s3c2440.h> /* Helios 2.4 侩 */#include <asm/arch/map.h> /* Helios 2.6 侩 by lovejin*/#include <asm/arch/bitfield.h> /* Helios 2.6侩, Fld() 鞍篮 概农肺 锭巩俊 by lovejin *///#define SW_DEBUG#include "heliosCam.h" // by lovejin#include "camif.h"#include "videodev.h"#include "miscdevice.h"/* 叼滚彪 皋矫瘤侩 by lovejin *///#define DEBUG0(args...) printk(args)//#define DEBUG1(args...) printk(args) //#define DEBUG2(args...) printk(args) #define DEBUG0(args...)#define DEBUG1(args...)#define DEBUG2(args...)static int camif_dma_burst(camif_cfg_t *);static int camif_scaler(camif_cfg_t *);static const char *camif_version = "$Id: camif.c,v 1.10 2004/06/04 04:24:14 swlee Exp $"; /* For SXGA Image */#define RESERVE_MEM 4*1024*1024#define YUV_MEM 2*1024*1024#define RGB_MEM (RESERVE_MEM - YUV_MEM)#define MEM_SIZE 128*1024*1024static int camif_malloc(camif_cfg_t *cfg){ unsigned int t_size; unsigned int daon = cfg->target_x *cfg->target_y; DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin if(cfg->dma_type & CAMIF_CODEC) { if (cfg->fmt & CAMIF_OUT_YCBCR420) { t_size = daon * 3 / 2 ; } else { t_size = daon * 2; /* CAMIF_OUT_YCBCR422 */ } t_size = t_size *cfg->pp_num;#ifndef SAMSUNG_SXGA_CAM// cfg->pp_virt_buf = consistent_alloc(GFP_KERNEL, t_size, &cfg->pp_phys_buf); /* Helios 2.4 侩 */// cfg->pp_virt_buf = dma_alloc_coherent(NULL, t_size, &cfg->pp_phys_buf, GFP_KERNEL); /* Helios 2.6 侩 by lovejin*/#if 1 // helios printk(KERN_INFO "Reserving High RAM Addresses \n"); cfg->pp_phys_buf = PHYS_OFFSET + (MEM_SIZE - RESERVE_MEM); cfg->pp_virt_buf = ioremap_nocache(cfg->pp_phys_buf,YUV_MEM);#endif#else printk(KERN_INFO "Reserving High RAM Addresses \n"); cfg->pp_phys_buf = PHYS_OFFSET + (MEM_SIZE - RESERVE_MEM); cfg->pp_virt_buf = ioremap_nocache(cfg->pp_phys_buf,YUV_MEM);#endif if ( !cfg->pp_virt_buf ) { printk(KERN_ERR"CAMERA:Failed to request YCBCR MEM\n"); DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return -ENOMEM; } memset(cfg->pp_virt_buf, 0, t_size); cfg->pp_totalsize = t_size; DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return 0; } if ( cfg->dma_type & CAMIF_PREVIEW ) { if (cfg->fmt & CAMIF_RGB16) t_size = daon * 2; /* 4byte per two pixel*/ else { assert(cfg->fmt & CAMIF_RGB24); t_size = daon * 4; /* 4byte per one pixel */ } t_size = t_size * cfg->pp_num; //printk("debug>> memory size %d(0x%08x)\n", t_size, t_size);#ifndef SAMSUNG_SXGA_CAM// cfg->pp_virt_buf = consistent_alloc(GFP_KERNEL, t_size, &cfg->pp_phys_buf); /* Helios 2.4 侩 */// cfg->pp_virt_buf = dma_alloc_coherent(NULL, t_size, &cfg->pp_phys_buf, GFP_KERNEL); /* Helios 2.6 侩 by lovejin*/#if 1 // helios printk(KERN_INFO "Reserving High RAM Addresses \n"); cfg->pp_phys_buf = PHYS_OFFSET + (MEM_SIZE - RESERVE_MEM ) + YUV_MEM; cfg->pp_virt_buf = ioremap_nocache(cfg->pp_phys_buf,RGB_MEM);#endif#else printk(KERN_INFO "Reserving High RAM Addresses \n"); cfg->pp_phys_buf = PHYS_OFFSET + (MEM_SIZE - RESERVE_MEM ) + YUV_MEM; cfg->pp_virt_buf = ioremap_nocache(cfg->pp_phys_buf,RGB_MEM);#endif if ( !cfg->pp_virt_buf ) { printk(KERN_ERR"CAMERA:Failed to request RGB MEM\n"); DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return -ENOMEM; } memset(cfg->pp_virt_buf, 0, t_size); cfg->pp_totalsize = t_size; DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return 0; } DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return 0; /* Never come. */}static int camif_demalloc(camif_cfg_t *cfg){ DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin#ifndef SAMSUNG_SXGA_CAM#if 0 // original by lovejin if ( cfg->pp_virt_buf ) {// consistent_free(cfg->pp_virt_buf,cfg->pp_totalsize,cfg->pp_phys_buf); /* Helios 2.6 侩 by lovejin */ dma_alloc_coherent(NULL, cfg->pp_totalsize, cfg->pp_virt_buf, cfg->pp_phys_buf); /* Helios 2.6 侩 by lovejin*/ cfg->pp_virt_buf = 0; }#endif#if 1 // helios by lovejin iounmap(cfg->pp_virt_buf); cfg->pp_virt_buf = 0;#endif#else iounmap(cfg->pp_virt_buf); cfg->pp_virt_buf = 0;#endif DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return 0;}/* * advise a person to use this func in ISR * index value indicates the next frame count to be used */int camif_g_frame_num(camif_cfg_t *cfg){ int index = 0; DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin if (cfg->dma_type & CAMIF_CODEC ) { index = FRAME_CNT(rCICOSTATUS); DPRINTK("CAMIF_CODEC frame %d \n", index); } else { assert(cfg->dma_type & CAMIF_PREVIEW ); index = FRAME_CNT(rCIPRSTATUS); DPRINTK("CAMIF_PREVIEW frame %d 0x%08X \n", index, CIPRSTATUS); } cfg->now_frame_num = (index + 2) % 4; /* When 4 PingPong */ DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return index; /* meaningless */}static int camif_pp_codec(camif_cfg_t *cfg){ u32 i, c_size; /* Cb,Cr size */ u32 one_p_size; u32 daon = cfg->target_x * cfg->target_y; DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin if (cfg->fmt & CAMIF_OUT_YCBCR420) { c_size = daon /4; } else { assert(cfg->fmt & CAMIF_OUT_YCBCR422); c_size = daon /2; } switch ( cfg->pp_num ) { case 1 : for ( i =0 ; i < 4; i=i+1) { cfg->img_buf[i].virt_y = cfg->pp_virt_buf; cfg->img_buf[i].phys_y = cfg->pp_phys_buf; cfg->img_buf[i].virt_cb = cfg->pp_virt_buf + daon; cfg->img_buf[i].phys_cb = cfg->pp_phys_buf + daon; cfg->img_buf[i].virt_cr = cfg->pp_virt_buf + daon + c_size; cfg->img_buf[i].phys_cr = cfg->pp_phys_buf + daon + c_size; rCICOYSA(i) = cfg->img_buf[i].phys_y; rCICOCBSA(i) = cfg->img_buf[i].phys_cb; rCICOCRSA(i) = cfg->img_buf[i].phys_cr; } break; case 2:#define TRY (( i%2 ) ? 1 :0) one_p_size = daon + 2*c_size; for (i = 0; i < 4 ; i++) { cfg->img_buf[i].virt_y = cfg->pp_virt_buf + TRY * one_p_size; cfg->img_buf[i].phys_y = cfg->pp_phys_buf + TRY * one_p_size; cfg->img_buf[i].virt_cb = cfg->pp_virt_buf + daon + TRY * one_p_size; cfg->img_buf[i].phys_cb = cfg->pp_phys_buf + daon + TRY * one_p_size; cfg->img_buf[i].virt_cr = cfg->pp_virt_buf + daon + c_size + TRY * one_p_size; cfg->img_buf[i].phys_cr = cfg->pp_phys_buf + daon + c_size + TRY * one_p_size; rCICOYSA(i) = cfg->img_buf[i].phys_y; rCICOCBSA(i) = cfg->img_buf[i].phys_cb; rCICOCRSA(i) = cfg->img_buf[i].phys_cr; } break; case 4: one_p_size = daon + 2*c_size; for (i = 0; i < 4 ; i++) { cfg->img_buf[i].virt_y = cfg->pp_virt_buf + i * one_p_size; cfg->img_buf[i].phys_y = cfg->pp_phys_buf + i * one_p_size; cfg->img_buf[i].virt_cb = cfg->pp_virt_buf + daon + i * one_p_size; cfg->img_buf[i].phys_cb = cfg->pp_phys_buf + daon + i * one_p_size; cfg->img_buf[i].virt_cr = cfg->pp_virt_buf + daon + c_size + i * one_p_size; cfg->img_buf[i].phys_cr = cfg->pp_phys_buf + daon + c_size + i * one_p_size; rCICOYSA(i) = cfg->img_buf[i].phys_y; rCICOCBSA(i) = cfg->img_buf[i].phys_cb; rCICOCRSA(i) = cfg->img_buf[i].phys_cr; } break; default: printk("Invalid PingPong Number %d \n",cfg->pp_num); panic("halt\n"); } DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return 0;}/* RGB Buffer Allocation */static int camif_pp_preview(camif_cfg_t *cfg){ int i; u32 daon = cfg->target_x * cfg->target_y; DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin if(cfg->fmt & CAMIF_RGB24) daon = daon * 4 ; else { assert (cfg->fmt & CAMIF_RGB16); daon = daon *2; } switch ( cfg->pp_num ) { case 1: for ( i = 0; i < 4 ; i++ ) { cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf ; cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf ; rCIPRCLRSA(i) = cfg->img_buf[i].phys_rgb; } break; case 2: for ( i = 0; i < 4 ; i++) { cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf + TRY * daon; cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf + TRY * daon; rCIPRCLRSA(i) = cfg->img_buf[i].phys_rgb; } break; case 4: for ( i = 0; i < 4 ; i++) { cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf + i * daon; cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf + i * daon; rCIPRCLRSA(i) = cfg->img_buf[i].phys_rgb; } break; default: printk("Invalid PingPong Number %d \n",cfg->pp_num); panic("halt\n"); } DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return 0;}static int camif_pingpong(camif_cfg_t *cfg){ DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin if (cfg->dma_type & CAMIF_CODEC ) { camif_pp_codec(cfg); } if ( cfg->dma_type & CAMIF_PREVIEW) { camif_pp_preview(cfg); } DEBUG0("[ %s() E ]\n",__FUNCTION__); // lovejin return 0;}/*********** Image Convert *******************************//* Return Format * Supported by Hardware * V4L2_PIX_FMT_YUV420, * V4L2_PIX_FMT_YUV422P, * V4L2_PIX_FMT_BGR32 (BGR4) * ----------------------------------- * V4L2_PIX_FMT_RGB565(X) * Currenly 2byte --> BGR656 Format * S3C2440A,S3C24A0 supports vairants with reversed FMT_RGB565 i.e blue toward the least, red towards the most significant bit -- by SW.LEE *//* * After calling camif_g_frame_num, * this func must be called */u8 * camif_g_frame(camif_cfg_t *cfg){ u8 * ret = NULL; int cnt = cfg->now_frame_num; if(cfg->dma_type & CAMIF_PREVIEW) { ret = cfg->img_buf[cnt].virt_rgb; } if (cfg->dma_type & CAMIF_CODEC) { ret = cfg->img_buf[cnt].virt_y; } return ret;}/* This function must be called in module initial time */static int camif_source_fmt(camif_gc_t *gc) { u32 cmd = 0; DEBUG0("[ %s() S ]\n",__FUNCTION__); // lovejin#if 1 printk("camif_source_fmt: start\n"); /* Configure CISRCFMT --Source Format */ if (gc->itu_fmt & CAMIF_ITU601) { cmd = CAMIF_ITU601; } else { assert ( gc->itu_fmt & CAMIF_ITU656);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -