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 + -
显示快捷键?