📄 cyberpro.c
字号:
cyberpro_grphw8(REG_BANK, REG_BANK_X, dp); cyberpro_grphw24(X_V2_VID_MEM_START, wi->src.offset, dp); cyberpro_grphw16(X_V2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp); cyberpro_grphw8 (X_V2_VID_SRC_WIN_WIDTH, phase, dp); cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp); cyberpro_grphw8(Y_V2_VID_FMT, wi->vid_fmt, dp);}/* * Set v2 window */static voidcyberpro_v2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi){ unsigned int xscale, yscale; unsigned int xoff, yoff; /* * Note: the offset does not appear to be influenced by * hardware scrolling. */ xoff = yoff = 0; xoff += wi->dst.x; yoff += wi->dst.y; xscale = (wi->src.width * 4096) / wi->dst.width; yscale = (wi->src.height * 4096) / wi->dst.height; cyberpro_grphw8(REG_BANK, REG_BANK_X, dp); cyberpro_grphw16(X_V2_X_START, xoff, dp); cyberpro_grphw16(X_V2_X_END, xoff + wi->dst.width, dp); cyberpro_grphw16(X_V2_Y_START, yoff, dp); cyberpro_grphw16(X_V2_Y_END, yoff + wi->dst.height, dp); cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp); cyberpro_grphw16(Y_V2_DDA_X_INC, xscale, dp); cyberpro_grphw16(Y_V2_DDA_Y_INC, yscale, dp);}/* * Enable or disable the 2nd overlay window. Note that for anything * useful to be displayed, we must have capture enabled. */static voidcyberpro_v2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on){ if (on) wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW; else wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW; cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp); cyberpro_grphw8(Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);}/*--------------------------- X2 Overlay Window ----------------------------- * Initialise 3rd overlay window (guesswork) */static voidcyberpro_x2_init(struct cyberpro_vidinfo *dp, struct win_info *wi){ wi->vid_fmt = EXT_VID_FMT_YUV422; wi->vid_disp_ctl1 = 0x40; wi->vid_misc_ctl1 = 0; cyberpro_grphw8(REG_BANK, REG_BANK_K, dp); cyberpro_grphw8 (K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp); cyberpro_grphw16(K_X2_DDA_X_INIT, 0x0800, dp); cyberpro_grphw16(K_X2_DDA_Y_INIT, 0x0800, dp);}/* * Set the source parameters for the x2 window */static voidcyberpro_x2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi){ unsigned int phase, pitch; pitch = (wi->src.width >> 2) & 0x0fff; phase = (wi->src.width + 3) >> 2; wi->vid_fmt &= ~7; switch (wi->src.format) { case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break; case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break; case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break; case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break; case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break; } cyberpro_grphw8(REG_BANK, REG_BANK_J, dp); cyberpro_grphw24(J_X2_VID_MEM_START, wi->src.offset, dp); cyberpro_grphw16(J_X2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp); cyberpro_grphw8 (J_X2_VID_SRC_WIN_WIDTH, phase, dp); cyberpro_grphw8(REG_BANK, REG_BANK_K, dp); cyberpro_grphw8(K_X2_VID_FMT, wi->vid_fmt, dp);}/* * Set x2 window */static voidcyberpro_x2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi){ unsigned int xscale, yscale; unsigned int xoff, yoff; /* * Note: the offset does not appear to be influenced by * hardware scrolling. */ xoff = yoff = 0; xoff += wi->dst.x; yoff += wi->dst.y; xscale = (wi->src.width * 4096) / wi->dst.width; yscale = (wi->src.height * 4096) / wi->dst.height; cyberpro_grphw8(REG_BANK, REG_BANK_J, dp); cyberpro_grphw16(J_X2_X_START, xoff, dp); cyberpro_grphw16(J_X2_X_END, xoff + wi->dst.width, dp); cyberpro_grphw16(J_X2_Y_START, yoff, dp); cyberpro_grphw16(J_X2_Y_END, yoff + wi->dst.height, dp); cyberpro_grphw8(REG_BANK, REG_BANK_K, dp); cyberpro_grphw16(K_X2_DDA_X_INC, xscale, dp); cyberpro_grphw16(K_X2_DDA_Y_INC, yscale, dp);}/* * Enable or disable the 3rd overlay window. Note that for anything * useful to be displayed, we must have capture enabled. */static voidcyberpro_x2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on){ if (on) wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW; else wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW; cyberpro_grphw8(REG_BANK, REG_BANK_K, dp); cyberpro_grphw8(K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);}/* ------------------------------------------------------------------------- */#if 0static void reset_seq(struct cyberpro_vidinfo *dp){ unsigned char ext_mem_ctl = cyberpro_grphr8(0x70, dp); cyberpro_grphw8(ext_mem_ctl | 0x80, 0x70, dp); cyberpro_grphw8(ext_mem_ctl, 0x70, dp);}#endif#ifdef USE_MMAP/* * Buffer support */static intcyberpro_alloc_frame_buffer(struct cyberpro_vidinfo *dp, struct framebuf *frame){ unsigned long addr; void *buffer; int pgidx; if (frame->buffer) return 0; /* * Allocate frame buffer */ buffer = vmalloc(NR_PAGES * PAGE_SIZE); if (frame->buffer) { vfree(buffer); return 0; } if (!buffer) return -ENOMEM; printk("Buffer allocated @ %p [", buffer); frame->buffer = buffer; frame->dbg = 1; /* * Don't leak information from the kernel. */ memset(buffer, 0x5a, NR_PAGES * PAGE_SIZE); /* * Now, reserve all the pages, and calculate * each pages' bus address. */ addr = (unsigned long)buffer; for (pgidx = 0; pgidx < NR_PAGES; pgidx++, addr += PAGE_SIZE) { struct page *page; pgd_t *pgd; pmd_t *pmd; pte_t *pte; /* * The page should be present. If not, * vmalloc has gone nuts. */ pgd = pgd_offset_k(addr); if (pgd_none(*pgd)) BUG(); pmd = pmd_offset(pgd, addr); if (pmd_none(*pmd)) BUG(); pte = pte_offset(pmd, addr); if (!pte_present(*pte)) BUG(); page = pte_page(*pte); frame->bus_addr[pgidx] = virt_to_bus((void *)page_address(page)); frame->pages[pgidx] = page; SetPageReserved(page); printk("%08lx (%08lx) ", page_address(page), frame->bus_addr[pgidx]); } printk("\n"); return 0;}static voidcyberpro_frames_free_one(struct cyberpro_vidinfo *dp, struct framebuf *frame){ void *buffer; int pgidx; frame->status = FRAME_FREE; buffer = frame->buffer; frame->buffer = NULL; if (buffer) { for (pgidx = 0; pgidx < NR_PAGES; pgidx++) { frame->bus_addr[pgidx] = 0; ClearPageReserved(frame->pages[pgidx]); frame->pages[pgidx] = NULL; } vfree(buffer); }}static voidcyberpro_busmaster_frame(struct cyberpro_vidinfo *dp, struct framebuf *frame){ unsigned long bus_addr; bus_addr = frame->bus_addr[dp->bm_index]; if (frame->dbg) { printk("Frame%d: %06x -> %08lx\n", dp->frame_idx, dp->bm_offset, bus_addr); } cyber2000_outw(dp->bm_offset, BM_VID_ADDR_LOW); cyber2000_outw(dp->bm_offset >> 16, BM_VID_ADDR_HIGH); cyber2000_outw(bus_addr, BM_ADDRESS_LOW); cyber2000_outw(bus_addr >> 16, BM_ADDRESS_HIGH); /* * One page-full only */ cyber2000_outw(1023, BM_LENGTH); /* * Load length */ cyber2000_outw(BM_CONTROL_INIT, BM_CONTROL); /* * Enable transfer */ cyber2000_outw(BM_CONTROL_ENABLE|BM_CONTROL_IRQEN, BM_CONTROL); dp->bm_offset += 1024; dp->bm_index += 1;}static void cyberpro_busmaster_interrupt(struct cyberpro_vidinfo *dp){ struct framebuf *frame = dp->frame + dp->frame_idx; /* * Disable Busmaster operations */ cyber2000_outw(0, BM_CONTROL); if (frame->status == FRAME_GRABBING) { /* * We are still grabbing this frame to system * memory. Transfer next page if there are * more, or else flag this frame as complete. */ if (dp->bm_index < NR_PAGES) cyberpro_busmaster_frame(dp); else { unsigned int idx; frame->status = FRAME_DONE; frame->dbg = 0; idx = dp->frame_idx + 1; if (idx >= NR_FRAMES) idx = 0; dp->frame_idx = idx; wake_up(&dp->frame_wait); } }}static void cyberpro_frames_vbl(struct cyberpro_vidinfo *dp, unsigned int stat){ struct framebuf *frame = dp->frame + dp->frame_idx; /* * No point capturing frames if the grabber isn't active. */ if (stat & EXT_ROM_UCB4GH_FREEZE) return; /* * If the next buffer is ready for grabbing, * set up the bus master registers for the * transfer. */ if (frame->status == FRAME_WAITING) { frame->status = FRAME_GRABBING; dp->bm_offset = dp->cap_mem_offset; dp->bm_index = 0; cyberpro_busmaster_frame(dp, frame); }}static void __init cyberpro_frames_init(struct cyberpro_vidinfo *dp){ unsigned int offset, maxsize; int i; init_waitqueue_head(&dp->frame_wait); maxsize = 2 * dp->cap.maxwidth * dp->cap.maxheight; dp->frame_size = PAGE_ALIGN(maxsize); dp->frame_idx = 0; for (i = offset = 0; i < NR_FRAMES; i++) { dp->frame[i].offset = offset; dp->frame[i].status = FRAME_FREE; offset += dp->frame_size; }}static void cyberpro_frames_free(struct cyberpro_vidinfo *dp){ int i; dp->mmaped = 0; /* * Free all frame buffers */ for (i = 0; i < NR_FRAMES; i++) cyberpro_frames_free_one(dp, dp->frame + i);}#else#define cyberpro_frames_vbl(dp,stat) do { } while (0)#define cyberpro_frames_init(dp) do { } while (0)#define cyberpro_frames_free(dp) do { } while (0)#endif/* * CyberPro Interrupts * ------------------- * * We don't really know how to signal an IRQ clear to the chip. However, * disabling and re-enabling the capture interrupt enable seems to do what * we want. */static void cyberpro_interrupt(int nr, void *dev_id, struct pt_regs *regs){ struct cyberpro_vidinfo *dp = dev_id; unsigned char old_grphidx; unsigned int status; /* * Save old graphics index register */ old_grphidx = cyberpro_readb(0x3ce, dp); status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); /* * Was it due to the Capture VSYNC? */ if (status & EXT_ROM_UCB4GH_INTSTAT) { /* * Frob the IRQ enable bit to drop the request. */ cyberpro_grphw8(VFAC_CTL3, dp->vfac3 & ~VFAC_CTL3_CAP_IRQ, dp); cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp); cyberpro_frames_vbl(dp, status); wake_up(&dp->vbl_wait); } /* * Restore graphics controller index */ cyberpro_writeb(old_grphidx, 0x3ce, dp);#ifdef USE_MMAP /* * Do Bus-Master IRQ stuff */ if (cyber2000_inb(BM_CONTROL) & (1 << 7)) cyberpro_busmaster_interrupt(dp);#endif}static void cyberpro_capture(struct cyberpro_vidinfo *dp, int on){ DECLARE_WAITQUEUE(wait, current); unsigned int status; status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); add_wait_queue(&dp->vbl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); if (!!on ^ !(status & EXT_ROM_UCB4GH_FREEZE)) { if (on) { schedule_timeout(40 * HZ / 1000); dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC); cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); } else { dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC; cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); if (!(status & EXT_ROM_UCB4GH_FREEZE)) schedule_timeout(40 * HZ / 1000); } } current->state = TASK_RUNNING; remove_wait_queue(&dp->vbl_wait, &wait);}static void cyberpro_capture_one(struct cyberpro_vidinfo *dp){ struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); unsigned int status; unsigned long policy, rt_priority; policy = tsk->policy; rt_priority = tsk->rt_priority; tsk->policy = SCHED_FIFO; tsk->rt_priority = 1; status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); add_wait_queue(&dp->vbl_wait, &wait); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(40 * HZ / 1000); dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC); cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(40 * HZ / 1000); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(40 * HZ / 1000); dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC; cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp); set_current_state(TASK_UNINTERRUPTIBLE); status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp); current->state = TASK_RUNNING; remove_wait_queue(&dp->vbl_wait, &wait); tsk->policy = policy; tsk->rt_priority = rt_priority;}static void cyberpro_capture_set_win(struct cyberpro_vidinfo *dp){ unsigned int xstart, xend, ystart, yend; xstart = 4 + dp->capt.x; xend = xstart + dp->capt.width; if (dp->cap_mode1 & EXT_CAP_MODE1_8BIT) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -