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

📄 planb.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
/* C */	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch2.br_sel),							PLANB_SET(DMA_ABORT));	/* this points to pos. B */	jump = virt_to_bus(c2 + nlines / 2);	base = virt_to_bus(pb->mask);	for (i=1; i < nlines; i += 2, c2++)     /* abort if set */		tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,			base + i * 96, jump);	/* Inform channel 1 and jump back to start */cmd_tab_mask_end:	/* ok, I just realized this is kind of flawed. */	/* this part is reached only after odd field clipmasking. */	/* wanna clean up? */		/* wait for field sync to be set */		/* corresponds to fsync (1) of ch1 *//* B */	tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);		/* restart ch1, meant to clear any dead bit or something */	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch1.control),							PLANB_CLR(RUN));	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch1.control),							PLANB_SET(RUN));	pb->overlay_last2 = c2;	/* keep a pointer to the last command */		/* start over even field clipmasking */	tab_cmd_dbdma(c2, DBDMA_NOP | BR_ALWAYS, pb->clip_cbo.bus);	eieio();	return;}/*********************************//* grabdisplay support functions *//*********************************/static inline int overlay_is_active(struct planb *pb){	unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);	unsigned int caddr = (unsigned)readl(&pb->planb_base->ch1.cmdptr);	return (readl(&pb->overlay_last1->cmd_dep) == pb->vid_cbo.bus)			&& (caddr < (pb->vid_cbo.bus + size))			&& (caddr >= (unsigned)pb->vid_cbo.bus);}static int vgrab(struct planb *pb, struct video_mmap *mp){	unsigned int	fr = mp->frame;	unsigned int	fmt = mp->format;	unsigned int	bpp = palette2fmt[fmt].bpp;	gbuf_ptr	gbuf = &pb->gbuf[fr];	if(pb->rawbuf==NULL) {		int err;		if((err=grabbuf_alloc(pb)))			return err;	}	DBG("PlanB: grab %d: %dx%d fmt %d (%u)\n", pb->grabbing, mp->width,						mp->height, fmt, fr);	if(pb->grabbing >= MAX_GBUFFERS) {		DBG("       no buffer\n");		return -ENOBUFS;	}	if(fr > (MAX_GBUFFERS - 1) || fr < 0) {		DBG("       invalid buffer\n");		return -EINVAL;	}	if(mp->height <= 0 || mp->width <= 0) {		DBG("       negative height or width\n");		return -EINVAL;	}	if(mp->format < 0 || mp->format >= PLANB_PALETTE_MAX) {		DBG("       format out of range\n");		return -EINVAL;	}	if(bpp == 0) {		DBG("       unsupported format %d\n", mp->format);		return -EINVAL;	}	if (mp->height * mp->width * bpp > PLANB_MAX_FBUF) {		DBG("       grab bigger than buffer\n");		return -EINVAL;	}	planb_lock(pb);	if(mp->width != gbuf->width || mp->height != gbuf->height ||			fmt != gbuf->fmt || (gbuf->norm_switch)) {		int i;#ifndef PLANB_GSCANLINE		unsigned int osize = gbuf->width * gbuf->height *					palette2fmt[gbuf->fmt].bpp;		unsigned int nsize = mp->width * mp->height * bpp;#endif		DBG("PlanB: changed gwidth = %d, gheight = %d, format = %u, "			"osize = %d, nsize = %d\n", mp->width, mp->height, fmt,								osize, nsize);/* Do we _really_ need to clear the grab buffers?? */#if 0#ifndef PLANB_GSCANLINE		if(gbuf->norm_switch)			nsize = 0;		if (nsize < osize) {			for(i = gbuf->idx; osize > 0; i++) {				memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);				osize -= PAGE_SIZE;			}		}		for(i = gbuf->l_fr_addr_idx; i <				gbuf->l_fr_addr_idx + gbuf->lnum; i++)			memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);#else/* XXX TODO *//*		if(gbuf->norm_switch)			memset((void *)pb->gbuffer[fr], 0,					pb->gbytes_per_line * gbuf->height);		else {			if(mp->			for(i = 0; i < gbuf->height; i++) {				memset((void *)(pb->gbuffer[fr]					+ pb->gbytes_per_line * i			}		}*/#endif#endif /* if 0 */		gbuf->width = mp->width;		gbuf->height = mp->height;		gbuf->fmt = fmt;		gbuf->last_cmd = setup_grab_cmd(fr, pb);		planb_pre_capture(fr, pb);		gbuf->need_pre_capture = 1;		gbuf->norm_switch = 0;	} else		gbuf->need_pre_capture = 0;	*gbuf->status = GBUFFER_GRABBING;	if(!(ACTIVE & readl(&pb->planb_base->ch1.status))) {		IDBG("PlanB: ch1 inactive, initiating grabbing\n");		planb_dbdma_stop(&pb->planb_base->ch1);		if(gbuf->need_pre_capture) {			DBG("PlanB: padding pre-capture sequence\n");			writel(virt_to_bus(gbuf->pre_cmd),				&pb->planb_base->ch1.cmdptr);		} else {			tab_cmd_dbdma(gbuf->last_cmd, DBDMA_STOP, 0);			tab_cmd_dbdma(gbuf->cap_cmd, DBDMA_NOP, 0);		/* let's be on the safe side. here is not timing critical. */			tab_cmd_dbdma((gbuf->cap_cmd + 1), DBDMA_NOP, 0);			writel(virt_to_bus(gbuf->cap_cmd),				&pb->planb_base->ch1.cmdptr);		}		planb_dbdma_restart(&pb->planb_base->ch1);		pb->last_fr = fr;	} else {		int i;		DBG("PlanB: ch1 active, grabbing being queued\n");		if((pb->last_fr == -1) || ((pb->last_fr == -2) &&						overlay_is_active(pb))) {			DBG("PlanB: overlay is active, grabbing defered\n");			tab_cmd_dbdma(gbuf->last_cmd, DBDMA_NOP | BR_ALWAYS,					pb->vid_cbo.bus);			if(gbuf->need_pre_capture) {				DBG("PlanB: padding pre-capture sequence\n");				tab_cmd_store(gbuf->pre_cmd,				    virt_to_bus(&pb->overlay_last1->cmd_dep),				    pb->vid_cbo.bus);				eieio();				writel(virt_to_bus(gbuf->pre_cmd),					&pb->overlay_last1->cmd_dep);			} else {				tab_cmd_store(gbuf->cap_cmd,				    virt_to_bus(&pb->overlay_last1->cmd_dep),				    pb->vid_cbo.bus);				tab_cmd_dbdma((gbuf->cap_cmd + 1),								DBDMA_NOP, 0);				eieio();				writel(virt_to_bus(gbuf->cap_cmd),					&pb->overlay_last1->cmd_dep);			}			for(i = 0; overlay_is_active(pb) && i < 999; i++)				DBG("PlanB: waiting for overlay done\n");			tab_cmd_dbdma(pb->vid_cbo.start, DBDMA_NOP, 0);			pb->prev_last_fr = fr;			pb->last_fr = -2;		} else if(pb->last_fr == -2) {			DBG("PlanB: mixed mode detected, grabbing"				" will be done before activating overlay\n");			tab_cmd_dbdma(pb->vid_cbo.start, DBDMA_NOP, 0);			if(gbuf->need_pre_capture) {				DBG("PlanB: padding pre-capture sequence\n");				tab_cmd_dbdma(pb->gbuf[pb->prev_last_fr].last_cmd,						DBDMA_NOP | BR_ALWAYS,						virt_to_bus(gbuf->pre_cmd));				eieio();			} else {				tab_cmd_dbdma(gbuf->cap_cmd, DBDMA_NOP, 0);				if(pb->gbuf[pb->prev_last_fr].width !=								gbuf->width					|| pb->gbuf[pb->prev_last_fr].height !=								gbuf->height					|| pb->gbuf[pb->prev_last_fr].fmt !=								gbuf->fmt)					tab_cmd_dbdma((gbuf->cap_cmd + 1),								DBDMA_NOP, 0);				else					tab_cmd_dbdma((gbuf->cap_cmd + 1),					    DBDMA_NOP | BR_ALWAYS,					    virt_to_bus(gbuf->cap_cmd + 16));				tab_cmd_dbdma(pb->gbuf[pb->prev_last_fr].last_cmd,						DBDMA_NOP | BR_ALWAYS,						virt_to_bus(gbuf->cap_cmd));				eieio();			}			tab_cmd_dbdma(gbuf->last_cmd, DBDMA_NOP | BR_ALWAYS,				pb->vid_cbo.bus);			eieio();			pb->prev_last_fr = fr;			pb->last_fr = -2;		} else {			gbuf_ptr	lastgbuf = &pb->gbuf[pb->last_fr];			DBG("PlanB: active grabbing session detected\n");			if(gbuf->need_pre_capture) {				DBG("PlanB: padding pre-capture sequence\n");				tab_cmd_dbdma(lastgbuf->last_cmd,						DBDMA_NOP | BR_ALWAYS,						virt_to_bus(gbuf->pre_cmd));				eieio();			} else {				tab_cmd_dbdma(gbuf->last_cmd, DBDMA_STOP, 0);				tab_cmd_dbdma(gbuf->cap_cmd, DBDMA_NOP, 0);				if(lastgbuf->width != gbuf->width				    || lastgbuf->height != gbuf->height				    || lastgbuf->fmt != gbuf->fmt)					tab_cmd_dbdma((gbuf->cap_cmd + 1),								DBDMA_NOP, 0);				else					tab_cmd_dbdma((gbuf->cap_cmd + 1),					    DBDMA_NOP | BR_ALWAYS,					    virt_to_bus(gbuf->cap_cmd + 16));				tab_cmd_dbdma(lastgbuf->last_cmd,						DBDMA_NOP | BR_ALWAYS,						virt_to_bus(gbuf->cap_cmd));				eieio();			}			pb->last_fr = fr;		}		if(!(ACTIVE & readl(&pb->planb_base->ch1.status))) {			DBG("PlanB: became inactive in the mean time... "				"reactivating\n");			planb_dbdma_stop(&pb->planb_base->ch1);			writel(virt_to_bus(gbuf->cap_cmd),				&pb->planb_base->ch1.cmdptr);			planb_dbdma_restart(&pb->planb_base->ch1);		}	}	pb->grabbing++;	planb_unlock(pb);	return 0;}static void planb_pre_capture(int fr, struct planb *pb){	gbuf_ptr	gbuf = &pb->gbuf[fr];	dbdma_cmd_ptr	c1 = gbuf->pre_cmd;	int		height = gbuf->height;	int		interlace = (height > pb->maxlines/2)? 1: 0;	tab_cmd_dbdma(c1++, DBDMA_NOP, 0);	c1 = cmd_geo_setup(c1, gbuf->width, height, interlace, gbuf->fmt,									0, pb);	/* Sync to even field */	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.wait_sel),							PLANB_SET(FIELD_SYNC));	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),							PLANB_SET(ODD_FIELD));	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);	tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;	tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),							PLANB_SET(DMA_ABORT));	/* For non-interlaced, we use even fields only */	if (interlace == 0)		goto cmd_tab_data_end;	/* Sync to odd field */	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),							PLANB_SET(ODD_FIELD));	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);	tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),							PLANB_SET(DMA_ABORT));cmd_tab_data_end:	tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(gbuf->cap_cmd));	eieio();}/* This needs some explanation. * What we do here is write the DBDMA commands to fill the grab buffer. * Since the grab buffer is made up of physically non-contiguous chunks, * we need to make sure to not make the DMA engine write across a chunk * boundary: the DMA engine needs a physically contiguous memory chunk for * a single scan line. * So all those scan lines that cross a chunk boundary are written do spare * scratch buffers, and we keep track of this fact. * Later, in the interrupt routine, we copy those scan lines (in two pieces) * back to where they belong in the right sequence in the grab buffer. */static dbdma_cmd_ptr setup_grab_cmd(int fr, struct planb *pb){	int		i, count, nlines, stepsize, interlace;#ifdef PLANB_GSCANLINE	int		scanline;#else	int		nlpp, leftover1;	unsigned long	base;#endif	unsigned long	jump;	int		pagei;	dbdma_cmd_ptr	c1;	dbdma_cmd_ptr	jump_addr;	gbuf_ptr	gbuf = &pb->gbuf[fr];	int		fmt = gbuf->fmt;	c1 = gbuf->cap_cmd;	nlines = gbuf->height;	interlace = (nlines > pb->maxlines/2) ? 1 : 0;	count = palette2fmt[fmt].bpp * gbuf->width;#ifdef PLANB_GSCANLINE	scanline = pb->gbytes_per_line;#else	gbuf->lsize = count;	gbuf->lnum = 0;#endif	/* Do video in: */	/* Preamble commands: */	tab_cmd_dbdma(c1++, DBDMA_NOP, 0);	tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(c1 + 16)); c1++;	c1 = cmd_geo_setup(c1, gbuf->width, nlines, interlace, fmt, 0, pb);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.wait_sel),							PLANB_SET(FIELD_SYNC));	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),							PLANB_SET(ODD_FIELD));	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);	tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;	tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),							PLANB_SET(DMA_ABORT));	if (interlace) {		stepsize = 2;		jump_addr = c1 + TAB_FACTOR * (nlines + 1) / 2;	} else {		stepsize = 1;		jump_addr = c1 + TAB_FACTOR * nlines;	}	jump = virt_to_bus(jump_addr);	/* even field data: */	pagei = gbuf->idx;#ifdef PLANB_GSCANLINE	for (i = 0; i < nlines; i += stepsize) {		tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,		    virt_to_bus(pb->rawbuf[pagei + i * scanline / PAGE_SIZE]),									jump);	}#else	i = 0;	leftover1 = 0;	do {	    int j;	    base = virt_to_bus(pb->rawbuf[pagei]);	    nlpp = (PAGE_SIZE - leftover1) / count / 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 + leftover1, jump);	    if(i < nlines) {		int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;		if(lov0 == 0)		    leftover1 = 0;		else {		    if(lov0 >= count) {			/* can happen only when interlacing; then other field			 * uses up leftover space (lov0 - count). */			tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, base				+ count * nlpp * stepsize + leftover1, jump);		    } else {			/* start of free space at end of page: */			pb->l_to_addr[fr][gbuf->lnum] = pb->rawbuf[pagei]					+ count * nlpp * stepsize + leftover1;			/* index where continuation is: */			pb->l_to_next_idx[fr][gbuf->lnum] = pagei + 1;			/* How much is left to do in next page: */			pb->l_to_next_size[fr][gbuf->lnum] = count - 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--;		    	}		    }		    leftover1 = count * stepsize - lov0;		    i += stepsize;		}	    }	    pagei++;	} while(i < nlines);	tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);	c1 = jump_addr;#endif /* PLANB_GSCANLINE */	/* For non-interlaced, we use even fields only */	if (!interlace)		goto cmd_tab_data_end;	/* Sync to odd field */	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),		PLANB_SET(ODD_FIELD));	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);	tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),		PLANB_SET(DMA_ABORT));		/* odd field data: */	jump_addr = c1 + TAB_FACTOR * nlines / 2;	jump = virt_to_bus(jump_addr);#ifdef PLANB_GSCANLINE	for (i = 1; i < nlines; i += stepsize) {		tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,					virt_to_bus(pb->rawbuf[pagei					+ i * scanline / PAGE_SIZE]), jump);	}#else	i = 1;

⌨️ 快捷键说明

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