📄 bfin_ppifcd.c
字号:
/* * File: drivers/char/bfin_ppifcd.c * Based on: * Author: Michael Hennerich * * Created: Sept. 10th 2004 * Description: Simple PPI Frame Capture driver for ADSP-BF5xx * * Rev: $Id: bfin_ppifcd.c 4091 2008-01-10 14:17:04Z hennerich $ * * Modified: * Copyright 2004-2008 Analog Devices Inc. * * Bugs: Enter bugs at http://blackfin.uclinux.org/ * * 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, see the file COPYING, or write * to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include <linux/kernel.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/wait.h>#include <linux/poll.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/string.h>#include <linux/spinlock.h>#include <linux/delay.h>#include <linux/miscdevice.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/blackfin.h>#include <asm/dma.h>#include <asm/cacheflush.h>#include <asm/portmux.h>#include <asm/gpio.h>#include "bfin_ppifcd.h"/************************************************************//* manual fix for use this driver with BF561 (2 PPI) */#ifdef _CDEF_BF561_H#ifdef CH_PPI#undef CH_PPI#endif#define CAM_2 // use 1 for CAM_1 on EXT board, use 2 for CAM_2 on EXT board, currently just support 1 CAM at once#ifdef CAM_1/* Parallel Peripheral Interface (PPI) 0 registers (0xFFC0 1000-0xFFC0 10FF) */#define CH_PPI (CH_PPI0) //mach-bf561/dma.h#define bfin_read_PPI_CONTROL() bfin_read_PPI0_CONTROL()#define bfin_write_PPI_CONTROL(val) bfin_write_PPI0_CONTROL(val)#define bfin_read_PPI_STATUS() bfin_read_PPI0_STATUS()#define bfin_write_PPI_STATUS(val) bfin_write_PPI0_STATUS(val)#define bfin_clear_PPI_STATUS() bfin_clear_PPI0_STATUS()#define bfin_read_PPI_COUNT() bfin_read_PPI0_COUNT()#define bfin_write_PPI_COUNT(val) bfin_write_PPI0_COUNT(val)#define bfin_read_PPI_DELAY() bfin_read_PPI0_DELAY()#define bfin_write_PPI_DELAY(val) bfin_write_PPI0_DELAY(val)#define bfin_read_PPI_FRAME() bfin_read_PPI0_FRAME()#define bfin_write_PPI_FRAME(val) bfin_write_PPI0_FRAME(val)u16 ppifcd_ppi_req[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, P_PPI0_D0,\ P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, P_PPI0_D6,\ P_PPI0_D7, 0};#endif#ifdef CAM_2/* Parallel Peripheral Interface (PPI) 1 registers (0xFFC0 1300-0xFFC0 13FF) */#define CH_PPI (CH_PPI1) //mach-bf561/dma.h#define bfin_read_PPI_CONTROL() bfin_read_PPI1_CONTROL()#define bfin_write_PPI_CONTROL(val) bfin_write_PPI1_CONTROL(val)#define bfin_read_PPI_STATUS() bfin_read_PPI1_STATUS()#define bfin_write_PPI_STATUS(val) bfin_write_PPI1_STATUS(val)#define bfin_clear_PPI_STATUS() bfin_clear_PPI1_STATUS()#define bfin_read_PPI_COUNT() bfin_read_PPI1_COUNT()#define bfin_write_PPI_COUNT(val) bfin_write_PPI1_COUNT(val)#define bfin_read_PPI_DELAY() bfin_read_PPI1_DELAY()#define bfin_write_PPI_DELAY(val) bfin_write_PPI1_DELAY(val)#define bfin_read_PPI_FRAME() bfin_read_PPI1_FRAME()#define bfin_write_PPI_FRAME(val) bfin_write_PPI1_FRAME(val)u16 ppifcd_ppi_req[] = {P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2, P_PPI1_D0,\ P_PPI1_D1, P_PPI1_D2, P_PPI1_D3, P_PPI1_D4, P_PPI1_D5, P_PPI1_D6,\ P_PPI1_D7, 0};#endif#elseu16 ppifcd_ppi_req[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, P_PPI0_D0,\ P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, P_PPI0_D6,\ P_PPI0_D7, 0};#endif/************************************************************//* definitions */#define PPI1_MINOR 248#define PPI_DEVNAME "PPIFCP"#define PPI_INTNAME "PPI-FCP-INT" /* Should be less than 19 chars. *//************************************************************/typedef struct PPI_Device_t { int opened; int nonblock; unsigned short irqnum; unsigned short done; unsigned short dma_config; unsigned short pixel_per_line; unsigned short lines_per_frame; unsigned short bpp; unsigned short ppi_control; unsigned short ppi_status; unsigned short ppi_delay; short ppi_trigger_gpio; struct fasync_struct *fasyc; wait_queue_head_t *rx_avail;} ppi_device_t;/************************************************************//* Globals */static DECLARE_WAIT_QUEUE_HEAD(ppirxq0);static ppi_device_t ppiinfo;static DEFINE_SPINLOCK(ppifcd_lock);/* * FUNCTION NAME: ppifcd_reg_reset * * INPUTS/OUTPUTS: * in_idev - device number , other unavailable. * VALUE RETURNED: * void * * FUNCTION(S) CALLED: * * GLOBAL VARIABLES REFERENCED: * * GLOBAL VARIABLES MODIFIED: NIL * * DESCRIPTION: Reset PPI to initialization state. * * CAUTION: */void ppifcd_reg_reset(ppi_device_t *pdev){/* Do some initializaion stuff here based on the defined Camera Module so we don't have to use ioctls */ bfin_clear_PPI_STATUS(); bfin_write_PPI_CONTROL(pdev->ppi_control & ~PORT_EN); bfin_write_PPI_DELAY(pdev->ppi_delay); bfin_write_PPI_COUNT(pdev->pixel_per_line - 1); bfin_write_PPI_FRAME(pdev->lines_per_frame); return;}/* * FUNCTION NAME: ppifcd_irq * * INPUTS/OUTPUTS: * in_irq - Interrupt vector number. * in_dev_id - point to device information structure base address. * in_regs - unuse here. * * VALUE RETURNED: * void * * FUNCTION(S) CALLED: * * GLOBAL VARIABLES REFERENCED: ppiinfo * * GLOBAL VARIABLES MODIFIED: NIL * * DESCRIPTION: ISR of PPI * * CAUTION: */static irqreturn_t ppifcd_irq(int irq, void *dev_id, struct pt_regs *regs){ ppi_device_t *pdev = (ppi_device_t *) dev_id;//printk(KERN_INFO "PPIFCD_irg: Interrupt triggered\n"); pr_debug("ppifcd_irq:\n");//printk(KERN_INFO "PPIFCD_irg: Acknowledge DMA Interrupt (clear DMA interrupt state)\n"); /* Acknowledge DMA Interrupt */ clear_dma_irqstat(CH_PPI); /* disable ppi *///printk(KERN_INFO "PPIFCD_irg: Disable PPI\n"); bfin_write_PPI_CONTROL(pdev->ppi_control & ~PORT_EN);//printk(KERN_INFO "PPIFCD_irg: Set DONE flag\n"); pdev->done = 1; /* Give a signal to user program. *///printk(KERN_INFO "PPIFCD_irg: Give a signal to user program (fasyc)\n"); if (pdev->fasyc) kill_fasync(&(pdev->fasyc), SIGIO, POLLIN);//printk(KERN_INFO "PPIFCD_irg: wake_up_interruptible pdev->done=%d\n", pdev->done); pr_debug("ppifcd_irq: wake_up_interruptible pdev->done=%d\n", pdev->done); /* wake up read *///printk(KERN_INFO "PPIFCD_irg: wake up read\n"); wake_up_interruptible(pdev->rx_avail);//printk(KERN_INFO "PPIFCD_irg: Return\n"); pr_debug("ppifcd_irq: return\n"); return IRQ_HANDLED;}static irqreturn_t ppifcd_irq_error(int irq, void *dev_id, struct pt_regs *regs){ ppi_device_t *pdev = (ppi_device_t *) dev_id;//printk(KERN_ERR "PPIFCD_error_irq: DMA data transfer ERROR, irq_error triggered\n"); pr_debug("ppifcd_error_irq:\n"); pr_debug("PPI Status = 0x%X\n", bfin_read_PPI_STATUS()); bfin_clear_PPI_STATUS(); /* Acknowledge DMA Interrupt */ clear_dma_irqstat(CH_PPI); /* disable ppi */ bfin_write_PPI_CONTROL(pdev->ppi_control & ~PORT_EN); pdev->done = 1; /* Give a signal to user program. */ if (pdev->fasyc) kill_fasync(&(pdev->fasyc), SIGIO, POLLIN); pr_debug("ppifcd_error_irq: wake_up_interruptible pdev->done=%d\n", pdev->done); /* wake up read */ wake_up_interruptible(pdev->rx_avail); pr_debug("ppifcd_error_irq: return\n"); return IRQ_HANDLED;}/* * FUNCTION NAME: ppi_ioctl * * INPUTS/OUTPUTS: * in_inode - Description of openned file. * in_filp - Description of openned file. * in_cmd - Command passed into ioctl system call. * in/out_arg - It is parameters which is specified by last command * * RETURN: * 0 OK * -EINVAL Invalid * * FUNCTION(S) CALLED: * * GLOBAL VARIABLES REFERENCED: ppiinfo * * GLOBAL VARIABLES MODIFIED: NIL * * DESCRIPTION: * * CAUTION: */static int ppi_ioctl(struct inode *inode, struct file *filp, uint cmd, unsigned long arg){ u_long value; ppi_device_t *pdev = filp->private_data; switch (cmd) { case CMD_PPI_SET_PIXELS_PER_LINE: {//printk(KERN_INFO "PPI_ioctl: CMD_PPI_SET_PIXELS_PER_LINE %d\n", (unsigned short)arg); pr_debug("ppi_ioctl: CMD_PPI_SET_PIXELS_PER_LINE\n"); pdev->pixel_per_line = (unsigned short)arg; bfin_write_PPI_COUNT(pdev->pixel_per_line - 1); break; } case CMD_PPI_SET_LINES_PER_FRAME: {//printk(KERN_INFO "PPI_ioctl: CMD_PPI_SET_LINES_PER_FRAME %d\n", (unsigned short)arg); pr_debug("ppi_ioctl: CMD_PPI_SET_LINES_PER_FRAME\n"); pdev->lines_per_frame = (unsigned short)arg; bfin_write_PPI_FRAME(pdev->lines_per_frame); break; } case CMD_PPI_SET_PPICONTROL_REG: {//printk(KERN_INFO "PPI_ioctl: CMD_PPI_SET_PPICONTROL_REG 0x%x\n", (unsigned short)arg); pr_debug("ppi_ioctl: CMD_PPI_SET_PPICONTROL_REG\n"); pdev->ppi_control = ((unsigned short)arg) & ~PORT_EN; bfin_write_PPI_CONTROL(pdev->ppi_control); break; } case CMD_PPI_SET_PPIDELAY_REG: {//printk(KERN_INFO "PPI_ioctl: CMD_PPI_SET_PPIDELAY_REG %d\n", (unsigned short)arg); pr_debug("ppi_ioctl: CMD_PPI_SET_PPIDELAY_REG\n"); pdev->ppi_delay = (unsigned short)arg; bfin_write_PPI_DELAY(pdev->ppi_delay); break; } case CMD_SET_TRIGGER_GPIO: {//printk(KERN_INFO "PPI_ioctl: CMD_SET_TRIGGER_GPIO %d\n", (unsigned short)arg); pr_debug("ppi_ioctl: CMD_SET_TRIGGER_GPIO\n"); pdev->ppi_trigger_gpio = (unsigned short)arg; if (pdev->ppi_trigger_gpio == NO_TRIGGER) { break; } if (gpio_request(pdev->ppi_trigger_gpio, PPI_DEVNAME)) { printk(KERN_ERR"Requesting GPIO %d faild\n", pdev->ppi_trigger_gpio); return -EFAULT; } gpio_direction_output(pdev->ppi_trigger_gpio, 0); break; } case CMD_PPI_GET_ALLCONFIG: {//printk(KERN_INFO "PPI_ioctl: CMD_PPI_GET_ALLCONFIG (Fix me)\n"); break; } case CMD_PPI_GET_SYSTEMCLOCK: { value = get_sclk();//printk(KERN_INFO "PPI_ioctl: CMD_PPI_GET_SYSTEMCLOCK SCLK: %d\n", (int)value); pr_debug ("ppi_ioctl: CMD_PPI_GET_SYSTEMCLOCK SCLK: %d \n", (int)value); copy_to_user((unsigned long *)arg, &value, sizeof(unsigned long)); break; } default: return -EINVAL; } return 0;}/* * FUNCTION NAME: ppi_fasync *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -