📄 camif_innovator.c
字号:
return -ENODEV; } if (streaming_active) { dbg("already active!\n"); spin_unlock_irqrestore(&camif_lock, flags); return 0; } if (snapshot_active) { dbg("snapshot is active!\n"); spin_unlock_irqrestore(&camif_lock, flags); return -EINVAL; } capture_buffer = buf; streaming_active = 1; camif_mode_set(EN_V_UP); spin_unlock_irqrestore(&camif_lock, flags); return 0;}static int camif_abort(void){ unsigned long flags; spin_lock_irqsave(&camif_lock, flags); camif_mode_clear(EN_V_UP | EN_DMA | EN_V_DOWN | EN_NIRQ | EN_FIFO_FULL); // terminate any in-progress DMA. if (camera_dma_regs) omap_reset_dma((dma_regs_t *)camera_dma_regs); snapshot_active = streaming_active = 0; spin_unlock_irqrestore(&camif_lock, flags); return 0;}static int camif_set_fp(int fp){ int ret, exclk_mhzx10; if (!this->camera) return -ENODEV; if (fp == this->camera->get_frame_period()) return fp; exclk_mhzx10 = fp < 500000 ? 24*10 : 12*10; // first test this frame rate with camera ret = this->camera->set_frame_period(fp, exclk_mhzx10 * 100000, 1); if (ret >= 0) { // frame rate passed tests, apply it. camif_abort(); if (exclk_mhzx10 != current_exclk) { this->camera->close(); camif_stop(); camif_start(exclk_mhzx10); if ((ret = this->camera->open()) < 0) { err("error from camera open\n"); return ret; } } ret = this->camera->set_frame_period(fp, exclk_mhzx10 * 100000, 0); /* * wait a few frames for camera to stabilize */ camif_wait_for_vsync_edge(EN_V_DOWN); camif_wait_for_vsync_edge(EN_V_DOWN); camif_wait_for_vsync_edge(EN_V_DOWN); } return ret;}static void CameraFPGADisable(void){#ifdef CONFIG_ARCH_OMAP1510 // turn off power to camera module outb((inb(INNOVATOR_FPGA_CAM_USB_CONTROL) | 0x04), INNOVATOR_FPGA_CAM_USB_CONTROL);#endif}static void CameraFPGAEnable(void){#ifdef CONFIG_ARCH_OMAP1510 CameraFPGADisable(); udelay(100); // turn on power to camera module outb((inb(INNOVATOR_FPGA_CAM_USB_CONTROL) & ~0x04), INNOVATOR_FPGA_CAM_USB_CONTROL); udelay(100); // reset the camera module outb(inb(OMAP1510P1_FPGA_RST) & ~(1<<4), OMAP1510P1_FPGA_RST); udelay(100); outb(inb(OMAP1510P1_FPGA_RST) | (1<<4), OMAP1510P1_FPGA_RST); udelay(100);#endif}static int camif_open(void){ int ret; if (!this->camera) return 0; // Camera interrupt if ((ret = request_irq(INT_CAMERA, camera_interrupt, SA_INTERRUPT, "camera", NULL))) { err("Failed to acquire camera interrupt\n"); return ret; } if ((ret = omap_request_dma(eCameraRx, "camera dma", dma_callback, NULL, (dma_regs_t **)&camera_dma_regs))) { err("No DMA available for camera\n"); free_irq(INT_CAMERA, NULL); camera_dma_regs = NULL; return ret; } //dbg("Camera DMA at %p\n", camera_dma_regs); omap_dma_setup(eCameraRx, eDmaIn); CameraFPGAEnable(); camif_start(current_exclk); if ((ret = this->camera->open())) { err("Error from Camera open\n"); camif_stop(); CameraFPGADisable(); free_irq(INT_CAMERA, NULL); omap_free_dma((dma_regs_t *)camera_dma_regs); camera_dma_regs = NULL; return ret; } #ifdef MEASURE_FR dmac_sum = dmac_delta = dmac_N = 0;#endif /* * wait a few frames for camera to stabilize */ camif_wait_for_vsync_edge(EN_V_DOWN); camif_wait_for_vsync_edge(EN_V_DOWN); camif_wait_for_vsync_edge(EN_V_DOWN); return ret;}static int camif_close(void){ camif_abort(); if (this->camera) this->camera->close(); camif_stop(); CameraFPGADisable(); free_irq(INT_CAMERA, NULL); omap_free_dma((dma_regs_t *)camera_dma_regs); camera_dma_regs = NULL;#ifdef MEASURE_FR dbg("%lu frames in %lu usecs\n", dmac_N, dmac_sum);#endif return 0;}static int camif_init(void (*callback)(void *), void* data){#ifdef CONFIG_ARCH_OMAP1510 u8 camera_pos;#endif this = &camif_innovator; capture_callback = callback; callback_data = data; if ( is_omap_1623() ) { if (!request_region(OMAP1623_CAMERA_BASE, CAMERA_IOSIZE, "OAMP1623 Camera")) { printk ("OMAP1623 Parallel Camera Interface is already in use\n"); return -ENOMEM; } camera_regs = (camera_regs_t *) ioremap (OMAP1623_CAMERA_BASE, CAMERA_IOSIZE); if (!camera_regs) { printk("CANNOT MAP CAMERA REGISTER\n"); return -ENOMEM; } } else { camera_regs = (camera_regs_t *)CAMERA_BASE; } #ifdef CONFIG_ARCH_OMAP1510 outl(inl(FUNC_MUX_CTRL_0) & ~(1<<28), FUNC_MUX_CTRL_0); outl(inl(FUNC_MUX_CTRL_4) & ~(0x1ff<<21), FUNC_MUX_CTRL_4); outl(0, FUNC_MUX_CTRL_5);#endif#ifdef CONFIG_ARCH_OMAP1610 /* set pin mux control for camera functionality */ outl(inl(FUNC_MUX_CTRL_4) & ~(0x1ff<<21), FUNC_MUX_CTRL_4); outl(0, FUNC_MUX_CTRL_5); outl((inl(FUNC_MUX_CTRL_A) & ~0x7) | 0x6, FUNC_MUX_CTRL_A); /* Enable internal pull-down resistors on Camera interface pins */ outl(inl(PULL_DWN_CTRL_0) & ~(0x1FFF<<17), PULL_DWN_CTRL_0); outl(inl(PU_PD_SEL_0) & ~(0x1FFF<<17), PU_PD_SEL_0); /* Enable internal pull-down on BCLK */ outl(inl(PULL_DWN_CTRL_2) & ~(0x1<<6), PULL_DWN_CTRL_2); outl(inl(PU_PD_SEL_2) & ~(0x1<<6), PU_PD_SEL_2); /* activate above settings */ outl(0xeaef, COMP_MODE_CTRL_0); /* reset camera interface */ outl(inl(RESET_CONTROL) & ~(1<<5), RESET_CONTROL); mdelay(1); outl(inl(RESET_CONTROL) | (1<<5), RESET_CONTROL); mdelay(1);#endif#ifdef CONFIG_ARCH_OMAP730 /* pin mux setup is done in board-specific configuration file, * e.g. perseus2.c. */ /* DPLL clock request */ *((volatile u16 *)SOFT_REQ_REG) |= SOFT_CAM_DPLL_MCK0_REQ; *((volatile u16 *)SOFT_DISABLE_REQ_REG) &= ~((u16)DIS_CAM_DPLL_MCLK_REQ); /* DPLL clock enable request */ OMAP730_CONFIGURE(PCC_CAM_CLK_REQ, ACTIVE); /* Enable the camera clock */ *((volatile u16 *)(CAM_CLK_CTRL)) = SYSTEM_CLK_EN | CAM_CLOCK_EN; mdelay(1);#endif //enable peripheral reset *ARM_RSTCT2 |= (1<<EN_PER); mdelay(1); if ( is_omap_1623() ) /*Enable TC2 clock*/ *ARM_IDLECT3 |= EN_TC2_CK; else //enable peripheral clock *ARM_IDLECT2 |= (1<<EN_XORPCK); mdelay(1); spin_lock_init(&camif_lock); init_waitqueue_head(&vsync_wait); dma_init();#ifdef CONFIG_ARCH_OMAP1510 camera_module_present = 0; camera_pos = inb(INNOVATOR_FPGA_CAM_USB_CONTROL) & 0x03; if (camera_pos == 0x03) { info("camera module not present\n"); // this is not an error return 0; } info("camera module detected, facing %s\n", camera_pos == 2 ? "forward" : "backward");#endif camera_module_present = 1; return 0;}static void camif_cleanup(void) { info("Unloading\n"); CameraFPGADisable(); if (this->camera) this->camera->cleanup(); if (this->sbus) { this->sbus->cleanup(); }}// **************************// Routine: // Description:// **************************static struct camera * camif_camera_detect(void){ struct camera * cam = NULL; ENTRY(); this->camera = NULL; if (!camera_module_present) return NULL; CameraFPGAEnable(); camif_start(current_exclk); // first, select serial bus module#ifdef CONFIG_ARCH_OMAP1510 this->sbus = &camera_sbus_sccb;#else this->sbus = &camera_sbus_new_i2c; //I2C in normal mode#endif // and init the camera serial bus if (this->sbus->init()) { err("error initializing SCCB\n"); goto cam_detect_exit; }#if defined(CONFIG_OMAP_H2) || defined (CONFIG_MACH_OMAP_PERSEUS2) // ------- // Try and detect if an OmniVision 9640 camera is out there. // ------- cam = &camera_ov9640; cam->camif = this; if (cam->detect() == 0) { info("OV9640 camera detected\n"); this->camera = cam; this->camera->init(); goto cam_detect_exit; }#endif // ------- // Try and detect if an OmniVision 6x30 camera is out there. // ------- cam = &camera_ov6x30; cam->camif = this; if (cam->detect() == 0) { info("OV6X30 camera detected\n"); this->camera = cam; this->camera->init(); goto cam_detect_exit; } this->sbus->cleanup(); cam = NULL; cam_detect_exit: camif_stop(); CameraFPGADisable(); return cam;}static void* camif_alloc_image_buffer(int size){ return (void*)__get_dma_pages(GFP_KERNEL, get_order(size));}static void camif_free_image_buffer(void* buffer, int size){ free_pages((unsigned long)buffer, get_order(size));}struct camera_interface camif_innovator = { camera_detect: camif_camera_detect, alloc_image_buffer: camif_alloc_image_buffer, free_image_buffer: camif_free_image_buffer, init: camif_init, cleanup: camif_cleanup, open: camif_open, close: camif_close, snapshot: camif_snapshot, start_streaming: camif_start_streaming, abort: camif_abort, set_frame_period: camif_set_fp,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -