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

📄 planb.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		}	} else {		DEBUG("PlanB: currently idle, so can do whatever\n");		planb_dbdma_stop(&pb->planb_base->ch2);		planb_dbdma_stop(&pb->planb_base->ch1);		st_le32 (&pb->planb_base->ch2.cmdptr,						virt_to_bus(pb->ch2_cmd));		st_le32 (&pb->planb_base->ch1.cmdptr,						virt_to_bus(pb->ch1_cmd));		out_le16 (&pb->ch1_cmd->command, DBDMA_NOP);		planb_dbdma_restart(&pb->planb_base->ch2);		planb_dbdma_restart(&pb->planb_base->ch1);		pb->last_fr = -1;	}	return;}static void overlay_stop(struct planb *pb){	DEBUG("PlanB: overlay_stop()\n");	if(pb->last_fr == -1) {		DEBUG("PlanB: no grabbing, it seems...\n");		planb_dbdma_stop(&pb->planb_base->ch2);		planb_dbdma_stop(&pb->planb_base->ch1);		pb->last_fr = -999;	} else if(pb->last_fr == -2) {		unsigned int cmd_dep;		tab_cmd_dbdma(pb->cap_cmd[pb->prev_last_fr], DBDMA_STOP, 0);		eieio();		cmd_dep = (unsigned int)in_le32(&pb->overlay_last1->cmd_dep);		if(overlay_is_active(pb)) {			DEBUG("PlanB: overlay is currently active\n");			planb_dbdma_stop(&pb->planb_base->ch2);			planb_dbdma_stop(&pb->planb_base->ch1);			if(cmd_dep != pb->ch1_cmd_phys) {				out_le32(&pb->planb_base->ch1.cmdptr,						virt_to_bus(pb->overlay_last1));				planb_dbdma_restart(&pb->planb_base->ch1);			}		}		pb->last_fr = pb->prev_last_fr;		pb->prev_last_fr = -999;	}	return;}static void suspend_overlay(struct planb *pb){	int fr = -1;	struct dbdma_cmd last;	DEBUG("PlanB: suspend_overlay: %d\n", pb->suspend);	if(pb->suspend++)		return;	if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {		if(pb->last_fr == -2) {			fr = pb->prev_last_fr;			memcpy(&last, (void*)pb->last_cmd[fr], sizeof(last));			tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);		}		if(overlay_is_active(pb)) {			planb_dbdma_stop(&pb->planb_base->ch2);			planb_dbdma_stop(&pb->planb_base->ch1);			pb->suspended.overlay = 1;			pb->suspended.frame = fr;			memcpy(&pb->suspended.cmd, &last, sizeof(last));			return;		}	}	pb->suspended.overlay = 0;	pb->suspended.frame = fr;	memcpy(&pb->suspended.cmd, &last, sizeof(last));	return;}static void resume_overlay(struct planb *pb){	DEBUG("PlanB: resume_overlay: %d\n", pb->suspend);	if(pb->suspend > 1)		return;	if(pb->suspended.frame != -1) {		memcpy((void*)pb->last_cmd[pb->suspended.frame],				&pb->suspended.cmd, sizeof(pb->suspended.cmd));	}	if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {		goto finish;	}	if(pb->suspended.overlay) {		DEBUG("PlanB: overlay being resumed\n");		st_le16 (&pb->ch1_cmd->command, DBDMA_NOP);		st_le16 (&pb->ch2_cmd->command, DBDMA_NOP);		/* Set command buffer addresses */		st_le32(&pb->planb_base->ch1.cmdptr,					virt_to_bus(pb->overlay_last1));		out_le32(&pb->planb_base->ch2.cmdptr,					virt_to_bus(pb->overlay_last2));		/* Start the DMA controller */		out_le32 (&pb->planb_base->ch2.control,				PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));		out_le32 (&pb->planb_base->ch1.control,				PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));	} else if(pb->suspended.frame != -1) {		out_le32(&pb->planb_base->ch1.cmdptr,				virt_to_bus(pb->last_cmd[pb->suspended.frame]));		out_le32 (&pb->planb_base->ch1.control,				PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));	}finish:	pb->suspend--;	wake_up_interruptible(&pb->suspendq);}static void add_clip(struct planb *pb, struct video_clip *clip) {	volatile unsigned char	*base;	int	xc = clip->x, yc = clip->y;	int	wc = clip->width, hc = clip->height;	int	ww = pb->win.width, hw = pb->win.height;	int	x, y, xtmp1, xtmp2;	DEBUG("PlanB: clip %dx%d+%d+%d\n", wc, hc, xc, yc);	if(xc < 0) {		wc += xc;		xc = 0;	}	if(yc < 0) {		hc += yc;		yc = 0;	}	if(xc + wc > ww)		wc = ww - xc;	if(wc <= 0) /* Nothing to do */		return;	if(yc + hc > hw)		hc = hw - yc;	for (y = yc; y < yc+hc; y++) {		xtmp1=xc>>3;		xtmp2=(xc+wc)>>3;		base = pb->mask + y*96;		if(xc != 0 || wc >= 8)			*(base + xtmp1) &= (unsigned char)(0x00ff &				(0xff00 >> (xc&7)));		for (x = xtmp1 + 1; x < xtmp2; x++) {			*(base + x) = 0;		}		if(xc < (ww & ~0x7))			*(base + xtmp2) &= (unsigned char)(0x00ff >>				((xc+wc) & 7));	}	return;}static void fill_cmd_buff(struct planb *pb){	int restore = 0;	volatile struct dbdma_cmd last;	DEBUG("PlanB: fill_cmd_buff()\n");	if(pb->overlay_last1 != pb->ch1_cmd) {		restore = 1;		last = *(pb->overlay_last1);	}	memset ((void *) pb->ch1_cmd, 0, 2 * pb->tab_size					* sizeof(struct dbdma_cmd));	cmd_buff (pb);	if(restore)		*(pb->overlay_last1) = last;	if(pb->suspended.overlay) {		unsigned long jump_addr = in_le32(&pb->overlay_last1->cmd_dep);		if(jump_addr != pb->ch1_cmd_phys) {			int i;			DEBUG("PlanB: adjusting ch1's jump address\n");			for(i = 0; i < MAX_GBUFFERS; i++) {				if(pb->need_pre_capture[i]) {				    if(jump_addr == virt_to_bus(pb->pre_cmd[i]))					goto found;				} else {				    if(jump_addr == virt_to_bus(pb->cap_cmd[i]))					goto found;				}			}			DEBUG("PlanB: not found...\n");			goto out;found:			if(pb->need_pre_capture[i])				out_le32(&pb->pre_cmd[i]->phy_addr,						virt_to_bus(pb->overlay_last1));			else				out_le32(&pb->cap_cmd[i]->phy_addr,						virt_to_bus(pb->overlay_last1));		}	}out:	pb->cmd_buff_inited = 1;	return;}static void cmd_buff(struct planb *pb){	int		i, bpp, count, nlines, stepsize, interlace;	unsigned long	base, jump, addr_com, addr_dep;	volatile struct dbdma_cmd *c1 = pb->ch1_cmd;	volatile struct dbdma_cmd *c2 = pb->ch2_cmd;	interlace = pb->win.interlace;	bpp = pb->win.bpp;	count = (bpp * ((pb->win.x + pb->win.width > pb->win.swidth) ?		(pb->win.swidth - pb->win.x) : pb->win.width));	nlines = ((pb->win.y + pb->win.height > pb->win.sheight) ?		(pb->win.sheight - pb->win.y) : pb->win.height);	/* Do video in: */	/* Preamble commands: */	addr_com = virt_to_bus(c1);	addr_dep = virt_to_bus(&c1->cmd_dep);	tab_cmd_dbdma(c1++, DBDMA_NOP, 0);	jump = virt_to_bus(c1+16); /* 14 by cmd_geo_setup() and 2 for padding */	if((c1 = cmd_geo_setup(c1, pb->win.width, pb->win.height, interlace,					bpp, 1, pb)) == NULL) {		printk(KERN_WARNING "PlanB: encountered serious problems\n");		tab_cmd_dbdma(pb->ch1_cmd + 1, DBDMA_STOP, 0);		tab_cmd_dbdma(pb->ch2_cmd + 1, DBDMA_STOP, 0);		return;	}	tab_cmd_store(c1++, addr_com, (unsigned)(DBDMA_NOP | BR_ALWAYS) << 16);	tab_cmd_store(c1++, addr_dep, jump);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),							PLANB_SET(FIELD_SYNC));		/* (1) wait for field sync to be set */	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),							PLANB_SET(ODD_FIELD));		/* wait for field sync to be cleared */	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);		/* if not odd field, wait until field sync is set again */	tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;		/* assert ch_sync to ch2 */	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control),							PLANB_SET(CH_SYNC));	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),							PLANB_SET(DMA_ABORT));	base = (pb->frame_buffer_phys + pb->offset + pb->win.y * (pb->win.bpl					+ pb->win.pad) + pb->win.x * bpp);	if (interlace) {		stepsize = 2;		jump = virt_to_bus(c1 + (nlines + 1) / 2);	} else {		stepsize = 1;		jump = virt_to_bus(c1 + nlines);	}	/* even field data: */	for (i=0; i < nlines; i += stepsize, c1++)		tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET,			count, base + i * (pb->win.bpl + pb->win.pad), jump);	/* For non-interlaced, we use even fields only */	if (!interlace)		goto cmd_tab_data_end;	/* Resync to odd field */		/* (2) wait for field sync to be set */	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),							PLANB_SET(ODD_FIELD));		/* wait for field sync to be cleared */	tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);		/* if not odd field, wait until field sync is set again */	tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;		/* assert ch_sync to ch2 */	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control),							PLANB_SET(CH_SYNC));	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),							PLANB_SET(DMA_ABORT));		/* odd field data: */	jump = virt_to_bus(c1 + nlines / 2);	for (i=1; i < nlines; i += stepsize, c1++)		tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,			base + i * (pb->win.bpl + pb->win.pad), jump);	/* And jump back to the start */cmd_tab_data_end:	pb->overlay_last1 = c1;	/* keep a pointer to the last command */	tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->ch1_cmd));	/* Clipmask command buffer */	/* Preamble commands: */	tab_cmd_dbdma(c2++, DBDMA_NOP, 0);	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel),							PLANB_SET(CH_SYNC));		/* wait until ch1 asserts ch_sync */	tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);		/* clear ch_sync asserted by ch1 */	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.control),							PLANB_CLR(CH_SYNC));	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel),							PLANB_SET(FIELD_SYNC));	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),							PLANB_SET(ODD_FIELD));	/* jump to end of even field if appropriate */	/* this points to (interlace)? pos. C: pos. B */	jump = (interlace) ? virt_to_bus(c2 + (nlines + 1) / 2 + 2):						virt_to_bus(c2 + nlines + 2);		/* if odd field, skip over to odd field clipmasking */	tab_cmd_dbdma(c2++, DBDMA_NOP | BR_IFSET, jump);	/* even field mask: */	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),							PLANB_SET(DMA_ABORT));	/* this points to pos. B */	jump = (interlace) ? virt_to_bus(c2 + nlines + 1):						virt_to_bus(c2 + nlines);	base = virt_to_bus(pb->mask);	for (i=0; i < nlines; i += stepsize, c2++)		tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,			base + i * 96, jump);	/* For non-interlaced, we use only even fields */	if(!interlace)		goto cmd_tab_mask_end;	/* odd field mask: *//* C */	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->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_phys->ch1.control),							PLANB_CLR(RUN));	tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->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, virt_to_bus(pb->ch2_cmd));	eieio();	return;}/*********************************//* grabdisplay support functions *//*********************************/static int palette2fmt[] = {       0,       PLANB_GRAY,       0,       0,       0,       PLANB_COLOUR32,       PLANB_COLOUR15,       0,       0,       0,       0,       0,       0,       0,       0,};#define PLANB_PALETTE_MAX 15static int vgrab(struct planb *pb, struct video_mmap *mp){	unsigned int fr = mp->frame;	unsigned int format;	if(pb->rawbuf==NULL) {		int err;		if((err=grabbuf_alloc(pb)))			return err;	}	IDEBUG("PlanB: grab %d: %dx%d(%u)\n", pb->grabbing,						mp->width, mp->height, fr);	if(pb->grabbing >= MAX_GBUFFERS)		return -ENOBUFS;	if(fr > (MAX_GBUFFERS - 1) || fr < 0)		return -EINVAL;	if(mp->height <= 0 || mp->width <= 0)		return -EINVAL;	if(mp->format < 0 || mp->format >= PLANB_PALETTE_MAX)		return -EINVAL;	if((format = palette2fmt[mp->format]) == 0)		return -EINVAL;	if (mp->height * mp->width * format > PLANB_MAX_FBUF) /* format = bpp */		return -EINVAL;	planb_lock(pb);	if(mp->width != pb->gwidth[fr] || mp->height != pb->gheight[fr] ||			format != pb->gfmt[fr] || (pb->gnorm_switch[fr])) {		int i;#ifndef PLANB_GSCANLINE		unsigned int osize = pb->gwidth[fr] * pb->gheight[fr]								* pb->gfmt[fr];		unsigned int nsize = mp->width * mp->height * format;#endif		IDEBUG("PlanB: gwidth = %d, gheight = %d, mp->format = %u\n",					mp->width, mp->height, mp->format);#ifndef PLANB_GSCANLINE		if(pb->gnorm_switch[fr])			nsize = 0;		if (nsize < osize) {			for(i = pb->gbuf_idx[fr]; osize > 0; i++) {				memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);				osize -= PAGE_SIZE;			}		}		for(i = pb->l_fr_addr_idx[fr]; i < pb->l_fr_addr_idx[fr]							+ pb->lnum[fr]; i++)			memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);#else/* XXX TODO *//*		if(pb->gnorm_switch[fr])			memset((void *)pb->gbuffer[fr], 0,

⌨️ 快捷键说明

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