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

📄 omap24xxcam.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * drivers/media/video/omap/omap24xxcam.c * * Video-for-Linux (Version 2) camera capture driver for  * the OMAP24xx camera controller. * * Author: Andy Lowe (source@mvista.com) * * Copyright (C) 2004 MontaVista Software, Inc. * Copyright (C) 2004 Texas Instruments. * * This file is licensed under the terms of the GNU General Public License  * version 2. This program is licensed "as is" without any warranty of any  * kind, whether express or implied. */#include <linux/config.h>#include <linux/init.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/interrupt.h>#include <linux/kdev_t.h>#include <linux/types.h>#include <linux/wait.h>#include <linux/i2c.h>#include <linux/videodev.h>#include <linux/pci.h>		/* needed for videobufs */#include <media/video-buf.h>#include <linux/dma-mapping.h>#include <linux/device.h>#include <linux/input.h>#include <asm/io.h>#include <asm/byteorder.h>#include <asm/scatterlist.h>#include <asm/irq.h>#include <asm/semaphore.h>#include <asm/processor.h>#include <asm/arch/bus.h>#include "omap24xxcam.h"#define CAMERA_OV9640#ifdef CAMERA_OV9640#include "ov9640.h"#endif#include "sensor_if.h"/* configuration macros */#define CAM_NAME "omap24xxcam"#define CONFIG_H4extern struct camera_sensor camera_sensor_if;void omap24xxcam_cleanup(void);/* global variables */static struct omap24xxcam_device *saved_cam;/* module parameters */static int video_nr = -1;	/* video device minor (-1 ==> auto assign) *//* Maximum amount of memory to use for capture buffers. * Default is 4800KB, enough to double-buffer SXGA. */static int capture_mem = 1280*960*2*2;/* Size of video overlay framebuffer.  This determines the maximum image size  * that can be previewed.  Default is 600KB, enough for VGA. */static int overlay_mem = 640*480*2;/* Size of video2_mem framebuffer. This determines the maximum image size which * video2_layer can support. Default is 300 KB. Size of LCD or 320*240.*/static int video2_mem = 320*240*2;/* -------------------------------------------------------------------------- *//* Set the value of the CC_CTRL register in cam->cc_ctrl that is required to  * support the currently selected capture format in cam->pix.  The CC_CTRL bits  * which must be configured are:  NOBT_SYNCHRO, BT_CORRECT, PAR_ORDERCAM,  * PAR_CLK_POL, NOBT_HS_POL, NOBT_VS_POL, PAR_MODE, and CCP_MODE.  The CC_RST,  * CC_FRAME_TRIG, and CC_EN bits are actively managed by the driver and should  * be set to zero by this routine. */static voidomap24xxcam_sensor_cc_ctrl(struct omap24xxcam_device *cam){	struct v4l2_pix_format *pix = &cam->pix;	cam->cc_ctrl = CC_CTRL_NOBT_SYNCHRO | CC_CTRL_NOBT_VS_POL 		| CC_CTRL_PAR_MODE_NOBT8;	switch (pix->pixelformat) {		case V4L2_PIX_FMT_UYVY:		case V4L2_PIX_FMT_RGB565:		case V4L2_PIX_FMT_RGB555:		default:			/* These formats need a 16-bit byte swap */			cam->cc_ctrl |= CC_CTRL_PAR_ORDERCAM;		case V4L2_PIX_FMT_YUYV:		case V4L2_PIX_FMT_RGB565X:		case V4L2_PIX_FMT_RGB555X:			/* These formats don't need a 16-bit byte swap */			break;	}}/* * camera core register I/O routines */static __inline__ u32 cc_reg_in(const struct omap24xxcam_device *cam, u32 offset){	return readl(cam->cam_mmio_base + CC_REG_OFFSET + offset);}static __inline__ u32 cc_reg_out(const struct omap24xxcam_device *cam, u32 offset, u32 val){	writel(val, cam->cam_mmio_base + CC_REG_OFFSET + offset);	return val;}static __inline__ u32 cc_reg_merge(const struct omap24xxcam_device *cam, u32 offset, 		u32 val, u32 mask){	u32 addr = cam->cam_mmio_base + CC_REG_OFFSET + offset;	u32 new_val = (readl(addr) & ~mask) | (val & mask);	writel(new_val, addr);	return new_val;}voidcc_init(const struct omap24xxcam_device *cam){	/* Setting the camera core AUTOIDLE bit causes problems with frame 	 * synchronization, so we will clear the AUTOIDLE bit instead.	 */	//cc_reg_out(cam, CC_SYSCONFIG, 0);	cc_reg_out(cam, CC_SYSCONFIG, CC_SYSCONFIG_AUTOIDLE);}/* * camera DMA register I/O routines */static __inline__ u32 camdma_reg_in(const struct omap24xxcam_device *cam, u32 offset){	return readl(cam->cam_mmio_base + CAMDMA_REG_OFFSET + offset);}static __inline__ u32 camdma_reg_out(const struct omap24xxcam_device *cam, u32 offset, u32 val){	writel(val, cam->cam_mmio_base + CAMDMA_REG_OFFSET + offset);	return val;}static __inline__ u32 camdma_reg_merge(const struct omap24xxcam_device *cam, u32 offset, 		u32 val, u32 mask){	u32 addr = cam->cam_mmio_base + CAMDMA_REG_OFFSET + offset;	u32 new_val = (readl(addr) & ~mask) | (val & mask);	writel(new_val, addr);	return new_val;}voidcamdma_init(const struct omap24xxcam_device *cam){	camdma_reg_out(cam, CAMDMA_OCP_SYSCONFIG, 		CAMDMA_OCP_SYSCONFIG_MIDLEMODE_FSTANDBY 	      | CAMDMA_OCP_SYSCONFIG_SIDLEMODE_FIDLE	      | CAMDMA_OCP_SYSCONFIG_AUTOIDLE);	camdma_reg_merge(cam, CAMDMA_GCR, 0x10, 		CAMDMA_GCR_MAX_CHANNEL_FIFO_DEPTH);}/* * camera MMU register I/O routines */static __inline__ u32 cammmu_reg_in(const struct omap24xxcam_device *cam, u32 offset){	return readl(cam->cam_mmio_base + CAMMMU_REG_OFFSET + offset);}static __inline__ u32 cammmu_reg_out(const struct omap24xxcam_device *cam, u32 offset, u32 val){	writel(val, cam->cam_mmio_base + CAMMMU_REG_OFFSET + offset);	return val;}static __inline__ u32 cammmu_reg_merge(const struct omap24xxcam_device *cam, u32 offset, 		u32 val, u32 mask){	u32 addr = cam->cam_mmio_base + CAMMMU_REG_OFFSET + offset;	u32 new_val = (readl(addr) & ~mask) | (val & mask);	writel(new_val, addr);	return new_val;}voidcammmu_init(const struct omap24xxcam_device *cam){	/* set the camera MMU autoidle bit */	cammmu_reg_out(cam, CAMMMU_SYSCONFIG, CAMMMU_SYSCONFIG_AUTOIDLE);}/* * camera subsystem register I/O routines */static __inline__ u32 cam_reg_in(const struct omap24xxcam_device *cam, u32 offset){	return readl(cam->cam_mmio_base + offset);}static __inline__ u32 cam_reg_out(const struct omap24xxcam_device *cam, u32 offset, u32 val){	writel(val, cam->cam_mmio_base + offset);	return val;}static __inline__ u32 cam_reg_merge(const struct omap24xxcam_device *cam, u32 offset, 		u32 val, u32 mask){	u32 addr = cam->cam_mmio_base + offset;	u32 new_val = (readl(addr) & ~mask) | (val & mask);	writel(new_val, addr);	return new_val;}/* Reset the camera subsystem (camera core, camera DMA, and camera MMU) */static voidcam_reset(const struct omap24xxcam_device *cam, unsigned long timeout_ticks){	unsigned long timeout;		cam_reg_out(cam, CAM_SYSCONFIG, CAM_SYSCONFIG_SOFTRESET);	/* wait for reset to complete */	timeout = jiffies + timeout_ticks;	while (!(cam_reg_in(cam, CAM_SYSSTATUS) & CAM_SYSSTATUS_RESETDONE)		&& time_before(jiffies, timeout))	{		if (!in_atomic()) {			set_current_state(TASK_INTERRUPTIBLE);			schedule_timeout(1);		} else			udelay(10);	}	if (!(cam_reg_in(cam, CAM_SYSSTATUS) & CAM_SYSSTATUS_RESETDONE))	{		printk(KERN_WARNING CAM_NAME 			": timeout waiting for camera subsystem reset\n");	}	return;}/* Initialize the camera subsystem (camera core, camera DMA, and camera MMU) */voidcam_init(const struct omap24xxcam_device *cam){	/* reset the camera subsystem with a timeout of 200ms */	cam_reset(cam, HZ/5);	/* set the camera subsystem autoidle bit */	cam_reg_out(cam, CAM_SYSCONFIG, CAM_SYSCONFIG_AUTOIDLE);	/* initialize the camera MMU */	cammmu_init(cam);	/* initialize the camera DMA controller */	camdma_init(cam);	/* initialize the camera core module */	cc_init(cam);}/* * display controller register I/O routines */static __inline__ u32 dispc_reg_in(const struct omap24xxcam_device *cam, u32 offset){	return readl(cam->dispc_mmio_base + DISPC_REG_OFFSET + offset);}static __inline__ u32 dispc_reg_out(const struct omap24xxcam_device *cam, u32 offset, u32 val){	writel(val, cam->dispc_mmio_base + DISPC_REG_OFFSET + offset);	return val;}static __inline__ u32 dispc_reg_merge(const struct omap24xxcam_device *cam, u32 offset, 		u32 val, u32 mask){	u32 addr = cam->dispc_mmio_base + DISPC_REG_OFFSET + offset;	u32 new_val = (readl(addr) & ~mask) | (val & mask);		writel(new_val, addr);	return new_val;}/* -------------------------------------------------------------------------- *//* Turn off the video overlay window. */static voidomap24xxcam_disable_vlayer(struct omap24xxcam_device *cam, int v){	unsigned long vid_attributes;	vid_attributes = dispc_reg_merge(cam, DISPC_VID_ATTRIBUTES(v), 0, 		DISPC_VID_ATTRIBUTES_ENABLE);	if (vid_attributes & DISPC_VID_ATTRIBUTES_VIDCHANNELOUT) {		/* digital output */		dispc_reg_merge(cam, DISPC_CONTROL, DISPC_CONTROL_GODIGITAL, 			DISPC_CONTROL_GODIGITAL);	}	else {		/* LCD */		dispc_reg_merge(cam, DISPC_CONTROL, DISPC_CONTROL_GOLCD, 			DISPC_CONTROL_GOLCD);	}}/* Flip the video overlay framebuffer.  The video overlay window may initially  * be either enabled or disabled.  The overlay window will be enabled by this  * routine.  fb_base_phys is the physical base address of the framebuffer for  * the video overlay.  The address programmed into the base address register of  * the video overlay window is calculated based on the cropped size and the full * size of the overlay framebuffer.  */static voidomap24xxcam_flip_overlay(struct omap24xxcam_device *cam, 	unsigned long fb_base_phys){	unsigned long vid_attributes;	int v = cam->vid1;	unsigned long cropped_base_phys;	struct v4l2_rect *crop = &cam->crop;	struct v4l2_pix_format *pix = &cam->pix;	cropped_base_phys = fb_base_phys 		+ pix->bytesperline*crop->top + crop->left*2;	dispc_reg_out(cam, DISPC_VID_BA0(v), cropped_base_phys);	dispc_reg_out(cam, DISPC_VID_BA1(v), cropped_base_phys);	vid_attributes = dispc_reg_merge(cam, DISPC_VID_ATTRIBUTES(v), 		DISPC_VID_ATTRIBUTES_ENABLE, DISPC_VID_ATTRIBUTES_ENABLE);	if (vid_attributes & DISPC_VID_ATTRIBUTES_VIDCHANNELOUT) {		/* digital output */		dispc_reg_merge(cam, DISPC_CONTROL, DISPC_CONTROL_GODIGITAL, 			DISPC_CONTROL_GODIGITAL);	}	else {		/* LCD */		dispc_reg_merge(cam, DISPC_CONTROL, DISPC_CONTROL_GOLCD, 			DISPC_CONTROL_GOLCD);	}}/* Get the framebuffer parameters by reading the display controller registers  * for the graphics window. */static voidomap24xxcam_g_fbuf(struct omap24xxcam_device *cam){	struct v4l2_framebuffer *fbuf = &cam->fbuf;	unsigned long gfx_size, gfx_position;	/* This routine makes some assumptions about the framebuffer driver.  	 * First, the entire contents of the graphics framebuffer must be 	 * displayed, i.e. a configuration in which part of the graphics 	 * framebuffer is offscreen is not supported.  The graphics 	 * window must not be resized or repositioned while capture preview is 	 * active.  The rotation capabilities of the display controller must 	 * not be used to rotate the graphics window.	 */	fbuf->capability = V4L2_FBUF_CAP_EXTERNOVERLAY 		| V4L2_FBUF_CAP_CHROMAKEY;	gfx_size = dispc_reg_in(cam, DISPC_GFX_SIZE);	fbuf->fmt.width = 1 + ((gfx_size & DISPC_GFX_SIZE_GFXSIZEX) 		>> DISPC_GFX_SIZE_GFXSIZEX_SHIFT);	fbuf->fmt.height = 1 + ((gfx_size & DISPC_GFX_SIZE_GFXSIZEY) 		>> DISPC_GFX_SIZE_GFXSIZEY_SHIFT);	gfx_position = dispc_reg_in(cam, DISPC_GFX_POSITION);	cam->gfx_position_x = (gfx_position & DISPC_GFX_POSITION_GFXPOSX)		>> DISPC_GFX_POSITION_GFXPOSX_SHIFT;	cam->gfx_position_y = (gfx_position & DISPC_GFX_POSITION_GFXPOSY)		>> DISPC_GFX_POSITION_GFXPOSY_SHIFT;	cam->gfx_attributes = dispc_reg_in(cam, DISPC_GFX_ATTRIBUTES);}/* Return the default overlay cropping rectangle in crop given the image capture * size in cam->pix and the video display size in cam->fbuf.  The default  * cropping rectangle is the largest rectangle no larger than the capture size  * that will fit on the display.  The default cropping rectangle is centered in  * the captured image.  All dimensions and offsets are rounded down to even  * numbers. */static voidomap24xxcam_default_crop_rect(struct omap24xxcam_device *cam, 	struct v4l2_rect *crop){	struct v4l2_pix_format *pix = &cam->pix;	struct v4l2_framebuffer *fbuf = &cam->fbuf;	crop->width = (pix->width < fbuf->fmt.width) ? 				pix->width : fbuf->fmt.width;	crop->height = (pix->height < fbuf->fmt.height) ? 				pix->height : fbuf->fmt.height;	crop->width &= ~1;	crop->height &= ~1;	crop->left = ((pix->width - crop->width) >> 1) & ~1;	crop->top = ((pix->height - crop->height) >> 1) & ~1;}/* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to  * the nearest supported configuration.  The image preview window cam->win will  * also be adjusted if necessary.  The preview window is adjusted such that the  * horizontal and vertical rescaling ratios stay constant.  If the preview  * window would fall outside the display boundaries, the cropping rectangle will 

⌨️ 快捷键说明

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