📄 h3600_backpaq_core.c
字号:
} if ( (status = h3600_backpaq_fpga_status()) != 0) return status; /* We have a valid set of data */ down(&cam->lock); set_camera_resolution( cam, vm.format, vm.width, vm.height ); update_camera_params(cam); retval = grab_streaming_frame(cam, vm.frame ); if ( !retval ) { if ( cam->frame[vm.frame].state == FRAME_FULL ) { retval = process_frame(cam, NULL, vm.frame); if ( retval > 0 ) retval = 0; } }// else {// CAMDEBUG( " ** Camera CAPTURE returned %d\n", retval);// } up(&cam->lock); break; } /* This SYNC doesn't do much...in the future, we may wish to key a bottom half to do video processing for on UNUSED frames */ case VIDIOCSYNC: { int frame; int status;// CAMDEBUG(" ** Camera SYNC : fpga status %d\n", h3600_backpaq_fpga_status()); if (copy_from_user((void *)&frame, arg, sizeof(int))) { retval = -EFAULT; break; } if (frame<0 || frame >= NUMBER_OF_FRAMES) { retval = -EINVAL; break; } if ( (status = h3600_backpaq_fpga_status()) != 0) return status; down(&cam->lock); sync_frame(cam, frame); up(&cam->lock); break; } /* We don't implement overlay with this camera */ case VIDIOCCAPTURE: retval = -EINVAL; break; case VIDIOCGFBUF: retval = -EINVAL; break; case VIDIOCSFBUF: retval = -EINVAL; break; case VIDIOCKEY: retval = -EINVAL; break; /* We have no tuner interface */ case VIDIOCGTUNER: retval = -EINVAL; break; case VIDIOCSTUNER: retval = -EINVAL; break; case VIDIOCGFREQ: retval = -EINVAL; break; case VIDIOCSFREQ: retval = -EINVAL; break; /* We have no audio interface */ case VIDIOCGAUDIO: retval = -EINVAL; break; case VIDIOCSAUDIO: retval = -EINVAL; break; default: retval = -ENOIOCTLCMD; break; } return retval;}static int h3600_camera_mmap(struct video_device *dev, const char *adr, unsigned long size){ struct h3600_camera_struct *cam = (struct h3600_camera_struct *) dev; unsigned long start = (unsigned long)adr; unsigned long page, pos; int retval; int status = h3600_backpaq_fpga_status(); if ( status ) return status; if (!cam) return -ENODEV; if (size > NUMBER_OF_FRAMES * HC_MAX_PROCESSED_FRAME_SIZE) return -EINVAL; /* make this _really_ smp-safe */ if (down_interruptible(&cam->lock)) return -EINTR; if (!cam->frame_buf) { /* we do lazy allocation */ if ((retval = allocate_frame_buf(cam))) { up(&cam->lock); return retval; } } pos = (unsigned long)(cam->frame_buf); while (size > 0) { page = kvirt_to_pa(pos); if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) { up(&cam->lock); return -EAGAIN; } start += PAGE_SIZE; pos += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } up(&cam->lock); return 0;}static int h3600_camera_open( struct video_device *dev, int flags ){ struct h3600_camera_struct *cam = (struct h3600_camera_struct *) dev; int retval = 0; int status = h3600_backpaq_fpga_status(); if ( status ) return status; if ( cam->usage_count > 0 ) { CAMDEBUG(" Camera already open\n"); return -EBUSY; } down(&cam->lock); cam->usage_count++; stop_capture(cam); cam->state = HC_V4L_IDLE; GPDR &= ~GPIO_H3600_OPT_IRQ; /* GPIO line as input */ set_GPIO_IRQ_edge( GPIO_H3600_OPT_IRQ, GPIO_RISING_EDGE ); /* Rising edge */ retval = request_irq(IRQ_GPIO_H3600_OPT_IRQ, fpga_interrupt, SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, "Backpaq FPGA", (void *)dev); up(&cam->lock); MOD_INC_USE_COUNT; return retval;}static void h3600_camera_close( struct video_device *dev ){ struct h3600_camera_struct *cam = (struct h3600_camera_struct *) dev; down(&cam->lock); if ( --cam->usage_count == 0 ) { if (!h3600_backpaq_fpga_status()) stop_capture(cam); cam->state = HC_V4L_IDLE; free_irq(IRQ_GPIO_H3600_OPT_IRQ, (void *)dev); } up(&cam->lock); MOD_DEC_USE_COUNT;}int h3600_camera_video_init(struct video_device *vdev){#ifdef CONFIG_PROC_FS // Create proc entry here?#endif return 0;}static struct video_device h3600_camera_template ={ owner: THIS_MODULE, name: "iPAQ H3600 Mercury BackPAQ", type: VID_TYPE_CAPTURE, hardware: VID_HARDWARE_H3600_BACKPAQ, open: h3600_camera_open, close: h3600_camera_close, read: h3600_camera_read, ioctl: h3600_camera_ioctl, mmap: h3600_camera_mmap, initialize: h3600_camera_video_init,};/****************************************************************************** * * Standard initialization * * We should add a check to see if the camera responds and if it is B/W or color * ******************************************************************************/static void free_all_buffers( struct h3600_camera_struct *cam ){ int i; for ( i = 0 ; i < NUMBER_OF_FRAMES ; i++ ) { if ( cam->frame[i].data != NULL ) { vfree(cam->frame[i].local_data); cam->frame[i].local_data = NULL; } } if (cam->frame_buf) { free_frame_buf(cam); cam->frame_buf = NULL; }}static int h3600_camera_startup( struct h3600_camera_struct *cam ){ int i; memset(cam, 0, sizeof(struct h3600_camera_struct)); memcpy(&cam->vdev, &h3600_camera_template, sizeof(h3600_camera_template)); for ( i = 0 ; i < NUMBER_OF_FRAMES ; i++ ) { cam->frame[i].local_data = vmalloc( HC_RAW_BUFFER_SIZE ); if ( !cam->frame[i].local_data ) { CAMERROR(": Unable to allocate frame buffer\n"); free_all_buffers(cam); return -ENOBUFS; } } init_MUTEX(&cam->lock); init_waitqueue_head(&cam->capq); init_waitqueue_head(&cam->i2cq); /* Set up some plausible defaults */ set_camera_type( cam ); cam->state = HC_V4L_IDLE; cam->i2c_status = 0; set_default_params( cam ); return 0;}static int h3600_camera_shutdown( struct h3600_camera_struct *cam ){ /* Toss the interrupt routine if we've messed up a shutdown somewhere */ if ( cam->usage_count > 0 ) { unsigned long flags; save_flags_cli(flags); free_irq(IRQ_GPIO_H3600_OPT_IRQ, (void *)cam); restore_flags(flags); } /* Should we kill the wait queue? */ free_all_buffers( cam ); return 0;}/****************************************************************************** * * /proc/backpaq/camera interface * ******************************************************************************/#ifdef CONFIG_PROC_FSstatic char *palette_names[] = { "","Grey","HI240","RGB565", "RGB24","RGB32","RGB444","YUV422", "YUYV","UYVY","YUV420","YUV411", "RAW","YUV422P","YUV411P","YUV420P", "YUV410P"};static int h3600_camera_read_proc( char *page, char **start, off_t off, int count, int *eof, void *data ){ struct h3600_camera_struct *cam = &hc_camera; char *out = page; int len; out += sprintf(out, "%s\n", BANNER); out += sprintf(out, "CMOS Image Size %d %d\n", HC_TRUE_WIDTH, HC_TRUE_HEIGHT); out += sprintf(out, "CameraType : %s\n",camera_type_names[cam->ctype]); out += sprintf(out, "CameraModel : %d\n", h3600_backpaq_eeprom_shadow.camera & BACKPAQ_EEPROM_CAMERA_TYPE_MASK); out += sprintf(out, "Capture window\n"); out += sprintf(out, " x : %d\n",cam->vwin.x); out += sprintf(out, " y : %d\n",cam->vwin.y); out += sprintf(out, " width : %d\n",cam->vwin.width); out += sprintf(out, " height : %d\n",cam->vwin.height); out += sprintf(out, "Image settings\n"); out += sprintf(out, " brightness : 0x%04x\n",cam->vpic.brightness); out += sprintf(out, " contrast : 0x%04x\n",cam->vpic.contrast); if ( cam->vpic.palette != VIDEO_PALETTE_GREY ) { out += sprintf(out, " hue : 0x%04x\n",cam->vpic.hue); out += sprintf(out, " colour : 0x%.4x\n",cam->vpic.colour); } else { out += sprintf(out, " whiteness : 0x%04x\n",cam->vpic.whiteness); } out += sprintf(out, " depth : %d\n",cam->vpic.depth); out += sprintf(out, " palette : %s\n",palette_names[cam->vpic.palette]); out += sprintf(out, "Imager parameters\n"); switch (cam->ctype) { case H3600_SMAL: out += sprintf(out, " clock divisor : %d (%d Hz)\n", cam->clock_divisor, 1280 / cam->clock_divisor); out += sprintf(out, " power setting : %d\n", cam->power_setting); out += sprintf(out, " gain format : %d\n", cam->gain_format); out += sprintf(out, " power management : 0x%x\n", cam->power_mgmt); out += sprintf(out, " special modes : 0x%x\n", cam->special_modes); out += sprintf(out, " autobright : 0x%x\n", cam->autobright); break; case H3600_PHILIPS: out += sprintf(out, " clock divisor : %d (%d Hz)\n", cam->clock_divisor, 40 / cam->clock_divisor); break; } out += sprintf(out, " interrupt fifo : %d\n", cam->interrupt_fifo); out += sprintf(out, " read polling mode : %d\n", cam->read_polling_mode); out += sprintf(out, " flip : %d\n", cam->flip); out += sprintf(out, "Internal statistics\n"); out += sprintf(out, " fifo highwater : %d\n",cam->capture_stats.fifo_high); out += sprintf(out, " fifo lowwater : %d\n",cam->capture_stats.fifo_low); out += sprintf(out, " vblank interrupts : %d\n",cam->capture_stats.vblank_count); out += sprintf(out, " fifo interrupts : %d\n",cam->capture_stats.fifo_count); out += sprintf(out, " complete frames : %d\n",cam->capture_stats.complete_frames); out += sprintf(out, " missed extra vblank : %d\n",cam->capture_stats.ef_extra_vblank); out += sprintf(out, " fifo overrun : %d\n",cam->capture_stats.ef_fifo_overrun); out += sprintf(out, " incomplete : %d\n",cam->capture_stats.ef_incomplete_frames); out += sprintf(out, " buffer unavil : %d\n",cam->capture_stats.ef_no_capture_buffer); out += sprintf(out, " camera writethru wait: %d\n",cam->capture_stats.camera_writethru_wait); len = out - page; len -= off; if (len < count) { *eof = 1; if (len <= 0) return 0; } else len = count; *start = page + off; return len;}#endif /* CONFIG_PROC_FS *//****************************************************************************** * * Module interface * ******************************************************************************/#ifdef MODULE#define CAMERA_PROC_DIR "backpaq"#define CAMERA_PROC_NAME "backpaq/camera"#define FPGA_MODULE "h3600_backpaq_fpga"static int __init h3600_camera_init( void ){ int retval = 0; /* This module only makes sense if h3600_backpaq_fpga is loaded */ retval = request_module(FPGA_MODULE); if ( retval ) { printk(KERN_ALERT __FILE__ ": unable to load " FPGA_MODULE "\n"); return retval; } printk(KERN_INFO BANNER "\n"); retval = h3600_camera_startup( &hc_camera ); if ( retval ) return retval; if (video_register_device(&hc_camera.vdev, VFL_TYPE_GRABBER, -1)) { printk(KERN_ERR __FILE__ "Unable to register H3600 BackPAQ camera\n"); return -ENODEV; }#ifdef CONFIG_PROC_FS /* Set up the PROC file system entry */ if ( !(proc_backpaq_camera = create_proc_entry(CAMERA_PROC_NAME,0,NULL))) { // Couldn't create - we need to create the "backpaq" directory proc_mkdir(CAMERA_PROC_DIR,0); proc_backpaq_camera = create_proc_entry(CAMERA_PROC_NAME,0,NULL); } if ( proc_backpaq_camera ) proc_backpaq_camera->read_proc = h3600_camera_read_proc; else printk(KERN_ALERT __FILE__ ": unable to create proc entry %s\n", CAMERA_PROC_NAME);#endif#ifdef CONFIG_PM h3600_backpaq_camera_dev = h3600_backpaq_register_device( H3600_BACKPAQ_CAMERA_DEV, 0, h3600_backpaq_camera_callback); printk(KERN_ALERT __FILE__ ": registered pm callback=%p\n", h3600_backpaq_camera_callback);#endif return 0; /* No error */}static void __exit h3600_camera_cleanup( void ){#ifdef CONFIG_PM h3600_backpaq_unregister_device(h3600_backpaq_camera_dev);#endif#ifdef CONFIG_PROC_FS if (proc_backpaq_camera) remove_proc_entry(CAMERA_PROC_NAME,0);#endif h3600_camera_shutdown( &hc_camera ); video_unregister_device(&hc_camera.vdev);}module_init(h3600_camera_init);module_exit(h3600_camera_cleanup);#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -