📄 chg-pxa_ov_camera.c_bak
字号:
/* pxa_ov_camera - main file for OmniVision camera driver
*
* Copyrith (c) 2006, OmniVision
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
*
* OmniVision is a trademark of OmniVision Technologies, Inc.
*
* Version 1.00 July.04.2006 david zhu
* david@ovt.com.cn
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
#include <linux/videodev.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/cpufreq.h>
#include <linux/types.h>
#include <asm/mach-types.h>
#include <asm/io.h>
#include <asm/semaphore.h>
#include <asm/hardware.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/arch/irqs.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/apap.h>
/*capture interface*/
#include "ci_ov.h"
#include "pxaovcamera.h"
#ifdef CONFIG_ARCH_MAINSTONE
/*camerachip control interface*/
#include "ovcamerachip.h"
#endif
#include "ovcamerachip.h"
//#define DEBUG
#ifdef DEBUG
#define ovcamprint(fmt,args...) printk(KERN_WARNING "pax ovcamera:" fmt, ## args)
#else
#define ovcamprint(fmt,args...)
#endif
/* macro define */
//#define BUFFER_SIZE_DEFAULT 0x1D4C00
#define BUFFER_SIZE_DEFAULT 0xea600 //jhy
#define SINGLE_DESCRIPTORS_TRANSFER_MAX 8000
#define MAX_DESCRIPTORS_NUM (BUFFER_SIZE_DEFAULT/SINGLE_DESCRIPTORS_TRANSFER_MAX)
//For YUV422 //jhy
#define FIFO_0_SINGLE_DESC_TRANS_MAX 8000//7680
#define FIFO_1_SINGLE_DESC_TRANS_MAX 8000//3840
#define FIFO_2_SINGLE_DESC_TRANS_MAX 8000//3840
#define MAX_DESC_NUM 0x400
#define MAX_BLOCK_NUM 20
#define CAPTURE_STILL_IMAGE 1 //jhy
#define CAPTURE_VIDEO_DATA 0
#define WIDTH_DEFAULT 176
#define HEIGHT_DEFAULT 144
#define FRAMERATE_DEFAULT 0x0
#define CIBR0_PHY (0x50000000 + 0x28)
#define CIBR1_PHY (0x50000000 + 0x30)
#define CIBR2_PHY (0x50000000 + 0x38)
typedef struct camera_control_s {
/* /dev/videoX registration number */
int minor;
int ci_dma_y;
int ci_dma_cb;
int ci_dma_cr;
int first_video_frame;
volatile unsigned int frames_captured;
volatile unsigned char capture_status;
volatile unsigned char still_image_rdy;
int refcount;
struct semaphore mutex;
#ifdef CONFIG_CPU_FREQ
struct notifier_block clockchg;
#endif
} camera_control_t,*p_camera_control_t;
static camera_control_t g_camera_control;
extern ovcamera_function_t camerachip_func;
static ovcamera_context_t *g_ovcamera_context;
static int minor = 0;
wait_queue_head_t ovcamera_wait_q;
volatile int task_waiting = 0;
static int still_image_mode = 0;
static int still_image_ready = 0;
static int first_video_frame = 0;
//jhy
struct reg_set_s {
int val1;
int val2;
};
/*DMA*/
int ci_dma_y,ci_dma_u,ci_dma_v;
void pxa_ci_dma_irq_y(int channel, void *data, struct pt_regs *regs);
void pxa_ci_dma_irq_u(int channel, void *data, struct pt_regs *regs);
void pxa_ci_dma_irq_v(int channel, void *data, struct pt_regs *regs);
static unsigned long ci_regs_base = 0; /* CI registers IOMEM mapping */
// map of camera image format (pxaovcamera.h) ==> capture interface format (ci_ov.h)
static const CI_IMAGE_FORMAT FORMAT_MAPPINGS[] = {
CI_RAW8, //RAW
CI_RAW9,
CI_RAW10,
CI_RGB444, //RGB
CI_RGB555,
CI_RGB565,
CI_RGB666_PACKED, //RGB Packed
CI_RGB666,
CI_RGB888_PACKED,
CI_RGB888,
CI_RGBT555_0, //RGB+Transparent bit 0
CI_RGBT888_0,
CI_RGBT555_1, //RGB+Transparent bit 1
CI_RGBT888_1,
CI_INVALID_FORMAT,
CI_YCBCR422, //YCBCR
CI_YCBCR422_PLANAR, //YCBCR Planaried
CI_INVALID_FORMAT,
CI_INVALID_FORMAT,
CI_JPEG,
};
static int ovcamera_set_capture_format(p_ovcamera_context_t p_ovcam_ctx);
static int ovcamera_deinit ( p_ovcamera_context_t p_ovcam_ctx );
//jhy
static DECLARE_WAIT_QUEUE_HEAD(dma_wait);
static DECLARE_WAIT_QUEUE_HEAD(dma_read_wait);
//jhy
struct dma_buf_struct{
unsigned int vaddr;
unsigned int paddr;
unsigned int size;
struct list_head queue;
};
//jhy
struct dma_buf_struct *get_list_entry(struct list_head *head){
struct list_head *next;
if (!head){
printk("%s: %d NULL Pointer!\n", __FUNCTION__, __LINE__);
return NULL;
}
next = head->next;
if (!next || next == head){
return NULL;
}
return (container_of(next, struct dma_buf_struct, queue));
}
/* #############################################################
/#
/# Intel Quick Capture Interface Configuration Interface
/#
/############################################################# */
void ci_set_frame_rate(CI_FRAME_CAPTURE_RATE frate)
{
unsigned int value;
// write cicr4
value = CICR4;
value &= ~(CI_CICR4_FR_RATE_SMASK << CI_CICR4_FR_RATE_SHIFT);
value |= (unsigned)frate << CI_CICR4_FR_RATE_SHIFT;
CICR4 = value;
}
CI_FRAME_CAPTURE_RATE ci_get_frame_rate(void)
{
unsigned int value;
value = CICR4;
return (CI_FRAME_CAPTURE_RATE)((value >> CI_CICR4_FR_RATE_SHIFT) & CI_CICR4_FR_RATE_SMASK);
}
void ci_set_image_format(CI_IMAGE_FORMAT input_format, CI_IMAGE_FORMAT output_format)
{
unsigned int value, tbit, rgbt_conv, rgb_conv, rgb_f, ycbcr_f, rgb_bpp, raw_bpp, cspace;
// write cicr1: preserve ppl value and data width value
value = CICR1;
value &= ( (CI_CICR1_PPL_SMASK << CI_CICR1_PPL_SHIFT) | ((CI_CICR1_DW_SMASK) << CI_CICR1_DW_SHIFT));
tbit = rgbt_conv = rgb_conv = rgb_f = ycbcr_f = rgb_bpp = raw_bpp = cspace = 0;
switch(input_format) {
case CI_RAW8:
cspace = 0;
raw_bpp = 0;
break;
case CI_RAW9:
cspace = 0;
raw_bpp = 1;
break;
case CI_RAW10:
cspace = 0;
raw_bpp = 2;
break;
case CI_YCBCR422:
case CI_YCBCR422_PLANAR:
cspace = 2;
if (output_format == CI_YCBCR422_PLANAR) {
ycbcr_f = 1;
}
break;
case CI_RGB444:
cspace = 1;
rgb_bpp = 0;
break;
case CI_RGB555:
cspace = 1;
rgb_bpp = 1;
if (output_format == CI_RGBT555_0) {
rgbt_conv = 2;
tbit = 0;
}
else if (output_format == CI_RGBT555_1) {
rgbt_conv = 2;
tbit = 1;
}
break;
case CI_RGB565:
cspace = 1;
rgb_bpp = 2;
rgb_f = 1;
break;
case CI_RGB666:
cspace = 1;
rgb_bpp = 3;
if (output_format == CI_RGB666_PACKED) {
rgb_f = 1;
}
break;
case CI_RGB888:
case CI_RGB888_PACKED:
cspace = 1;
rgb_bpp = 4;
switch(output_format) {
case CI_RGB888_PACKED:
rgb_f = 1;
break;
case CI_RGBT888_0:
rgbt_conv = 1;
tbit = 0;
break;
case CI_RGBT888_1:
rgbt_conv = 1;
tbit = 1;
break;
case CI_RGB666:
rgb_conv = 1;
break;
case CI_RGB666_PACKED:
rgb_conv = 1;
rgb_f = 1;
break;
case CI_RGB565:
rgb_conv = 2;
break;
case CI_RGB555:
rgb_conv = 3;
break;
case CI_RGB444:
rgb_conv = 4;
break;
default:
break;
}
break;
case CI_JPEG:
cspace = 0;
raw_bpp = 0;
break;
default:
break;
}
value |= (tbit==1) ? CI_CICR1_TBIT : 0;
value |= rgbt_conv << CI_CICR1_RGBT_CONV_SHIFT;
value |= rgb_conv << CI_CICR1_RGB_CONV_SHIFT;
value |= (rgb_f==1) ? CI_CICR1_RBG_F : 0;
value |= (ycbcr_f==1) ? CI_CICR1_YCBCR_F : 0;
value |= rgb_bpp << CI_CICR1_RGB_BPP_SHIFT;
value |= raw_bpp << CI_CICR1_RAW_BPP_SHIFT;
value |= cspace << CI_CICR1_COLOR_SP_SHIFT;
CICR1 = value;
return;
}
void ci_set_mode(CI_MODE mode, CI_DATA_WIDTH data_width)
{
unsigned int value;
// write mode field in cicr0
value = CICR0;
value &= ~(CI_CICR0_SIM_SMASK << CI_CICR0_SIM_SHIFT);
value |= (unsigned int)mode << CI_CICR0_SIM_SHIFT;
CICR0 = value;
// write data width cicr1
value = CICR1;
value &= ~(CI_CICR1_DW_SMASK << CI_CICR1_DW_SHIFT);
value |= ((unsigned)data_width) << CI_CICR1_DW_SHIFT;
CICR1 = value;
return;
}
///////////////////////////////////////////////////////////////////////////////
//Configure Quick Capture Interface to Master-Parallel mode
///////////////////////////////////////////////////////////////////////////////
void ci_configure_mp(unsigned int ppl, unsigned int lpf, CI_MP_TIMING* timing)
{
unsigned int value;
// write ppl field in cicr1
value = CICR1;
value &= ~(CI_CICR1_PPL_SMASK << CI_CICR1_PPL_SHIFT);
value |= (ppl & CI_CICR1_PPL_SMASK) << CI_CICR1_PPL_SHIFT;
CICR1 = value;
// write BLW, ELW in cicr2
value = CICR2;
value &= ~(CI_CICR2_BLW_SMASK << CI_CICR2_BLW_SHIFT | CI_CICR2_ELW_SMASK << CI_CICR2_ELW_SHIFT );
value |= (timing->BLW & CI_CICR2_BLW_SMASK) << CI_CICR2_BLW_SHIFT;
CICR2 = value;
// write BFW, LPF in cicr3
value = CICR3;
value &= ~(CI_CICR3_BFW_SMASK << CI_CICR3_BFW_SHIFT | CI_CICR3_LPF_SMASK << CI_CICR3_LPF_SHIFT );
value |= (timing->BFW & CI_CICR3_BFW_SMASK) << CI_CICR3_BFW_SHIFT;
value |= (lpf & CI_CICR3_LPF_SMASK) << CI_CICR3_LPF_SHIFT;
CICR3 = value;
return;
}
void ci_configure_sp(unsigned int ppl, unsigned int lpf, CI_SP_TIMING* timing)
{
unsigned int value;
// write ppl field in cicr1
value = CICR1;
value &= ~(CI_CICR1_PPL_SMASK << CI_CICR1_PPL_SHIFT);
value |= (ppl & CI_CICR1_PPL_SMASK) << CI_CICR1_PPL_SHIFT;
CICR1 = value;
// write cicr2
value = CICR2;
value |= (timing->BLW & CI_CICR2_BLW_SMASK) << CI_CICR2_BLW_SHIFT;
value |= (timing->ELW & CI_CICR2_ELW_SMASK) << CI_CICR2_ELW_SHIFT;
value |= (timing->HSW & CI_CICR2_HSW_SMASK) << CI_CICR2_HSW_SHIFT;
value |= (timing->BFPW & CI_CICR2_BFPW_SMASK) << CI_CICR2_BFPW_SHIFT;
value |= (timing->FSW & CI_CICR2_FSW_SMASK) << CI_CICR2_FSW_SHIFT;
CICR2 = value;
// write cicr3
value = CICR3;
value |= (timing->BFW & CI_CICR3_BFW_SMASK) << CI_CICR3_BFW_SHIFT;
value |= (timing->EFW & CI_CICR3_EFW_SMASK) << CI_CICR3_EFW_SHIFT;
value |= (timing->VSW & CI_CICR3_VSW_SMASK) << CI_CICR3_VSW_SHIFT;
value |= (lpf & CI_CICR3_LPF_SMASK) << CI_CICR3_LPF_SHIFT;
CICR3 = value;
return;
}
void ci_configure_ms(unsigned int ppl, unsigned int lpf, CI_MS_TIMING* timing)
{
// the operation is same as Master-Parallel
ci_configure_mp(ppl, lpf, (CI_MP_TIMING*)timing);
}
void ci_configure_ep(int parity_check)
{
unsigned int value;
// write parity_enable field in cicr0
value = CICR0;
if (parity_check) {
value |= CI_CICR0_PAR_EN;
}
else {
value &= ~CI_CICR0_PAR_EN;
}
CICR0 = value;
return;
}
void ci_configure_es(int parity_check)
{
// the operationi is same as Embedded-Parallel
ci_configure_ep(parity_check);
}
void ci_set_clock(unsigned int clk_regs_base, int pclk_enable, int mclk_enable, unsigned int mclk_khz)
{
unsigned int ciclk = 0, value, div, cccr_l;
ovcamprint("ci_set_clock( + ) \n");
ovcamprint("CCCR =%16x\n",CCCR);
// determine the LCLK frequency programmed into the CCCR.
cccr_l = (CCCR & 0x0000001F);
if (cccr_l < 8) // L = [2 - 7]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -