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

📄 camif_evm.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
字号:
/* * File: camif_evm.c * * Description: *   Implementation of Camera Interface for OMAP1510 EVM platform. *                            f *   This driver was highly leveraged from Bill Dirk's *   v4l2 example generic driver. Modified by RidgeRun *   to work with the omap1509 camera module. * * Author: RidgeRun, Inc <skranz@ridgerun.com> * Created 2002, Copyright (C) 2002 RidgeRun, Inc.  All rights reserved. * Created 2002, Copyright (C) 2002 Texas Instruments  All rights reserved. * Copyright (C) 2003 MontaVista Software, Inc. All rights reserved. * * 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. * * Original Author: Bill Dirks <bdirks@pacbell.net> *                  based on code by Alan Cox, <alan@cymru.net> */#include <linux/config.h> /* retrieve the CONFIG_* macros */#include <linux/init.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/ioport.h>#include <linux/sched.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>#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;static int capture_size;static void CAM_cleanfifo(void);static void CAM_intr(int irq, void *client_data, struct pt_regs *regs);static void DMA_intr(void *client_data);static int snapshot_active = 0;static int streaming_active = 0;#define CAM_MODE     ((volatile unsigned int *)0xFFFB6808)#define CAM_GPIO_RST ((volatile unsigned int *)0xFFFB6814)static dma_regs_t *dma_regs = NULL;static int camif_abort(void){	// Disable cam_intr() interrupts.	*CAM_MODE &= ~0x301f0;		omap_reset_dma(dma_regs); // terminate any in-progress DMA.		// *revisit-skranz* in the interest of power	// management we should also put logic here	// that uses I2C to tell the camera Module	// to stop processing images -- or maybe assert	// and hold indefinitely the camera module's	// reset line. I believe the "*CAM_GPIO_RST=0x0;"	// would accomplish that.	snapshot_active = streaming_active = 0;	return 0;}static int camif_snapshot(u8* buf, int size){        ENTRY();	capture_buffer = buf;	capture_size = size;		if (snapshot_active || streaming_active)                camif_abort();	// Enable cam_intr() interrupts.		*CAM_MODE |= 0x0110;  // Set DMA Mode and Unmask EN_V_UP//          *CAM_MODE |= 0x00020110;  // Set DMA Mode and Unmask EN_V_UP	*CAM_GPIO_RST |= 0x01;  // Take Camera interface out of reset        snapshot_active = 1;	return 0;}static int camif_start_streaming(u8* buf, int size){	ENTRY();		capture_buffer = buf;	capture_size = size;		if (snapshot_active || streaming_active)		camif_abort();		// Enable cam_intr() interrupts.		*CAM_MODE |= 0x0110;  // Set DMA Mode and Unmask EN_V_UP//          *CAM_MODE |= 0x00020110;  // Set DMA Mode and Unmask EN_V_UP		*CAM_GPIO_RST |= 0x01;  // Take Camera interface out of reset		streaming_active = 1;	return 0;}/* * *      V I D E O   F O R   L I N U X   I N T E R F A C I N G * */// **************************// Routine:// Description:// **************************static int camif_open(void){	int status;	if (!this->camera)		return 0;	// Request and enable Camera interrupt	status = request_irq(INT_CAMERA, &CAM_intr,			     SA_INTERRUPT, "camera", NULL);	if (status < 0) {		err("No IRQ available for camera");		return status;	}	if (!dma_regs) {		if (omap_request_dma(eCameraRx, "camera", DMA_intr,				     NULL, &dma_regs)) {			err("No DMA available for camera");			return -ENODEV;		}		omap_dma_setup(eCameraRx, eDmaIn);				dma_regs->csdp   = 0x000E;		// sync camera fifo, no autoinit, high pri,		dma_regs->ccr    = 0x4054;		// frame sync, src const, dst post inc		dma_regs->cicr   = 0x0020;   	// enable block interrupt		dma_regs->cssa_l = 0x6810;   	// low; camif data reg		dma_regs->cssa_u = 0xFFFB;   	// hi;  camif data reg//      dma_regs->cfn = 1;//      dma_regs->cen = ((Camera_Data_Size) / 4);//      dma_regs->cen = 1;//      dma_regs->cfn = (((Camera_Data_Size) / 4) / dma_regs->cen);//      dma_regs->cen = 2;		//dma_regs->cen = 32;		//dma_regs->cfn = (((Camera_Data_Size) / 4) / dma_regs->cen);	}	return this->camera->open();}static int camif_close(void){	camif_abort();	if (this->camera)		this->camera->close();	free_irq(INT_CAMERA, NULL);	omap_free_dma((dma_regs_t *)dma_regs);	return 0;}// ------------------hw----------------------- //#define CAM_BASE              ((volatile unsigned int *)0xFFFB6800)#define CAM_CTRLCLOCK         ((volatile unsigned int *)0xFFFB6800)#define CAM_IT_STATUS         ((volatile unsigned int *)0xFFFB6804)#define CAM_STATUS            ((volatile unsigned int *)0xFFFB680C)static void dump_dma_regs(void){	u16 *i;	for (i=(u16 *)dma_regs; i < (((u16 *)dma_regs) + 13); i++)		dbg("dma_reg:  0x%08x = 0x%04x\n", (unsigned int)i, (u16)(*i));}static void dump_camera_regs(void){	u32 *i;	for (i=(u32 *)CAM_BASE; i < (((u32 *)CAM_BASE) + 7); i++)		dbg("cam_reg:  0x%08x = 0x%08x\n", (unsigned int)i, (u32)(*i));}static inline void CAM_cleanfifo(void){#define CAMDATA ((volatile unsigned int *)0xFFFB6810)#define CAM_PEAK_COUNTER ((volatile unsigned int *)0xFFFB6818)	int i;	volatile unsigned int val;	for (i=0;i<128;i++)		val = *CAMDATA;	*CAM_PEAK_COUNTER = 0;//   *CAM_MODE |= (1<<18);//   *CAM_MODE &=~(1<<18);}// **************************// Routine:// Description:// **************************static void CAM_intr(int irq, void *client_data, struct pt_regs *regs){	unsigned int status;	// This is a clear-on-read register so we'll read it only	// once and perform all tests on the single cached value.	status = *CAM_IT_STATUS;  	//DBG("Status= 0x%08x\n", status);//  dump_camera_regs();	if (DATA_XFER & status) {		//DBG("DATA_XFER\n");	}	if (FIFO_FULL & status) {		//DBG("FIFO_FULL\n");//    CAM_cleanfifo();//    status = *CAM_IT_STATUS;	}	if (H_DOWN & status) {		//DBG("H_DOWN\n");	}	if (H_UP & status) {		//DBG("H_UP\n");	}	if (V_DOWN & status) {		//DBG("V_DOWN\n");	}	if (V_UP & status) {		//DBG("V_UP\n");//    dump_dma_regs();		if (snapshot_active || streaming_active) {			u32* phyBuff =				(u32 *)virt_to_phys((void*)capture_buffer);			//DBG("StartCamera"); 			CAM_cleanfifo();			status = *CAM_IT_STATUS;						// start a new capture.			omap_start_dma(dma_regs,				       (dma_addr_t)phyBuff,				       (u_int)capture_size);						// Note: At this point the pump is furthur primed			//       for picking up an image. Processing will			//       continue at DMA_intr() interrupt.		}	}}// **************************// Routine:// Description:// **************************static void DMA_intr(void *client_data){	// Note: This represents the last step	// in capturing a raw image from the h/w.	snapshot_active = 0;	// callback to V4L2 layer	capture_callback(callback_data);}static int camif_init(void (*callback)(void *), void* data){	ENTRY();	this = &camif_evm;	capture_callback = callback;	callback_data = data;	//  *CAM_GPIO_RST = 0x00; // hold reset.	*CAM_CTRLCLOCK = 0xA0;  // LCLK_EN | MCLK_EN//  *CAM_MODE = 0x0200;     // THRESHOLD = 1//  *CAM_MODE = 0x0400;     // THRESHOLD = 2// 	*CAM_MODE = 0x0800;     // THRESHOLD = 4// 	*CAM_MODE = 0x1000;     // THRESHOLD = 8//  *CAM_MODE = 0x2000;     // THRESHOLD = 16//  *CAM_MODE = 0x4000;     // THRESHOLD = 32//  *CAM_MODE = 0x8000;     // THRESHOLD = 64	//DBG("Threshold = 4\n");	CAM_cleanfifo();//  *CAM_CTRLCLOCK |= 0x0010;  // Enable external clock	*CAM_MODE |= 0x8; 		// turn on byte swap in cam intf fifo.	// so that we can avoid doing it in SW	// This probably is off by default and we don't need to	// explicitly turn it of for omni as swap is not needed there.//  *CAM_GPIO_RST = 0x00;//  *CAM_GPIO_RST = 0x01;	return 0;}static void camif_cleanup(void) {	struct camera_serial_bus * sbus = this->sbus;	info("Unloading\n");	if (this->camera)		this->camera->cleanup();	sbus->cleanup();}// **************************// Routine: // Description:// **************************static struct camera * camif_camera_detect(void){	struct camera * cam;	ENTRY();	this->camera = NULL;	// first, set serial bus to I2C	this->sbus = &camera_sbus_old_i2c;	// and init the bus	if (this->sbus->init()) {		err("error initializing 1509-mode I2C bus\n");		return NULL;	}	// -------	// try and detect if a Sanyo camera is out there.	// -------	cam = &camera_sanyo;	cam->camif = this;	if (cam->detect() == 0) {		this->camera = cam;		this->camera->init();		return cam;	}		// -------	// Try and detect if an OmniVision camera is out there.	// -------	cam = &camera_ov6x30;	cam->camif = this;		if (cam->detect() == 0) {		this->camera = cam;		this->camera->init();		return cam;	}	return NULL; // camera not present.}static void* camif_alloc_image_buffer(int size){	return (void*)__get_dma_pages(GFP_KERNEL, get_order(size));}static void camif_free_image_buffer(void* buffer, int size){	free_pages((unsigned long)buffer, get_order(size));}struct camera_interface camif_evm = {	camera_detect:      camif_camera_detect,	alloc_image_buffer: camif_alloc_image_buffer,	free_image_buffer:  camif_free_image_buffer,	init:               camif_init,	cleanup:            camif_cleanup,	open:               camif_open,	close:              camif_close,	snapshot:           camif_snapshot,	start_streaming:    camif_start_streaming,	abort:              camif_abort,};

⌨️ 快捷键说明

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