📄 video_buffer.c
字号:
/* * drivers/char/arca/video_buffer.c * Driver for control Video buffer and get the Finger data. * * Copyright (C) 2003 LingFang Micro System. * * * 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. See * the file "COPYING" in the main directory of this archive * for more details. * */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/slab.h>#include <linux/list.h>#include <linux/arca-chars.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/io.h>#include <asm/delay.h>#include <asm/hardware.h>//SCCB define.#define SCC_PORT_MASK 0x3F#define SCC_DATA_HIGH 0x80 + SCC_PORT_MASK //PA7 -- data#define SCC_DATA_LOW 0x00 + SCC_PORT_MASK#define SCC_CLK_HIGH 0x40 //PA6 -- clock#define SCC_CLK_LOW 0x00/*#define SCC_PORT_MASK 0xCF#define SCC_DATA_HIGH 0x20 + SCC_PORT_MASK //PA5 -- data#define SCC_DATA_LOW 0x00 + SCC_PORT_MASK#define SCC_CLK_HIGH 0x10 //PA4 -- clock#define SCC_CLK_LOW 0x00*/#define SCC_PORT *(unsigned char volatile *)(0xE0000504)//SCCB define end. //The driver's function define#define FIFO_RESET_DELAY 0x20//Windows defines.#define X_START 176#define Y_START 132#define X_WIDTH 296#define Y_WIDTH 300//Windows define end.static int video_buffer_open(struct inode *, struct file *);static int video_buffer_close(struct inode *, struct file *);static ssize_t video_buffer_read(struct file *, char *, unsigned long , loff_t *);static ssize_t video_buffer_write(struct file *, const char *, size_t, loff_t *);static int video_buffer_ioctl(struct inode *, struct file *, unsigned int, unsigned long);static void video_buffer_interrupt(int irq, void *dev_id, struct pt_regs *regs);//This is the address for my video buffer.static unsigned long VIDEO_BUFFER_ADDRESS;//This device's struct.struct video_buffer_dev_struct { int opened; char *name; void *private;} video_buffer_dev;video_buffer_dev_minor = 0x22; //Here are the same number in the /dev/arca/video_buffer nods./*************************************************************************** ** define driver struct. ** ***************************************************************************/static struct file_operations video_buffer_fops ={ open: video_buffer_open, release:video_buffer_close, read: video_buffer_read, write: video_buffer_write, ioctl: video_buffer_ioctl,};//SCCB function define.void sccb_write_ov_sio_data_io(unsigned char devaddress, unsigned char regaddress, unsigned char mydata);void sccb_delay(void){ unsigned long i; for(i=0x0000;i<0xF000;i++) { i++; }}//////////////////////////////////////////////////////////////////////////////////////////////////////*************************************************************************** ** driver open process. ** ***************************************************************************/void reset_7620(void){ unsigned long i; unsigned char data; //__gpiod_write(0xDF); //__gpiod_as_outputs(); *(unsigned char *)(0xE0000534) = 0xD0; *(unsigned long *)(0xE0000530) = 0x00000FF0; *(unsigned char *)(0xE0000534) = 0x10; for(i=0;i<FIFO_RESET_DELAY;i++) {i++;} data = *(unsigned char volatile *)(VIDEO_BUFFER_ADDRESS); data = *(unsigned char volatile *)(VIDEO_BUFFER_ADDRESS + 1); for(i=0;i<FIFO_RESET_DELAY;i++) {i++;} *(unsigned char *)(0xE0000534) = 0xD0; }static int video_buffer_open(struct inode *inode, struct file *filp){ unsigned long i; unsigned char data; unsigned long reg; unsigned char hstart,hend,vstart,vend; if (video_buffer_dev.opened) { printk(KERN_INFO "video_buffer: the device is busy\n"); return -EBUSY; } VIDEO_BUFFER_ADDRESS = ioremap(0x84000000,0x4B000); *(unsigned char *)(0xE0000534) = 0xD0; *(unsigned long *)(0xE0000530) = 0x00000FF0; //*(unsigned long volatile *)(0xE1020008) = 0x02222200; *(unsigned long volatile *)(0xE1020008) = 0x04444400; __gpioa_write(0xFF); __gpioa_as_outputs(); hstart = 0x2F + (X_START/4); hend = hstart + (X_WIDTH/4); vstart = 0x06 + (Y_START/2); vend = vstart - 1 + (Y_WIDTH/2); sccb_write_ov_sio_data_io(0x42,0x28,0x20); sccb_delay(); //sccb_write_ov_sio_data_io(0x42,0x17,0x57); sccb_write_ov_sio_data_io(0x42,0x17,hstart); sccb_delay(); //sccb_write_ov_sio_data_io(0x42,0x18,0xA7); sccb_write_ov_sio_data_io(0x42,0x18,hend); sccb_delay(); //sccb_write_ov_sio_data_io(0x42,0x19,0x2E); sccb_write_ov_sio_data_io(0x42,0x19,vstart); sccb_delay(); //sccb_write_ov_sio_data_io(0x42,0x1A,0xCD); sccb_write_ov_sio_data_io(0x42,0x1A,vend); sccb_delay(); /* for(i=0;i<0x1000000;i++) {i++;} __gpiod_write(0x10); for(i=0;i<0x100000;i++) {i++;} data = *(unsigned char volatile *)(VIDEO_BUFFER_ADDRESS); data = *(unsigned char volatile *)(VIDEO_BUFFER_ADDRESS + 1); for(i=0;i<0x1000000;i++) {i++;} __gpiod_write(0xDF); */ reset_7620(); MOD_INC_USE_COUNT; video_buffer_dev.opened = 1; //printk("The ioremap result for fucking video buffer is %08X.\n",VIDEO_BUFFER_ADDRESS); return 0;}/*************************************************************************** ** driver close process. ** ***************************************************************************/static int video_buffer_close(struct inode *inode, struct file *filp){ MOD_DEC_USE_COUNT; video_buffer_dev.opened = 0; return 0;}/*************************************************************************** ** Read video buffer data. ** ***************************************************************************/static ssize_t video_buffer_read(struct file *filp, char *buf, unsigned long count, loff_t *ppos){ unsigned char mydata; unsigned long i; reset_7620(); //for(i=0;i<(640*480);i++) //for(i=0;i<(320*320);i++) for(i=0;i<(X_WIDTH * Y_WIDTH);i++) { buf[i] = *(unsigned char volatile *)(VIDEO_BUFFER_ADDRESS + i); } return 0x01;}/*************************************************************************** ** Dummy Write data. ** ***************************************************************************/static ssize_t video_buffer_write(struct file *filp, const char *buf, size_t count, loff_t *ppos){ return 0;}/*************************************************************************** ** ioctl function. ** ***************************************************************************/static int video_buffer_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ int val=0; unsigned long value=0; unsigned long flags; switch (cmd) { case 0: return 0x00; case 1: return 0x01; } return -EINVAL;}/*************************************************************************** ** interrupt process routine. ** ***************************************************************************/static void video_buffer_interrupt(int irq, void *dev_id, struct pt_regs *regs){}/*************************************************************************** ** Init routine ** ***************************************************************************/static int __init video_buffer_init(void){ int result; int i; unsigned long value=0; result = arca_register_chrdev(video_buffer_dev_minor, "video_bffer", &video_buffer_fops); return result;}/*************************************************************************** ** exit routine. ** ***************************************************************************/static void __exit video_buffer_exit(void){ printk(KERN_INFO "video_buffer driver exit.\n");}//This is the SCCB function.//The devaddress is the address of OV7620 sensor, it should be 0x42,and decided by the power on pull up/down set.//The regaddress is the address of OV register,//The data is the data you want to change to .void sccb_write_ov_sio_data_io(unsigned char devaddress, unsigned char regaddress, unsigned char mydata){ unsigned char i,j,k; unsigned char data; SCC_PORT = SCC_DATA_HIGH + SCC_CLK_HIGH; //Set data and clock high for start. //data = *(unsigned char volatile *)(0xE0000504); //printk("PORTA is %02X.\n",data); SCC_PORT = SCC_DATA_LOW + SCC_CLK_HIGH; //Set data low for start signal of IIC. //data = *(unsigned char volatile *)(0xE0000504); //printk("PORTA is %02X.\n",data); sccb_delay(); //send device id address. j = 0x80; for(i=0;i<0x08;i++) { k = j & devaddress; if(j == k) { //Send data high when this bit is "1". sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; } else { //Send data low when this bit is "0". sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_LOW; sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_LOW; } j = j>>1; } //send x bit. sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; //send register address. j = 0x80; for(i=0;i<0x08;i++) { k = j & regaddress; if(j == k) { //Send data high when this bit is "1". sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; } else { //Send data low when this bit is "0". sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_LOW; sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_LOW; } j = j>>1; } //send x bit. //*(unsigned char *)(0x60000000) = 0b10000000; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; //send data. j = 0x80; for(i=0;i<0x08;i++) { k = j & mydata; if(j == k) { //Send data high when this bit is "1". sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; } else { //Send data low when this bit is "0". sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_LOW; sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_LOW; } j = j>>1; } //send x bit. sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_LOW; sccb_delay(); sccb_delay(); SCC_PORT = SCC_DATA_LOW + SCC_CLK_HIGH; sccb_delay(); SCC_PORT = SCC_DATA_HIGH + SCC_CLK_HIGH;}MODULE_AUTHOR ("");MODULE_DESCRIPTION ("video_buffer driver");MODULE_LICENSE("GPL");module_init(video_buffer_init);module_exit(video_buffer_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -