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

📄 planb.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
					pb->gbytes_per_line * pb->gheight[fr]);		else {			if(mp->			for(i = 0; i < pb->gheight[fr]; i++) {				memset((void *)(pb->gbuffer[fr]					+ pb->gbytes_per_line * i			}		}*/#endif		pb->gwidth[fr] = mp->width;		pb->gheight[fr] = mp->height;		pb->gfmt[fr] = format;		pb->last_cmd[fr] = setup_grab_cmd(fr, pb);		planb_pre_capture(fr, pb->gfmt[fr], pb); /* gfmt = bpp */		pb->need_pre_capture[fr] = 1;		pb->gnorm_switch[fr] = 0;	} else		pb->need_pre_capture[fr] = 0;	pb->frame_stat[fr] = GBUFFER_GRABBING;	if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {		IDEBUG("PlanB: ch1 inactive, initiating grabbing\n");		planb_dbdma_stop(&pb->planb_base->ch1);		if(pb->need_pre_capture[fr]) {			IDEBUG("PlanB: padding pre-capture sequence\n");			out_le32 (&pb->planb_base->ch1.cmdptr,						virt_to_bus(pb->pre_cmd[fr]));		} else {			tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);			tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);		/* let's be on the safe side. here is not timing critical. */			tab_cmd_dbdma((pb->cap_cmd[fr] + 1), DBDMA_NOP, 0);			out_le32 (&pb->planb_base->ch1.cmdptr,						virt_to_bus(pb->cap_cmd[fr]));		}		planb_dbdma_restart(&pb->planb_base->ch1);		pb->last_fr = fr;	} else {		int i;		IDEBUG("PlanB: ch1 active, grabbing being queued\n");		if((pb->last_fr == -1) || ((pb->last_fr == -2) &&						overlay_is_active(pb))) {			IDEBUG("PlanB: overlay is active, grabbing defered\n");			tab_cmd_dbdma(pb->last_cmd[fr],					DBDMA_NOP | BR_ALWAYS,					virt_to_bus(pb->ch1_cmd));			if(pb->need_pre_capture[fr]) {				IDEBUG("PlanB: padding pre-capture sequence\n");				tab_cmd_store(pb->pre_cmd[fr],				    virt_to_bus(&pb->overlay_last1->cmd_dep),						virt_to_bus(pb->ch1_cmd));				eieio();				out_le32 (&pb->overlay_last1->cmd_dep,						virt_to_bus(pb->pre_cmd[fr]));			} else {				tab_cmd_store(pb->cap_cmd[fr],				    virt_to_bus(&pb->overlay_last1->cmd_dep),						virt_to_bus(pb->ch1_cmd));				tab_cmd_dbdma((pb->cap_cmd[fr] + 1),								DBDMA_NOP, 0);				eieio();				out_le32 (&pb->overlay_last1->cmd_dep,						virt_to_bus(pb->cap_cmd[fr]));			}			for(i = 0; overlay_is_active(pb) && i < 999; i++)				IDEBUG("PlanB: waiting for overlay done\n");			tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0);			pb->prev_last_fr = fr;			pb->last_fr = -2;		} else if(pb->last_fr == -2) {			IDEBUG("PlanB: mixed mode detected, grabbing"				" will be done before activating overlay\n");			tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0);			if(pb->need_pre_capture[fr]) {				IDEBUG("PlanB: padding pre-capture sequence\n");				tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr],						DBDMA_NOP | BR_ALWAYS,						virt_to_bus(pb->pre_cmd[fr]));				eieio();			} else {				tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);				if(pb->gwidth[pb->prev_last_fr] !=								pb->gwidth[fr]					|| pb->gheight[pb->prev_last_fr] !=								pb->gheight[fr]					|| pb->gfmt[pb->prev_last_fr] !=								pb->gfmt[fr])					tab_cmd_dbdma((pb->cap_cmd[fr] + 1),								DBDMA_NOP, 0);				else					tab_cmd_dbdma((pb->cap_cmd[fr] + 1),					    DBDMA_NOP | BR_ALWAYS,					    virt_to_bus(pb->cap_cmd[fr] + 16));				tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr],						DBDMA_NOP | BR_ALWAYS,						virt_to_bus(pb->cap_cmd[fr]));				eieio();			}			tab_cmd_dbdma(pb->last_cmd[fr],					DBDMA_NOP | BR_ALWAYS,					virt_to_bus(pb->ch1_cmd));			eieio();			pb->prev_last_fr = fr;			pb->last_fr = -2;		} else {			IDEBUG("PlanB: active grabbing session detected\n");			if(pb->need_pre_capture[fr]) {				IDEBUG("PlanB: padding pre-capture sequence\n");				tab_cmd_dbdma(pb->last_cmd[pb->last_fr],						DBDMA_NOP | BR_ALWAYS,						virt_to_bus(pb->pre_cmd[fr]));				eieio();			} else {				tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);				tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);				if(pb->gwidth[pb->last_fr] != pb->gwidth[fr]					|| pb->gheight[pb->last_fr] !=								pb->gheight[fr]					|| pb->gfmt[pb->last_fr] !=								pb->gfmt[fr])					tab_cmd_dbdma((pb->cap_cmd[fr] + 1),								DBDMA_NOP, 0);				else					tab_cmd_dbdma((pb->cap_cmd[fr] + 1),					    DBDMA_NOP | BR_ALWAYS,					    virt_to_bus(pb->cap_cmd[fr] + 16));				tab_cmd_dbdma(pb->last_cmd[pb->last_fr],						DBDMA_NOP | BR_ALWAYS,						virt_to_bus(pb->cap_cmd[fr]));				eieio();			}			pb->last_fr = fr;		}		if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {			IDEBUG("PlanB: became inactive in the mean time..."				"reactivating\n");			planb_dbdma_stop(&pb->planb_base->ch1);			out_le32 (&pb->planb_base->ch1.cmdptr,						virt_to_bus(pb->cap_cmd[fr]));			planb_dbdma_restart(&pb->planb_base->ch1);		}	}	pb->grabbing++;	planb_unlock(pb);	return 0;}static void planb_pre_capture(int fr, int bpp, struct planb *pb){	volatile struct dbdma_cmd *c1 = pb->pre_cmd[fr];	int interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0;	tab_cmd_dbdma(c1++, DBDMA_NOP, 0);	if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace,						bpp, 0, pb)) == NULL) {		printk(KERN_WARNING "PlanB: encountered some problems\n");		tab_cmd_dbdma(pb->pre_cmd[fr] + 1, DBDMA_STOP, 0);		return;	}	/* Sync to even field */	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),		PLANB_SET(FIELD_SYNC));	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));	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_phys->ch1.br_sel),		PLANB_SET(DMA_ABORT));	/* For non-interlaced, we use even fields only */	if (pb->gheight[fr] <= pb->maxlines/2)		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_phys->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_phys->ch1.br_sel),		PLANB_SET(DMA_ABORT));cmd_tab_data_end:	tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->cap_cmd[fr]));	eieio();}static volatile struct dbdma_cmd *setup_grab_cmd(int fr, struct planb *pb){	int		i, bpp, count, nlines, stepsize, interlace;#ifdef PLANB_GSCANLINE	int		scanline;#else	int		nlpp, leftover1;	unsigned long	base;#endif	unsigned long	jump;	int		pagei;	volatile struct dbdma_cmd *c1;	volatile struct dbdma_cmd *jump_addr;	c1 = pb->cap_cmd[fr];	interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0;	bpp = pb->gfmt[fr];	/* gfmt = bpp */	count = bpp * pb->gwidth[fr];	nlines = pb->gheight[fr];#ifdef PLANB_GSCANLINE	scanline = pb->gbytes_per_line;#else	pb->lsize[fr] = count;	pb->lnum[fr] = 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++;	if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace,						bpp, 0, pb)) == NULL) {		printk(KERN_WARNING "PlanB: encountered serious problems\n");		tab_cmd_dbdma(pb->cap_cmd[fr] + 1, DBDMA_STOP, 0);		return (pb->cap_cmd[fr] + 2);	}	tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),		PLANB_SET(FIELD_SYNC));	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));	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_phys->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 = pb->gbuf_idx[fr];#ifdef PLANB_GSCANLINE	for (i = 0; i < nlines; i += stepsize) {		tab_cmd_gen(c1++, INPUT_MORE | 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) {			tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, base				+ count * nlpp * stepsize + leftover1, jump);		    } else {			pb->l_to_addr[fr][pb->lnum[fr]] = pb->rawbuf[pagei]					+ count * nlpp * stepsize + leftover1;			pb->l_to_next_idx[fr][pb->lnum[fr]] = pagei + 1;			pb->l_to_next_size[fr][pb->lnum[fr]] = count - lov0;			tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,				virt_to_bus(pb->rawbuf[pb->l_fr_addr_idx[fr]						+ pb->lnum[fr]]), jump);			if(++pb->lnum[fr] > MAX_LNUM)				pb->lnum[fr]--;		    }		    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_phys->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_phys->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 | BR_IFSET, count,					virt_to_bus(pb->rawbuf[pagei					+ i * scanline / PAGE_SIZE]), jump);	}#else	i = 1;	leftover1 = 0;	pagei = pb->gbuf_idx[fr];	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][pb->lnum[fr]] = pb->rawbuf[pagei]				+ count * (nlpp * stepsize + 1) + leftover1;			pb->l_to_next_idx[fr][pb->lnum[fr]] = pagei + 1;			pb->l_to_next_size[fr][pb->lnum[fr]] = count * stepsize									- lov0;			tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,				virt_to_bus(pb->rawbuf[pb->l_fr_addr_idx[fr]							+ pb->lnum[fr]]), jump);			if(++pb->lnum[fr] > MAX_LNUM)				pb->lnum[fr]--;			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_phys->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;	IDEBUG("PlanB: planb_irq()\n");	/* get/clear interrupt status bits */	eieio();	stat = in_le32(&pb->planb_base->intr_stat);	astat = stat & pb->intr_mask;	out_le32(&pb->planb_base->intr_stat, PLANB_FRM_IRQ					& ~astat & stat & ~PLANB_GEN_IRQ);	IDEBUG("PlanB: stat = %X, astat = %X\n", stat, astat);	if(astat & PLANB_FRM_IRQ) {		unsigned int fr = stat >> 9;#ifndef PLANB_GSCANLINE		int i;#endif		IDEBUG("PlanB: PLANB_FRM_IRQ\n");		pb->gcount++;		IDEBUG("PlanB: grab %d: fr = %d, gcount = %d\n",				pb->grabbing, fr, pb->gcount);#ifndef PLANB_GSCANLINE		IDEBUG("PlanB: %d * %d bytes are being copied over\n",				pb->lnum[fr], pb->lsize[fr]);		for(i = 0; i < pb->lnum[fr]; i++) {			int first = pb->lsize[fr] - pb->l_to_next_size[fr][i];			memcpy(pb->l_to_addr[fr][i],				pb->rawbuf[pb->l_fr_addr_idx[fr] + i],				first);			memcpy(pb->rawbuf[pb->l_to_next_idx[fr][i]],				pb->rawbuf[pb->l_fr_addr_idx[fr] + i] + first,						pb->l_to_next_size[fr][i]);		}#endif		pb->frame_stat[fr] = GBUFFER_DONE;		pb->grabbing--;		wake_up_interruptible(&pb->capq);		return;	}	/* incorrect interrupts? */	pb->intr_mask = PLANB_CLR_IRQ;	out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ);	printk(KERN_ERR "PlanB: IRQ lockup, cleared intrrupts"							" unconditionally\n");}/******************************* * Device Operations functions * *******************************/static int planb_open(struct video_device *dev, int mode){	struct planb *pb = (struct planb *)dev;	if (pb->user == 0) {		int err;		if((err = planb_prepare_open(pb)) != 0)			return err;	}	pb->user++;

⌨️ 快捷键说明

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