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

📄 camif_innovator.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * camif_innovator.c * * Implementation of Camera Interface for OMAP1510 Innovator platform. * * Copyright (C) 2003-2004 MontaVista Software, Inc. * * Author: MontaVista Software, Inc. *              stevel@mvista.com or source@mvista.com * *  Modifications: * *  Oct 2003: MontaVista Software Inc. source@mvista.com *  Added OMAP1610 support * *  May 2004: MontaVista Software Inc. stevel@mvista.com *    - stripped out old NO_DMA support. *    - added support for OV9640 camera detection. *    - some minor fixes to the camera API. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#include <linux/config.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/ioport.h>#include <linux/videodev.h>#include <linux/version.h>#include <linux/interrupt.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/pgtable.h>#include <asm/page.h>#include <asm/dma.h>#ifdef CONFIG_ARCH_OMAP730#include <asm/arch/omap730_config.h>#endif#define MODULE_NAME "camif"#include "common.h"#include "camif.h"static struct camera_interface * this;static void (*capture_callback)(void *);static void* callback_data;static u8* capture_buffer;#undef MEASURE_FRstatic volatile u32 *omap_product_id = (volatile u32 *)OMAP_PROD_ID_1;// DMA global control registerstatic volatile u16 *        dma_gcr = (u16 *)(OMAP_DMA_BASE + 0x400);static volatile dma_regs_t * camera_dma_regs = NULL;static volatile camera_regs_t * camera_regs = NULL;static int snapshot_active = 0;static int streaming_active = 0;static int camera_module_present = 0;static int current_exclk = 24*10;  // MHz * 10static spinlock_t camif_lock;static wait_queue_head_t vsync_wait;#define FIFO_TRIGGER_LVL 32#define DMA_DEST_AMODE  AMODE_POST_INC#define DMA_FRAME_INDEX 0#define DMA_ELEM_INDEX  0#define DMA_ELEM_SIZE   4#define DMA_DEST_PORT   PORT_EMIFFstatic inline int is_omap_1623(void){	return (*omap_product_id >> 1) == OMAP1623_PROD_ID;}static inline u32 get_imgsize_bits(void){	if (this->camera) {		switch (this->camera->imgfmt) {		case VGA:			return IMGSIZE_VGA;		case CIF:			return IMGSIZE_CIF;		case QVGA:			return IMGSIZE_QVGA;		default:			return IMGSIZE_QCIF;		}	}	return IMGSIZE_QCIF;}static inline void camif_mode_set(u32 mask){	u32 itstat = camera_regs->it_status ;	itstat = 0;	camera_regs->mode |= mask;}static inline void camif_mode_clear(u32 mask){	u32 itstat = camera_regs->it_status ;	itstat = 0;	camera_regs->mode &= ~mask;}static inline void camif_cleanfifo(void){	ENTRY();	camera_regs->ctrlclock &= ~LCLK_EN;	camif_mode_set(RAZ_FIFO);	udelay(10);	camif_mode_clear(RAZ_FIFO);	camera_regs->ctrlclock |= LCLK_EN;	EXIT();}static inline u32 mhzx10_to_foscmod(int mhzx10){	switch (mhzx10) {	case 60:		return FOSCMOD_6MHz;	case 80:		return FOSCMOD_8MHz;	case 96:		return FOSCMOD_9_6MHz;	case 120:		return FOSCMOD_12MHz;	case 240:	default:		/* gotta use DPLL source for 24 MHz */		return FOSCMOD_24MHz | DPLL_EN;	}}static inline void camif_start(int exclk){	u32 clkbits = mhzx10_to_foscmod(exclk);		// take camera interface out of reset	camera_regs->gpio = CAM_RST;	// reset mode	camera_regs->mode = (get_imgsize_bits() |			     (FIFO_TRIGGER_LVL << THRESHOLD_BIT));		// start the camera interface clocks	camera_regs->ctrlclock =		(MCLK_EN | LCLK_EN | CAMEXCLK_EN | clkbits);	mdelay(10);	current_exclk = exclk;}static inline void camif_stop(void){	camera_regs->ctrlclock = 0; // stop clocks	camera_regs->gpio = 0;	    // put camera interface in reset	mdelay(10);}#ifdef MEASURE_FRextern unsigned long do_getmachinecycles(void);extern unsigned long machinecycles_to_usecs(unsigned long mputicks);static unsigned long dmac_sum;static unsigned long dmac_delta;static unsigned long dmac_N;#endifstatic void dma_callback(void *client_data){	unsigned long flags;		spin_lock_irqsave(&camif_lock, flags);	snapshot_active = 0;	if (streaming_active) {		camif_cleanfifo();		camera_dma_regs->ccr |= DCCR_EN; // restart DMA	} else {		camif_mode_clear(EN_DMA | EN_FIFO_FULL);	}	spin_unlock_irqrestore(&camif_lock, flags);#ifdef MEASURE_FR	if (dmac_delta) {		dmac_sum += machinecycles_to_usecs(do_getmachinecycles()						   - dmac_delta);		dmac_N++;	}	dmac_delta = do_getmachinecycles();#endif		// callback to V4L2 layer	capture_callback(callback_data);	EXIT();}// SystemDMA initstatic int dma_init(void){	ENTRY();	*dma_gcr = 0x0004;  // dma free running	EXIT();	return 0;}static void dma_start(void){	dma_addr_t physbuf;	int width = omap_image_size[this->camera->imgfmt].width;	int height = omap_image_size[this->camera->imgfmt].height;	int Bpp = (omap_pixfmt_depth[this->camera->pixfmt] + 7) >> 3;	u16 port = 0;    	ENTRY();	if (!this->camera)		return;	if ( is_omap_1623() ) 		port = (PORT_OCP_T1 << DCSDP_SRC_PORT_BIT);	else 		port = (PORT_TIPB << DCSDP_SRC_PORT_BIT);				camera_dma_regs->csdp = DATA_TYPE_S32 | port | (DMA_DEST_PORT << DCSDP_DEST_PORT_BIT);	//dbg("%04x --> CSDP\n", camera_dma_regs->csdp);		/*	 * sync on camera fifo, no autoinit, high pri,	 * frame sync, src const, dst post inc	 */	camera_dma_regs->ccr =		((DMA_DEST_AMODE << DCCR_DST_AMODE_BIT) |		 (AMODE_CONST << DCCR_SRC_AMODE_BIT) |		 DCCR_PRIO | DCCR_FS | eCameraRx);	if (streaming_active)		camera_dma_regs->ccr |= (DCCR_AI | DCCR_REPEAT);	//dbg("%04x --> CCR\n", camera_dma_regs->ccr);		camera_dma_regs->cicr   = 0x0020; // enable block interrupt			if ( is_omap_1623() ) {		camera_dma_regs->cssa_l = (OMAP1623_CAM_CAMDATA_REG & 0xffff);		camera_dma_regs->cssa_u = ((OMAP1623_CAM_CAMDATA_REG>>16) & 0xffff);	}	else {		camera_dma_regs->cssa_l = (CAM_CAMDATA_REG & 0xffff);		camera_dma_regs->cssa_u = ((CAM_CAMDATA_REG>>16) & 0xffff);	}	//dbg("%04x --> CSSA_L\n", camera_dma_regs->cssa_l);	//dbg("%04x --> CSSA_U\n", camera_dma_regs->cssa_u);	/*	 * elements per frame must be FIFO trigger level when	 * using frame sync	 */	camera_dma_regs->cen = FIFO_TRIGGER_LVL;	// TODO: make sure this divides to a whole number.	camera_dma_regs->cfn =		(width * height * Bpp) / (DMA_ELEM_SIZE * FIFO_TRIGGER_LVL);#ifdef CONFIG_ARCH_OMAP1510	camera_dma_regs->cfi = DMA_FRAME_INDEX;	camera_dma_regs->cei = DMA_ELEM_INDEX;#else	camera_dma_regs->csfi = DMA_FRAME_INDEX;	camera_dma_regs->csei = DMA_ELEM_INDEX;	camera_dma_regs->cdfi = DMA_FRAME_INDEX;	camera_dma_regs->cdei = DMA_ELEM_INDEX;#endif	physbuf = (dma_addr_t)virt_to_phys(capture_buffer);#if 1	//dbg("regs->csr = 0x%08x\n", camera_dma_regs->csr);	camera_dma_regs->cdsa_l = physbuf & 0xffff;	camera_dma_regs->cdsa_u = (physbuf >> 16) & 0xffff;	//dbg("%04x --> CDSA_L\n", camera_dma_regs->cdsa_l);	//dbg("%04x --> CDSA_U\n", camera_dma_regs->cdsa_u);	camera_dma_regs->ccr |= DCCR_EN;	// start transfer;#else	omap_start_dma((dma_regs_t *)camera_dma_regs, physbuf, 0);#endif	EXIT();}static void camera_interrupt(int irq, void *client_data,			     struct pt_regs *regs){	u32 itstat;	ENTRY();		spin_lock(&camif_lock);	itstat = camera_regs->it_status;		if (itstat & V_UP) {		if (snapshot_active || streaming_active) {			camif_cleanfifo();			camif_mode_clear(EN_V_UP);			camif_mode_set(EN_DMA | EN_FIFO_FULL);			dma_start();		}		wake_up_interruptible(&vsync_wait);	}		if (itstat & V_DOWN) {		wake_up_interruptible(&vsync_wait);	}	if (itstat & H_UP) {		dbg("H_UP set\n");	}	if (itstat & H_DOWN) {		dbg("H_DOWN set\n");	}	if (itstat & FIFO_FULL) {		camif_cleanfifo();		dbg("FIFO_FULL set\n");	}	spin_unlock(&camif_lock);	EXIT();}static void camif_wait_for_vsync_edge(u32 edge_mask){	ENTRY();	camif_mode_set(edge_mask);	// wait for VSYNC edge	do {		interruptible_sleep_on(&vsync_wait);	} while (signal_pending(current));	camif_mode_clear(edge_mask);	camif_cleanfifo();	EXIT();}static int camif_snapshot(u8* buf, int size){	unsigned long flags;	spin_lock_irqsave(&camif_lock, flags);	if (!this->camera) {		spin_unlock_irqrestore(&camif_lock, flags);		return -ENODEV;	}	if (snapshot_active) {		dbg("already active!\n");		spin_unlock_irqrestore(&camif_lock, flags);		return 0;	}	if (streaming_active) {		dbg("streaming is active!\n");		spin_unlock_irqrestore(&camif_lock, flags);		return -EINVAL;	}		capture_buffer = buf;	snapshot_active = 1;	camif_mode_set(EN_V_UP);	//dbg("mode = 0x%08x\n", camera_regs->mode);	spin_unlock_irqrestore(&camif_lock, flags);	return 0;}static int camif_start_streaming(u8* buf, int size){	unsigned long flags;	spin_lock_irqsave(&camif_lock, flags);	if (!this->camera) {		spin_unlock_irqrestore(&camif_lock, flags);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -