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

📄 bfin_ppifcd.c

📁 This is the source code of Camera driver for OV2640 camera from OmniVision using in Blackfin platfor
💻 C
📖 第 1 页 / 共 2 页
字号:
 * INPUTS/OUTPUTS: * in_fd - File descriptor of openned file. * in_filp - Description of openned file. * * RETURN: * * FUNCTION(S) CALLED: * * GLOBAL VARIABLES REFERENCED: ppiinfo * * GLOBAL VARIABLES MODIFIED: NIL * * DESCRIPTION: It is invoked when user changes status of sync *              it resister a hook in system. When there is *              data coming, user program would get a signal. * * CAUTION: */static int ppi_fasync(int fd, struct file *filp, int on){	ppi_device_t *pdev = filp->private_data;	return fasync_helper(fd, filp, on, &(pdev->fasyc));}/* * FUNCTION NAME: ppi_read * * INPUTS/OUTPUTS: * in_filp - Description of openned file. * in_count - how many bytes user wants to get. * out_buf - data would be write to this address. * * RETURN * positive number: bytes read back * -EINVIL When word size is set to 16, reading odd bytes. * -EAGAIN When reading mode is set to non block and there is no rx data. * * FUNCTION(S) CALLED: * * GLOBAL VARIABLES REFERENCED: ppiinfo * * GLOBAL VARIABLES MODIFIED: NIL * * DESCRIPTION: It is invoked when user call 'read' system call *              to read from system. * * CAUTION: */static ssize_t ppi_read(struct file *filp, char *buf, size_t count,			loff_t * pos){	int ierr;	ppi_device_t *pdev = filp->private_data;//printk(KERN_INFO "PPI_read: Start\n");	pr_debug("ppi_read:\n");	if (count <= 0)		return 0;	pdev->done = 0;	/* Invalidate allocated memory in Data Cache */	blackfin_dcache_invalidate_range((u_long) buf, (u_long) (buf + count));//printk(KERN_INFO "PPI_read: blackfin_dcache_invalidate_range: DONE\n");	pr_debug("ppi_read: blackfin_dcache_invalidate_range : DONE\n");	/* configure ppi port for DMA RX */	set_dma_config(CH_PPI, pdev->dma_config);	set_dma_start_addr(CH_PPI, (u_long) buf);	if (pdev->bpp == 8 && pdev->ppi_control & PACK_EN) {//printk(KERN_INFO "PPI_read: Set DMA X count = %d\n", pdev->pixel_per_line/2);		set_dma_x_count(CH_PPI, pdev->pixel_per_line / 2);	// Div 2 because of 16-bit packing	} else {//printk(KERN_INFO "PPI_read: Set DMA X count = %d\n", pdev->pixel_per_line);		set_dma_x_count(CH_PPI, pdev->pixel_per_line);	}//printk(KERN_INFO "PPI_read: Set DMA Y count = %d\n", pdev->lines_per_frame);	set_dma_y_count(CH_PPI, pdev->lines_per_frame);	if (pdev->bpp > 8 || pdev->dma_config & WDSIZE_16){//printk(KERN_INFO "PPI_read: Set DMA modify = 2\n");		set_dma_x_modify(CH_PPI, 2);		set_dma_y_modify(CH_PPI, 2);	} else {//printk(KERN_INFO "PPI_read: Set DMA modify = 1\n");		set_dma_x_modify(CH_PPI, 1);		set_dma_y_modify(CH_PPI, 1);	}//printk(KERN_INFO "PPI_read: Setup DMA: DONE\n");	pr_debug("ppi_read: SETUP DMA : DONE\n");//printk(KERN_INFO "PPI_read: Enable DMA for PPI channel\n");	enable_dma(CH_PPI);	//SSYNC();	/* Enable PPI *///printk(KERN_INFO "PPI_read: Enable PPI with data length mask: 0x%x\n", pdev->ppi_control & DLENGTH);	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);	SSYNC();	if (pdev->ppi_trigger_gpio > NO_TRIGGER) {		gpio_set_value(pdev->ppi_trigger_gpio, 1);		udelay(1);		gpio_set_value(pdev->ppi_trigger_gpio, 0);	}//printk(KERN_INFO "PPI_read: PPI0 enabled: DONE\n");	pr_debug("ppi_read: PPI ENABLED : DONE\n");	/* Wait for data available *///printk(KERN_INFO "PPI_read: Wait for data available\n");	if (1) {		if (pdev->nonblock) {//printk(KERN_INFO "PPI_read: Use nonblocking mode, return Try Again (Fix me)\n");			return -EAGAIN;		} else {//printk(KERN_INFO "PPI_read: PPI wait_event_interruptible\n");			pr_debug("PPI wait_event_interruptible\n");			ierr =			    wait_event_interruptible(*(pdev->rx_avail),						     pdev->done);			if (ierr) {				/* waiting is broken by a signal *///printk(KERN_INFO "PPI_read: waiting is broken by a signal (Fix me); PPI wait_event_interruptible ierr; Return\n");				pr_debug("PPI wait_event_interruptible ierr\n");				return ierr;			}		}	}//printk(KERN_INFO "PPI_read: PPI wait_event_interruptible done\n");	pr_debug("PPI wait_event_interruptible done\n");//printk(KERN_INFO "PPI_read: Disable DMA for PPI0 channel\n");	disable_dma(CH_PPI);//printk(KERN_INFO "PPI_read: Return %d bytes\n", count);	pr_debug("ppi_read: return\n");	return count;}/* * FUNCTION NAME: ppi_open * * INPUTS/OUTPUTS: * in_inode - Description of openned file. * in_filp - Description of openned file. * * RETURN * 0: Open ok. * -ENXIO  No such device * * FUNCTION(S) CALLED: * * GLOBAL VARIABLES REFERENCED: ppiinfo * * GLOBAL VARIABLES MODIFIED: NIL * * DESCRIPTION: It is invoked when user call 'open' system call *              to open ppi device. * * CAUTION: */static int ppi_open(struct inode *inode, struct file *filp){	char intname[20];	unsigned long flags;	int minor = MINOR(inode->i_rdev);//printk(KERN_INFO "PPI_open: Start\n");	pr_debug("ppi_open:\n");	/* PPI ? */	if (minor != PPI1_MINOR) {//printk(KERN_ERR "PPI_open: Error: wrong minor. Correct is %d\n", minor);		return -ENXIO;	}	spin_lock_irqsave(&ppifcd_lock, flags);	if (ppiinfo.opened) {		spin_unlock_irqrestore(&ppifcd_lock, flags);		return -EMFILE;	}//printk(KERN_INFO "PPI_open: Clear configuration\n");	/* Clear configuration information */	memset(&ppiinfo, 0, sizeof(ppi_device_t));	if (filp->f_flags & O_NONBLOCK)		ppiinfo.nonblock = 1;	ppiinfo.opened = 1;	ppiinfo.done = 0;	ppiinfo.dma_config =	    (DMA_FLOW_MODE | WNR | RESTART | DMA_WDSIZE | DMA2D | DI_EN);	ppiinfo.pixel_per_line = PIXEL_PER_LINE;		// Does it need to be minus 1???	ppiinfo.lines_per_frame = LINES_PER_FRAME;	ppiinfo.bpp = 8;	ppiinfo.ppi_control =	    POL_S | POL_C | PPI_DATA_LEN | PPI_PACKING | CFG_GP_Input_3Syncs |	    GP_Input_Mode;	ppiinfo.ppi_status = 0;	ppiinfo.ppi_delay = 0;	ppiinfo.ppi_trigger_gpio = NO_TRIGGER;	ppiinfo.rx_avail = &ppirxq0;	strcpy(intname, PPI_INTNAME);	ppiinfo.irqnum = IRQ_PPI;	filp->private_data = &ppiinfo;	ppifcd_reg_reset(filp->private_data);	/* Request DMA channel, and pass the interrupt handler *///printk(KERN_INFO "PPI_open: Request DMA channel, and pass the interrupt handler\n");	if (request_dma(CH_PPI, "BF561_PPI_DMA") < 0) {		panic("Unable to attach BlackFin PPI DMA channel\n");		ppiinfo.opened = 0;		spin_unlock_irqrestore(&ppifcd_lock, flags);		return -EFAULT;	} else {//printk(KERN_INFO "PPI_open: Set DMA callback when data transfer complete (PPI interrupt trigger)\n");		set_dma_callback(CH_PPI, (void *)ppifcd_irq,				 filp->private_data);	}//printk(KERN_INFO "PPI_open: Request interupt\n");	request_irq(IRQ_PPI_ERROR, (void *)ppifcd_irq_error, IRQF_DISABLED,		    "PPI ERROR", filp->private_data);	spin_unlock_irqrestore(&ppifcd_lock, flags);//printk(KERN_INFO "PPI_open: Return\n");	pr_debug("ppi_open: return\n");	return 0;}/* * FUNCTION NAME: ppi_release * * INPUTS/OUTPUTS: * in_inode - Description of openned file. * in_filp - Description of openned file. * * RETURN * Always 0 * * FUNCTION(S) CALLED: * * GLOBAL VARIABLES REFERENCED: ppiinfo * * GLOBAL VARIABLES MODIFIED: NIL * * DESCRIPTION: It is invoked when user call 'close' system call *              to close device. * * CAUTION: */static int ppi_release(struct inode *inode, struct file *filp){	unsigned long flags;	ppi_device_t *pdev = filp->private_data;	pr_debug("ppi_release: close()\n");	spin_lock_irqsave(&ppifcd_lock, flags);	/* After finish DMA, release it. */	free_dma(CH_PPI);	free_irq(IRQ_PPI_ERROR, filp->private_data);	if (pdev->ppi_trigger_gpio > NO_TRIGGER)		gpio_free(pdev->ppi_trigger_gpio);	ppifcd_reg_reset(pdev);	pdev->opened = 0;	spin_unlock_irqrestore(&ppifcd_lock, flags);	ppi_fasync(-1, filp, 0);	pr_debug("ppi_release: close() return\n");	return 0;}static struct file_operations ppi_fops = {	owner:   THIS_MODULE,	read:    ppi_read,	ioctl:   ppi_ioctl,	open:    ppi_open,	release: ppi_release,	fasync:  ppi_fasync,};static struct miscdevice bfin_ppi_dev = {	PPI1_MINOR,	"ppi",	&ppi_fops};/* * FUNCTION NAME: ppifcd_init / init_module * * INPUTS/OUTPUTS: * * RETURN: * 0 if module init ok. * -1 init fail. * * FUNCTION(S) CALLED: * * GLOBAL VARIABLES REFERENCED: ppiinfo * * GLOBAL VARIABLES MODIFIED: NIL * * DESCRIPTION: It will be invoked when using 'insmod' command. *              or invoke it directly if ppi module is needed. * * CAUTION: */int __init ppifcd_init(void){	int result;	if (peripheral_request_list(ppifcd_ppi_req, PPI_DEVNAME)) {		printk(KERN_ERR "Requesting Peripherals PPI faild\n");		return -EFAULT;	}	result = misc_register(&bfin_ppi_dev);	if (result < 0) {		printk(KERN_WARNING "PPI: can't get minor %d\n", PPI1_MINOR);		return result;	}	printk(KERN_INFO "PPI: ADSP PPI Frame Capture Driver IRQ:%d \n",	       IRQ_PPI);	return 0;}/* * FUNCTION NAME: ppifcd_uninit / cleanup_module * * INPUTS/OUTPUTS: * * RETURN: * * FUNCTION(S) CALLED: * * GLOBAL VARIABLES REFERENCED: ppiinfo * * GLOBAL VARIABLES MODIFIED: NIL * * DESCRIPTION: It will be invoked when using 'rmmod' command. *              or, you invoke it directly when it needs remove *              ppi module. * * CAUTION: */void __exit ppifcd_uninit(void){	if (ppiinfo.ppi_trigger_gpio != NO_TRIGGER)		gpio_free(ppiinfo.ppi_trigger_gpio);	peripheral_free_list(ppifcd_ppi_req);	misc_deregister(&bfin_ppi_dev);	printk(KERN_ALERT "Goodbye PPI\n");}module_init(ppifcd_init);module_exit(ppifcd_uninit);MODULE_AUTHOR("Michael Hennerich");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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