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

📄 omap1610_camera_hw.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
字号:
/*
 *  linux/drivers/media/video/omap/omap1610_camera_hw.c
 *
 * Copyright (C) 2004 Texas Instruments Inc
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <asm/io.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
#include <linux/interrupt.h>
#include <asm/arch/dma.h>
#include <linux/delay.h>
#include <linux/ioport.h>

#include <asm/arch/clocks.h>
#include <asm/arch/hardware.h>
#include "camera_core.h"
#include "omap_camera_if.h"
#include "omap1610_camera_hw.h"

camera_regs_t *camera_regs= NULL;
static wait_queue_head_t vsync_wait;
void omap1610_waitfvsync(void);
static void camif_wait_for_vsync_edge(u32 );
extern int dma_channel_number1;
extern int ck_get_rate(ck_t);
int omap1610_set_xclk (int , int );

void omap1610_camera_initenable (void)
{
#ifdef CONFIG_MACH_OMAP_H3
	camera_regs->gpio = 0;    /*enable camera */
#else
	camera_regs->gpio = 1;    /*enable camera */
#endif
	/* give clock to camera_module */
	camera_regs->ctrlclock = 0x00000035;
	camera_regs->mode = 0;
	mdelay(10);
	
}

/* Enables the camera. Takes camera out of reset. Enables the clocks. */ 
void omap1610_camera_enable (int mclk)
{
#ifdef CONFIG_MACH_OMAP_H3
	camera_regs->gpio = 0;    /*enable camera */
#else
	camera_regs->gpio = 1;    /*enable camera */
#endif

	/* give clock to camera_module */
	camera_regs->mode = 0x4000;
	camera_regs->ctrlclock = 0x00000030;
#ifdef CONFIG_MACH_OMAP_H3
	omap1610_set_xclk(24000000, mclk);
#endif
	mdelay(10);
	/* wait for camera to settle down */
	camif_wait_for_vsync_edge(EN_V_DOWN);
	camif_wait_for_vsync_edge(EN_V_DOWN);
	camif_wait_for_vsync_edge(EN_V_DOWN);
	
}
void omap1610_close(void)
{
	camera_regs->mode = 0x0;

	camera_regs->ctrlclock = 0x00000000;
	omap1610_camera_mode_set(RAZ_FIFO);
	udelay(10);
	omap1610_camera_mode_clear(RAZ_FIFO);
#ifdef CONFIG_MACH_OMAP_H3
	camera_regs->gpio = 1;
#else
	camera_regs->gpio = 0;
#endif
}


/* change the XCLK value */
int omap1610_set_xclk (int xclk, int ocp_clk)
{
	int xclk_val;
	int divisor = 1;
	divisor = ocp_clk/xclk;
	if ( divisor * xclk < ocp_clk)
		++divisor; 

	switch (divisor) {
		case 1:
		case 2:
			xclk_val = FOSCMOD_TC2_CK2;
			break;
		case 3:
			xclk_val = FOSCMOD_TC2_CK3;
			break;
		case 4:
		case 5:
		case 6:
		case 7:
			xclk_val = FOSCMOD_TC2_CK4;
			break;
		case 8:
		case 9:
			xclk_val = FOSCMOD_TC2_CK8;
			break;
		case 10:
		case 11:
			xclk_val = FOSCMOD_TC2_CK10;
			break;
		case 12:
		case 13:
		case 14:
		case 15:
			xclk_val = FOSCMOD_TC2_CK12;
			break;
		case 16:
			xclk_val = FOSCMOD_TC2_CK16;
			break;
		default:
			xclk_val = FOSCMOD_TC2_CK16;
	}
	
	/* Change the XCLK clock */
	camera_regs->ctrlclock &= ~CAMEXCLK_EN;
	camera_regs->ctrlclock &= ~0x7;

	camera_regs->ctrlclock |= xclk_val;

	camera_regs->ctrlclock |= CAMEXCLK_EN;

	return (ocp_clk/divisor);
}


/* Disables all the camera clocks. Put the camera interface in reset. */
void omap1610_camera_disable (void)
{
	camera_regs->ctrlclock = 0;     
	camera_regs->gpio = 1;  
	camera_regs->mode = 0;
}

/* Set the bits in the mode control register specified by mask. */
void omap1610_camera_mode_set (unsigned int mask)
{
	camera_regs->mode |= mask;
}

void omap1610_camera_clk_set (unsigned int mask)
{
	camera_regs->ctrlclock |= mask;
}

void omap1610_camera_clk_clear (unsigned int mask)
{
	camera_regs->ctrlclock &= ~mask;
}


/* clear the bits in the mode control register specified by mask. */
void omap1610_camera_mode_clear (unsigned int mask)
{
	camera_regs->mode &= ~mask;
}

/* Clears the camera data FIFO by setting RAZ_FIFO bit in MODE configuration register. */
void omap1610_clear_fifo (void)
{
	
	camera_regs->ctrlclock &= ~LCLK_EN;
	omap1610_camera_mode_set(RAZ_FIFO);
	udelay(10);
	omap1610_camera_mode_clear(RAZ_FIFO);
	camera_regs->ctrlclock |= LCLK_EN;
}

