📄 planb.c
字号:
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 + -