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

📄 chg-pxa_ov_camera.c_bak

📁 ov2640驱动开发
💻 C_BAK
📖 第 1 页 / 共 5 页
字号:
/* 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 + -