⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 meye.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
				return;			udelay(1);		}	}	else		return;	printk(KERN_WARNING "meye: mchip_sync() timeout on reg 0x%x status=0x%x\n", reg, status);}/* sets a value into the register */static inline void mchip_set(int reg, u32 v) {	mchip_sync(reg);	writel(v, meye.mchip_mmregs + reg);}/* get the register value */static inline u32 mchip_read(int reg) {	mchip_sync(reg);	return readl(meye.mchip_mmregs + reg);}/* wait for a register to become a particular value */static inline int mchip_delay(u32 reg, u32 v) {	int n = 10;	while (--n && mchip_read(reg) != v) 		udelay(1);	return n;}/* setup subsampling */static void mchip_subsample(void) {	mchip_set(MCHIP_MCC_R_SAMPLING, meye.params.subsample);	mchip_set(MCHIP_MCC_R_XRANGE, mchip_hsize());	mchip_set(MCHIP_MCC_R_YRANGE, mchip_vsize());	mchip_set(MCHIP_MCC_B_XRANGE, mchip_hsize());	mchip_set(MCHIP_MCC_B_YRANGE, mchip_vsize());	mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);}/* set the framerate into the mchip */static void mchip_set_framerate(void) {	mchip_set(MCHIP_HIC_S_RATE, meye.params.framerate);}/* load some huffman and quantisation tables into the VRJ chip ready   for JPEG compression */static void mchip_load_tables(void) {	int i;	int size;	u16 *tables;	tables = jpeg_huffman_tables(&size);	for (i = 0; i < size / 2; i++)		writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);	tables = jpeg_quantisation_tables(&size, meye.params.quality);	for (i = 0; i < size / 2; i++)		writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);}/* setup the VRJ parameters in the chip */static void mchip_vrj_setup(u8 mode) {	mchip_set(MCHIP_VRJ_BUS_MODE, 5);	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();}/* 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)		ptable_free();}/* sets the DMA parameters into the chip */static void mchip_dma_setup(void) {	int i;	mchip_set(MCHIP_MM_PT_ADDR, meye.mchip_dmahandle);	for (i = 0; i < 4; i++)		mchip_set(MCHIP_MM_FIR(i), 0);	meye.mchip_fnum = 0;}/* 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 = 0;	meye.mchip_mode = MCHIP_HIC_MODE_NOOP;	if (!(mchip_read(MCHIP_HIC_STATUS) & MCHIP_HIC_STATUS_BUSY)) 		return;	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP);	mchip_delay(MCHIP_HIC_CMD, 0);	while (!mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE)) {		/*  resetting HIC */		mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP);		mchip_delay(MCHIP_HIC_CMD, 0);		mchip_set(MCHIP_HIC_CTL, MCHIP_HIC_CTL_SOFT_RESET);		wait_ms(250);		if (i++ > 20) {			printk(KERN_ERR "meye: resetting HIC hanged!\n");			break;		}	}	wait_ms(100);}/****************************************************************************//* 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();	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;		wait_ms(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;		wait_ms(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_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;		wait_ms(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/* 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_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                                                       *//****************************************************************************/static void meye_irq(int irq, void *dev_id, struct pt_regs *regs) {	u32 v;	int reqnr;	v = mchip_read(MCHIP_MM_INTA);	while (1) {		v = mchip_get_frame();		if (!(v & MCHIP_MM_FIR_RDY))			goto out;		switch (meye.mchip_mode) {		case MCHIP_HIC_MODE_CONT_OUT:			if (!meye_emptyq(&meye.grabq, NULL)) {				int nr = meye_pullq(&meye.grabq);				mchip_cont_read_frame(					v, 					meye.grab_fbuffer + gbufsize * nr,					mchip_hsize() * mchip_vsize() * 2);				meye.grab_buffer[nr].state = MEYE_BUF_DONE;				wake_up_interruptible(&meye.grabq.proc_list);			}			break;		case MCHIP_HIC_MODE_CONT_COMP:			if (!meye_emptyq(&meye.grabq, &reqnr)) {				int size;				size = mchip_comp_read_frame(					v,					meye.grab_fbuffer + gbufsize * reqnr,					gbufsize);				if (size == -1)					break;				reqnr = meye_pullq(&meye.grabq);				meye.grab_buffer[reqnr].size = size;				meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;				wake_up_interruptible(&meye.grabq.proc_list);			}			break;		default:			/* do not free frame, since it can be a snap */			goto out;		} /* switch */		mchip_free_frame();	}out: ;}/****************************************************************************//* video4linux integration                                                  *//****************************************************************************/static int meye_open(struct inode *inode, struct file *file) {	int i, err;	err = video_exclusive_open(inode,file);	if (err < 0)		return err;				if (mchip_dma_alloc()) {		printk(KERN_ERR "meye: mchip framebuffer allocation failed\n");		video_exclusive_release(inode,file);		return -ENOBUFS;	}	mchip_hic_stop();	meye_initq(&meye.grabq);	for (i = 0; i < MEYE_MAX_BUFNBRS; i++)		meye.grab_buffer[i].state = MEYE_BUF_UNUSED;	return 0;}static int meye_release(struct inode *inode, struct file *file) {	mchip_hic_stop();	video_exclusive_release(inode,file);	return 0;}static int meye_do_ioctl(struct inode *inode, struct file *file,			 unsigned int cmd, void *arg) {	switch (cmd) {	case VIDIOCGCAP: {		struct video_capability *b = arg;		strcpy(b->name,meye.video_dev.name);		b->type = VID_TYPE_CAPTURE;		b->channels = 1;		b->audios = 0;		b->maxwidth = 640;		b->maxheight = 480;		b->minwidth = 320;		b->minheight = 240;		break;	}	case VIDIOCGCHAN: {		struct video_channel *v = arg;		v->flags = 0;		v->tuners = 0;		v->type = VIDEO_TYPE_CAMERA;		if (v->channel != 0)			return -EINVAL;		strcpy(v->name,"Camera");		break;	}	case VIDIOCSCHAN: {		struct video_channel *v = arg;		if (v->channel != 0)			return -EINVAL;		break;	}	case VIDIOCGPICT: {		struct video_picture *p = arg;		*p = meye.picture;		break;	}	case VIDIOCSPICT: {		struct video_picture *p = arg;		if (p->depth != 2)			return -EINVAL;		if (p->palette != VIDEO_PALETTE_YUV422)			return -EINVAL;		down(&meye.lock);		sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, 				      p->brightness >> 10);		sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, 				      p->hue >> 10);		sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, 				      p->colour >> 10);		sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, 				      p->contrast >> 10);		meye.picture = *p;		up(&meye.lock);		break;	}	case VIDIOCSYNC: {		int *i = arg;		DECLARE_WAITQUEUE(wait, current);		if (*i < 0 || *i >= gbuffers)			return -EINVAL;		switch (meye.grab_buffer[*i].state) {		case MEYE_BUF_UNUSED:			return -EINVAL;		case MEYE_BUF_USING:			add_wait_queue(&meye.grabq.proc_list, &wait);			current->state = TASK_INTERRUPTIBLE;			while (meye.grab_buffer[*i].state == MEYE_BUF_USING) {				schedule();				if(signal_pending(current)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -