meye.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 2,009 行 · 第 1/4 页
C
2,009 行
mchip_set(MCHIP_VRJ_SIGNAL_ACTIVE_LEVEL, 0x1f); mchip_set(MCHIP_VRJ_PDAT_USE, 1); mchip_set(MCHIP_VRJ_IRQ_FLAG, 0xa0); mchip_set(MCHIP_VRJ_MODE_SPECIFY, mode); mchip_set(MCHIP_VRJ_NUM_LINES, mchip_vsize()); mchip_set(MCHIP_VRJ_NUM_PIXELS, mchip_hsize()); mchip_set(MCHIP_VRJ_NUM_COMPONENTS, 0x1b); mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_LO, 0xFFFF); mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_HI, 0xFFFF); mchip_set(MCHIP_VRJ_COMP_DATA_FORMAT, 0xC); mchip_set(MCHIP_VRJ_RESTART_INTERVAL, 0); mchip_set(MCHIP_VRJ_SOF1, 0x601); mchip_set(MCHIP_VRJ_SOF2, 0x1502); mchip_set(MCHIP_VRJ_SOF3, 0x1503); mchip_set(MCHIP_VRJ_SOF4, 0x1596); mchip_set(MCHIP_VRJ_SOS, 0x0ed0); mchip_load_tables();}/* sets the DMA parameters into the chip */static void mchip_dma_setup(dma_addr_t dma_addr){ int i; mchip_set(MCHIP_MM_PT_ADDR, (u32)dma_addr); for (i = 0; i < 4; i++) mchip_set(MCHIP_MM_FIR(i), 0); meye.mchip_fnum = 0;}/* setup for DMA transfers - also zeros the framebuffer */static int mchip_dma_alloc(void){ if (!meye.mchip_dmahandle) if (ptable_alloc()) return -1; return 0;}/* frees the DMA buffer */static void mchip_dma_free(void){ if (meye.mchip_dmahandle) { mchip_dma_setup(0); ptable_free(); }}/* stop any existing HIC action and wait for any dma to complete then reset the dma engine */static void mchip_hic_stop(void){ int i, j; meye.mchip_mode = MCHIP_HIC_MODE_NOOP; if (!(mchip_read(MCHIP_HIC_STATUS) & MCHIP_HIC_STATUS_BUSY)) return; for (i = 0; i < 20; ++i) { mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP); mchip_delay(MCHIP_HIC_CMD, 0); for (j = 0; j < 100; ++j) { if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE)) return; msleep(1); } printk(KERN_ERR "meye: need to reset HIC!\n"); mchip_set(MCHIP_HIC_CTL, MCHIP_HIC_CTL_SOFT_RESET); msleep(250); } printk(KERN_ERR "meye: resetting HIC hanged!\n");}/****************************************************************************//* MCHIP frame processing functions *//****************************************************************************//* get the next ready frame from the dma engine */static u32 mchip_get_frame(void){ u32 v; v = mchip_read(MCHIP_MM_FIR(meye.mchip_fnum)); return v;}/* frees the current frame from the dma engine */static void mchip_free_frame(void){ mchip_set(MCHIP_MM_FIR(meye.mchip_fnum), 0); meye.mchip_fnum++; meye.mchip_fnum %= 4;}/* read one frame from the framebuffer assuming it was captured using a uncompressed transfer */static void mchip_cont_read_frame(u32 v, u8 *buf, int size){ int pt_id; pt_id = (v >> 17) & 0x3FF; ptable_copy(buf, pt_id, size, MCHIP_NB_PAGES);}/* read a compressed frame from the framebuffer */static int mchip_comp_read_frame(u32 v, u8 *buf, int size){ int pt_start, pt_end, trailer; int fsize; int i; pt_start = (v >> 19) & 0xFF; pt_end = (v >> 11) & 0xFF; trailer = (v >> 1) & 0x3FF; if (pt_end < pt_start) fsize = (MCHIP_NB_PAGES_MJPEG - pt_start) * PAGE_SIZE + pt_end * PAGE_SIZE + trailer * 4; else fsize = (pt_end - pt_start) * PAGE_SIZE + trailer * 4; if (fsize > size) { printk(KERN_WARNING "meye: oversized compressed frame %d\n", fsize); return -1; } ptable_copy(buf, pt_start, fsize, MCHIP_NB_PAGES_MJPEG);#ifdef MEYE_JPEG_CORRECTION /* Some mchip generated jpeg frames are incorrect. In most * (all ?) of those cases, the final EOI (0xff 0xd9) marker * is not present at the end of the frame. * * Since adding the final marker is not enough to restore * the jpeg integrity, we drop the frame. */ for (i = fsize - 1; i > 0 && buf[i] == 0xff; i--) ; if (i < 2 || buf[i - 1] != 0xff || buf[i] != 0xd9) return -1;#endif return fsize;}/* take a picture into SDRAM */static void mchip_take_picture(void){ int i; mchip_hic_stop(); mchip_subsample(); mchip_dma_setup(meye.mchip_dmahandle); mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_CAP); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); mchip_delay(MCHIP_HIC_CMD, 0); for (i = 0; i < 100; ++i) { if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE)) break; msleep(1); }}/* dma a previously taken picture into a buffer */static void mchip_get_picture(u8 *buf, int bufsize){ u32 v; int i; mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_OUT); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); mchip_delay(MCHIP_HIC_CMD, 0); for (i = 0; i < 100; ++i) { if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE)) break; msleep(1); } for (i = 0; i < 4; ++i) { v = mchip_get_frame(); if (v & MCHIP_MM_FIR_RDY) { mchip_cont_read_frame(v, buf, bufsize); break; } mchip_free_frame(); }}/* start continuous dma capture */static void mchip_continuous_start(void){ mchip_hic_stop(); mchip_subsample(); mchip_set_framerate(); mchip_dma_setup(meye.mchip_dmahandle); meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT; mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_OUT); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); mchip_delay(MCHIP_HIC_CMD, 0);}/* compress one frame into a buffer */static int mchip_compress_frame(u8 *buf, int bufsize){ u32 v; int len = -1, i; mchip_vrj_setup(0x3f); udelay(50); mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_COMP); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); mchip_delay(MCHIP_HIC_CMD, 0); for (i = 0; i < 100; ++i) { if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE)) break; msleep(1); } for (i = 0; i < 4; ++i) { v = mchip_get_frame(); if (v & MCHIP_MM_FIR_RDY) { len = mchip_comp_read_frame(v, buf, bufsize); break; } mchip_free_frame(); } return len;}#if 0 /* keep *//* uncompress one image into a buffer */static int mchip_uncompress_frame(u8 *img, int imgsize, u8 *buf, int bufsize){ mchip_vrj_setup(0x3f); udelay(50); mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_DECOMP); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); mchip_delay(MCHIP_HIC_CMD, 0); return mchip_comp_read_frame(buf, bufsize);}#endif/* start continuous compressed capture */static void mchip_cont_compression_start(void){ mchip_hic_stop(); mchip_vrj_setup(0x3f); mchip_subsample(); mchip_set_framerate(); mchip_dma_setup(meye.mchip_dmahandle); meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP; mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_COMP); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); mchip_delay(MCHIP_HIC_CMD, 0);}/****************************************************************************//* Interrupt handling *//****************************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)static irqreturn_t meye_irq(int irq, void *dev_id, struct pt_regs *regs)#elsestatic irqreturn_t meye_irq(int irq, void *dev_id)#endif{ u32 v; int reqnr; static int sequence; v = mchip_read(MCHIP_MM_INTA); if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT && meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP) return IRQ_NONE;again: v = mchip_get_frame(); if (!(v & MCHIP_MM_FIR_RDY)) return IRQ_HANDLED; if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, sizeof(int)) != sizeof(int)) { mchip_free_frame(); return IRQ_HANDLED; } mchip_cont_read_frame(v, meye.grab_fbuffer + gbufsize * reqnr, mchip_hsize() * mchip_vsize() * 2); meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2; meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); wake_up_interruptible(&meye.proc_list); } else { int size; size = mchip_comp_read_frame(v, meye.grab_temp, gbufsize); if (size == -1) { mchip_free_frame(); goto again; } if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, sizeof(int)) != sizeof(int)) { mchip_free_frame(); goto again; } memcpy(meye.grab_fbuffer + gbufsize * reqnr, meye.grab_temp, size); meye.grab_buffer[reqnr].size = size; meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); wake_up_interruptible(&meye.proc_list); } mchip_free_frame(); goto again;}/****************************************************************************//* video4linux integration *//****************************************************************************/static int meye_open(struct inode *inode, struct file *file){ int i; if (test_and_set_bit(0, &meye.in_use)) return -EBUSY; mchip_hic_stop(); if (mchip_dma_alloc()) { printk(KERN_ERR "meye: mchip framebuffer allocation failed\n"); clear_bit(0, &meye.in_use); return -ENOBUFS; } for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; kfifo_reset(meye.grabq); kfifo_reset(meye.doneq); return 0;}static int meye_release(struct inode *inode, struct file *file){ mchip_hic_stop(); mchip_dma_free(); clear_bit(0, &meye.in_use); return 0;}static int meyeioc_g_params(struct meye_params *p){ *p = meye.params; return 0;}static int meyeioc_s_params(struct meye_params *jp){ if (jp->subsample > 1) return -EINVAL; if (jp->quality > 10) return -EINVAL; if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63) return -EINVAL; if (jp->framerate > 31) return -EINVAL; mutex_lock(&meye.lock); if (meye.params.subsample != jp->subsample || meye.params.quality != jp->quality) mchip_hic_stop(); /* need restart */ meye.params = *jp; sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, meye.params.sharpness); sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, meye.params.agc); sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, meye.params.picture); mutex_unlock(&meye.lock); return 0;}static int meyeioc_qbuf_capt(int *nb){ if (!meye.grab_fbuffer) return -EINVAL; if (*nb >= gbuffers) return -EINVAL; if (*nb < 0) { /* stop capture */ mchip_hic_stop(); return 0; } if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED) return -EBUSY; mutex_lock(&meye.lock); if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); mutex_unlock(&meye.lock); return 0;}static int meyeioc_sync(struct file *file, void *fh, int *i){ int unused; if (*i < 0 || *i >= gbuffers) return -EINVAL; mutex_lock(&meye.lock); switch (meye.grab_buffer[*i].state) { case MEYE_BUF_UNUSED: mutex_unlock(&meye.lock); return -EINVAL; case MEYE_BUF_USING: if (file->f_flags & O_NONBLOCK) { mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { mutex_unlock(&meye.lock); return -EINTR; } /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); } *i = meye.grab_buffer[*i].size; mutex_unlock(&meye.lock); return 0;}static int meyeioc_stillcapt(void){ if (!meye.grab_fbuffer) return -EINVAL; if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) return -EBUSY; mutex_lock(&meye.lock); meye.grab_buffer[0].state = MEYE_BUF_USING; mchip_take_picture(); mchip_get_picture(meye.grab_fbuffer, mchip_hsize() * mchip_vsize() * 2); meye.grab_buffer[0].state = MEYE_BUF_DONE; mutex_unlock(&meye.lock); return 0;}static int meyeioc_stilljcapt(int *len){ if (!meye.grab_fbuffer) return -EINVAL; if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) return -EBUSY;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?