/* sets the dma threshold value in MODE configuration register. */
void omap1610_set_dma_threshold (void)
{
	camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT);
}

/* Enable the DMA by setting the DMA bit in the MODE configuration register. */
void omap1610_enable_dma (void)
{
	camera_regs->mode |= EN_DMA;
}

/* Disable Lclk and stop dma transfer. */
void omap1610_capture_abort (void)
{
	/*  Turn off the capture hardware  */
	camera_regs->ctrlclock &= ~(LCLK_EN);   
	camera_regs->mode = 0;
}

irqreturn_t omap1610_isr(int irq, void *client_data,
					struct pt_regs *regs)
{
	unsigned int itstat;
	itstat = camera_regs->it_status;
	/* VSYNC UP interrupt */
	if (itstat & V_UP) {
		
		omap1610_clear_fifo();
		omap_start_dma(dma_channel_number1);	
		omap1610_camera_mode_clear(EN_V_UP);
		omap1610_camera_mode_set(EN_DMA | EN_FIFO_FULL);
		wake_up_interruptible(&vsync_wait);
	}
	if( itstat & 0x2){
		wake_up_interruptible(&vsync_wait);
	}
	if( itstat & 0x2){
		omap1610_camera_mode_clear(EN_V_DOWN);
	}
	if( itstat & 0x4)
		printk(" H_UP \n");
	if( itstat & 0x8)
		printk(" H_DOWN \n");
	if( itstat & 0x10){
		omap1610_clear_fifo();
		printk(" FIFO_FULL \n");
	}
	if( itstat & 0x20)
		printk(" DATA_TRANS \n");
	
	return IRQ_HANDLED;
}

static void camif_wait_for_vsync_edge(u32 edge_mask)
{

	omap1610_camera_mode_set(edge_mask);

	/* wait for VSYNC edge */
	do {
		interruptible_sleep_on(&vsync_wait);
	} while (signal_pending(current));

	omap1610_camera_mode_clear(edge_mask);
	omap1610_clear_fifo();
}

void waitforVsync(void)
{

	camera_regs->mode = 0x4002;
	omap1610_camera_mode_set(EN_V_UP);
	do{
		interruptible_sleep_on(&vsync_wait);
	} while (signal_pending(current));
	omap_start_dma(dma_channel_number1);
	

}

void omap1610_cleanup(unsigned long iobase_phys)
{
#ifdef CONFIG_MACH_OMAP_H3
	if(camera_regs) {	
		iounmap((void *)camera_regs);
		camera_regs= NULL;
	}
#endif
	if(iobase_phys) {
		release_mem_region(iobase_phys, CAMERA_IOSIZE);
	}
}

/* 
* Initialise the OMAP1610 camera Interface 
* - Configure the MUX control registers
* - Enable the omap1610 camera.
*/
int omap1610_camera_init (unsigned long * iobase_phys)
{
#ifdef CONFIG_MACH_OMAP_H3
	unsigned long cam_iobase;
#endif

	/* 
	 * Call request_region to reserve the area of 
	 * memory assigned for omap1610 camera interface control registers 
	 */
	if (!request_region(CAMERA_BASE, CAMERA_IOSIZE, "OV9640 Camera")) {
		printk ("OMAP1610 Parallel Camera Interface is already in use\n");
		return -1;
	}
	*iobase_phys = CAMERA_BASE;

#ifdef CONFIG_MACH_OMAP_H3
	cam_iobase = (unsigned long) ioremap (CAMERA_BASE, CAMERA_IOSIZE);
	if (!cam_iobase){
		printk(" CANNOT MAP CAMERA REGISTER \n");
		return -1;
	}
    
	/* Set the base address of the camera registers */
	camera_regs = (camera_regs_t *)cam_iobase;
#else
	camera_regs = (camera_regs_t *)CAMERA_BASE;
#endif
 
	/*
	 * FIXME - Use mux API's instead of directly writing in to MUX registers
	 */
	omap_writel(omap_readl(FUNC_MUX_CTRL_4) & ~(0x1ff << 21), FUNC_MUX_CTRL_4);
	omap_writel(0, FUNC_MUX_CTRL_5);
	omap_writel(omap_readl(PULL_DWN_CTRL_0) & ~(0x1FFF << 17), PULL_DWN_CTRL_0);
	omap_writel(omap_readl(PU_PD_SEL_0) & ~(0x1FFF << 17), PU_PD_SEL_0);
	omap_writel(0xeaef, COMP_MODE_CTRL_0);
	omap_writel(omap_readl(OMAP16XX_RESET_CONTROL) & ~(1 << 5), OMAP16XX_RESET_CONTROL);
	omap_writel(omap_readl(OMAP16XX_RESET_CONTROL) | (1 << 5), OMAP16XX_RESET_CONTROL);
    
	/* Enable peripheral reset */
	omap_writew(omap_readw(ARM_RSTCT2) | (1 << 0), ARM_RSTCT2); 
 
	/* enable peripheral clock */
	omap_writew(omap_readw(ARM_IDLECT2) | (1 << EN_XORPCK), ARM_IDLECT2);

	init_waitqueue_head(&vsync_wait);
 
	/* Enable the camera */
	omap1610_camera_initenable();
 
	return 0;
}

⌨️ 快捷键说明

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