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

📄 planb.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	leftover1 = 0;	pagei = gbuf->idx;	if(nlines <= 1)	    goto skip;	do {	    int j;	    base = virt_to_bus(pb->rawbuf[pagei]);	    nlpp = (PAGE_SIZE - leftover1) / count / stepsize;	    if(leftover1 >= count) {		tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,						base + leftover1 - count, jump);		i += stepsize;	    }	    for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++)		tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,			base + count * (j * stepsize + 1) + leftover1, jump);	    if(i < nlines) {		int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;		if(lov0 == 0)		    leftover1 = 0;		else {		    if(lov0 > count) {			pb->l_to_addr[fr][gbuf->lnum] = pb->rawbuf[pagei]				+ count * (nlpp * stepsize + 1) + leftover1;			pb->l_to_next_idx[fr][gbuf->lnum] = pagei + 1;			pb->l_to_next_size[fr][gbuf->lnum] = count * stepsize									- lov0;			tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,				virt_to_bus(pb->rawbuf[gbuf->l_fr_addr_idx							+ gbuf->lnum]), jump);			if(++gbuf->lnum > MAX_LNUM) {				/* FIXME: error condition! */				gbuf->lnum--;			}			i += stepsize;		    }		    leftover1 = count * stepsize - lov0;		}	    }	    pagei++;	} while(i < nlines);skip:	tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);	c1 = jump_addr;#endif /* PLANB_GSCANLINE */cmd_tab_data_end:	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->intr_stat),			(fr << 9) | PLANB_FRM_IRQ | PLANB_GEN_IRQ);	/* stop it */	tab_cmd_dbdma(c1, DBDMA_STOP, 0);	eieio();	return c1;}static void planb_irq(int irq, void *dev_id, struct pt_regs * regs){	unsigned int stat, astat;	struct planb *pb = (struct planb *)dev_id;	IDBG("PlanB: planb_irq()\n");	/* get/clear interrupt status bits */	eieio();	stat = readl(&pb->planb_base->intr_stat);	astat = stat & pb->intr_mask;	writel(PLANB_FRM_IRQ & ~astat & stat & ~PLANB_GEN_IRQ,		&pb->planb_base->intr_stat);	IDBG("PlanB: stat = %X, astat = %X\n", stat, astat);	if(astat & PLANB_FRM_IRQ) {		unsigned int	fr = stat >> 9;		gbuf_ptr	gbuf = &pb->gbuf[fr];#ifndef PLANB_GSCANLINE		int		i;#endif		IDBG("PlanB: PLANB_FRM_IRQ\n");		pb->gcount++;		IDBG("PlanB: grab %d: fr = %d, gcount = %d\n",				pb->grabbing, fr, pb->gcount);#ifndef PLANB_GSCANLINE		/* Now that the buffer is full, copy those lines that fell		 * on a page boundary from the spare buffers back to where		 * they belong. */		IDBG("PlanB: %d * %d bytes are being copied over\n",				gbuf->lnum, gbuf->lsize);		for(i = 0; i < gbuf->lnum; i++) {			int first = gbuf->lsize - pb->l_to_next_size[fr][i];			memcpy(pb->l_to_addr[fr][i],				pb->rawbuf[gbuf->l_fr_addr_idx + i],				first);			memcpy(pb->rawbuf[pb->l_to_next_idx[fr][i]],				pb->rawbuf[gbuf->l_fr_addr_idx + i] + first,						pb->l_to_next_size[fr][i]);		}#endif		*gbuf->status = GBUFFER_DONE;		pb->grabbing--;		wake_up_interruptible(&pb->capq);		return;	}	/* incorrect interrupts? */	pb->intr_mask = PLANB_CLR_IRQ;	writel(PLANB_CLR_IRQ, &pb->planb_base->intr_stat);	printk(KERN_ERR "PlanB: IRQ lockup, cleared interrupts"							" unconditionally\n");}/******************************* * Device Operations functions * *******************************/static int planb_open(struct video_device *dev, int mode){	struct planb	*pb = (struct planb *)dev->priv;	int		err;	/* first open on driver? */	if(pb->vid_user + pb->vbi_user == 0) {		if((err = planb_prepare_open(pb)) != 0)			return err;	}	/* first open on video dev? */	if(pb->vid_user == 0) {		if((err = planb_prepare_video(pb)) != 0)			return err;	}	pb->vid_user++;	DBG("PlanB: device opened\n");	MOD_INC_USE_COUNT;	return 0;   }static void planb_close(struct video_device *dev){	struct planb *pb = (struct planb *)dev->priv;	planb_lock(pb);	/* last close? then stop everything... */	if(--pb->vid_user == 0) {		if(pb->overlay) {			planb_dbdma_stop(&pb->planb_base->ch2);			planb_dbdma_stop(&pb->planb_base->ch1);			pb->overlay = 0;		}		planb_close_video(pb);	}	/* last open on PlanB hardware? */	if(pb->vid_user + pb->vbi_user == 0)		planb_prepare_close(pb);	planb_unlock(pb);	DBG("PlanB: device closed\n");	MOD_DEC_USE_COUNT;	return;}static long planb_read(struct video_device *v, char *buf, unsigned long count,				int nonblock){	DBG("planb: read request\n");	return -EINVAL;}static long planb_write(struct video_device *v, const char *buf,				unsigned long count, int nonblock){	DBG("planb: write request\n");	return -EINVAL;}static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg){	struct planb *pb=(struct planb *)dev->priv;  		switch (cmd)	{			case VIDIOCGCAP:		{			struct video_capability b;			DBG("PlanB: IOCTL VIDIOCGCAP\n");			strcpy (b.name, pb->video_dev.name);			b.type = VID_TYPE_OVERLAY | VID_TYPE_CLIPPING |				 VID_TYPE_FRAMERAM | VID_TYPE_SCALES |				 VID_TYPE_CAPTURE;			b.channels = 2;	/* composite & svhs */			b.audios = 0;			b.maxwidth = PLANB_MAXPIXELS;                        b.maxheight = PLANB_MAXLINES;                        b.minwidth = 32; /* wild guess */                        b.minheight = 32;                        if (copy_to_user(arg,&b,sizeof(b)))                                return -EFAULT;			return 0;		}		case VIDIOCSFBUF:		{                        struct video_buffer v;			unsigned int fmt;			DBG("PlanB: IOCTL VIDIOCSFBUF\n");                        if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))                                return -EPERM;                        if (copy_from_user(&v, arg, sizeof(v)))                                return -EFAULT;			planb_lock(pb);			switch(v.depth) {			    /* xawtv only asks for 8 bit in static grey, but			     * there is no way to know what it really means.. */			    case 8:				fmt = VIDEO_PALETTE_GREY;				break;			    case 15:				fmt = VIDEO_PALETTE_RGB555;				break;			    case 32:				fmt = VIDEO_PALETTE_RGB32;				break;			    /* We don't deliver these two... */			    case 16:			    case 24:			    default:				planb_unlock(pb);                                return -EINVAL;			}			if (palette2fmt[fmt].bpp * v.width > v.bytesperline) {				planb_unlock(pb);				return -EINVAL;			}			pb->win.bpp = palette2fmt[fmt].bpp;			pb->win.color_fmt = fmt;			pb->fb.phys = (unsigned long) v.base;			pb->win.sheight = v.height;			pb->win.swidth = v.width;			pb->picture.depth = pb->win.depth = v.depth;			pb->win.bpl = pb->win.bpp * pb->win.swidth;			pb->win.pad = v.bytesperline - pb->win.bpl;                        DBG("PlanB: Display at %p is %d by %d, bytedepth %d,"				" bpl %d (+ %d)\n", v.base, v.width,v.height,				pb->win.bpp, pb->win.bpl, pb->win.pad);			pb->cmd_buff_inited = 0;			if(pb->overlay) {				suspend_overlay(pb);				fill_cmd_buff(pb);				resume_overlay(pb);			}			planb_unlock(pb);			return 0;				}		case VIDIOCGFBUF:		{                        struct video_buffer v;			DBG("PlanB: IOCTL VIDIOCGFBUF\n");			v.base = (void *)pb->fb.phys;			v.height = pb->win.sheight;			v.width = pb->win.swidth;			v.depth = pb->win.depth;			v.bytesperline = pb->win.bpl + pb->win.pad;			if (copy_to_user(arg, &v, sizeof(v)))                                return -EFAULT;			return 0;		}		case VIDIOCCAPTURE:		{			int i;                        if(copy_from_user(&i, arg, sizeof(i)))                                return -EFAULT;			if(i==0) {				DBG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");				if (!(pb->overlay))					return 0;				planb_lock(pb);				pb->overlay = 0;				overlay_stop(pb);				planb_unlock(pb);			} else {				DBG("PlanB: IOCTL VIDIOCCAPTURE Start\n");				if (pb->fb.phys == 0 ||					  pb->win.width == 0 ||					  pb->win.height == 0)					return -EINVAL;				if (pb->overlay)					return 0;				planb_lock(pb);				pb->overlay = 1;				if(!(pb->cmd_buff_inited))					fill_cmd_buff(pb);				overlay_start(pb);				planb_unlock(pb);			}			return 0;		}		case VIDIOCGCHAN:		{			struct video_channel v;			DBG("PlanB: IOCTL VIDIOCGCHAN\n");			if(copy_from_user(&v, arg,sizeof(v)))				return -EFAULT;			v.flags = 0;			v.tuners = 0;			v.type = VIDEO_TYPE_CAMERA;			v.norm = pb->win.norm;			switch(v.channel)			{			case 0:				strcpy(v.name,"Composite");				break;			case 1:				strcpy(v.name,"SVHS");				break;			default:				return -EINVAL;				break;			}			if(copy_to_user(arg,&v,sizeof(v)))				return -EFAULT;			return 0;		}		case VIDIOCSCHAN:		{			struct video_channel v;			DBG("PlanB: IOCTL VIDIOCSCHAN\n");			if(copy_from_user(&v, arg, sizeof(v)))				return -EFAULT;			if (v.norm != pb->win.norm) {				int i, maxlines;				switch (v.norm)				{				case VIDEO_MODE_PAL:				case VIDEO_MODE_SECAM:					maxlines = PLANB_MAXLINES;					break;				case VIDEO_MODE_NTSC:					maxlines = PLANB_NTSC_MAXLINES;					break;				default:					DBG("       invalid norm %d.\n", v.norm);					return -EINVAL;					break;				}				planb_lock(pb);				/* empty the grabbing queue */				while(pb->grabbing)					interruptible_sleep_on(&pb->capq);				pb->maxlines = maxlines;				pb->win.norm = v.norm;				/* Stop overlay if running */				suspend_overlay(pb);				for(i = 0; i < MAX_GBUFFERS; i++)					pb->gbuf[i].norm_switch = 1;				/* I know it's an overkill, but.... */				fill_cmd_buff(pb);				/* ok, now init it accordingly */				saa_init_regs (pb);				/* restart overlay if it was running */				resume_overlay(pb);				planb_unlock(pb);			}			switch(v.channel)			{			case 0:	/* Composite	*/				saa_set (SAA7196_IOCC,					((saa_regs[pb->win.norm][SAA7196_IOCC] &					  ~7) | 3), pb);				break;			case 1:	/* SVHS		*/				saa_set (SAA7196_IOCC,					((saa_regs[pb->win.norm][SAA7196_IOCC] &					  ~7) | 4), pb);				break;			default:				DBG("       invalid channel %d.\n", v.channel);				return -EINVAL;				break;			}			return 0;		}		case VIDIOCGPICT:		{			struct video_picture vp = pb->picture;			DBG("PlanB: IOCTL VIDIOCGPICT\n");			vp.palette = pb->win.color_fmt;			if(copy_to_user(arg,&vp,sizeof(vp)))				return -EFAULT;			return 0;		}		case VIDIOCSPICT:		{			struct video_picture vp;			DBG("PlanB: IOCTL VIDIOCSPICT\n");			if(copy_from_user(&vp,arg,sizeof(vp)))				return -EFAULT;			pb->picture = vp;			/* Should we do sanity checks here? */			planb_lock(pb);			saa_set (SAA7196_BRIG, (unsigned char)			    ((pb->picture.brightness) >> 8), pb);			saa_set (SAA7196_HUEC, (unsigned char)			    ((pb->picture.hue) >> 8) ^ 0x80, pb);			saa_set (SAA7196_CSAT, (unsigned char)			    ((pb->picture.colour) >> 9), pb);			saa_set (SAA7196_CONT, (unsigned char)			    ((pb->picture.contrast) >> 9), pb);			planb_unlock(pb);			return 0;		}		case VIDIOCSWIN:		{			struct video_window	vw;			struct video_clip	clip;			int 			i;						DBG("PlanB: IOCTL VIDIOCSWIN\n");			if(copy_from_user(&vw,arg,sizeof(vw)))				return -EFAULT;			planb_lock(pb);			/* Stop overlay if running */			suspend_overlay(pb);			pb->win.interlace = (vw.height > pb->maxlines/2)? 1: 0;			if (pb->win.x != vw.x ||			    pb->win.y != vw.y ||			    pb->win.width != vw.width ||			    pb->win.height != vw.height ||			    !pb->cmd_buff_inited) {				pb->win.x = vw.x;				pb->win.y = vw.y;				pb->win.width = vw.width;				pb->win.height = vw.height;				fill_cmd_buff(pb);			}                        DBG("PlanB: Window at (%d,%d) size %dx%d\n", vw.x, vw.y, vw.width,				vw.height);

⌨️ 快捷键说明

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