📄 pm2fb.c
字号:
} } } }}static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn, unsigned char* pp) { unsigned char m; unsigned char n; unsigned char p; u32 f; s32 delta=1000; *mm=*nn=*pp=0; for (n=1; n; n++) { for (m=1; m; m++) { for (p=0; p<2; p++) { f=PM2_REFERENCE_CLOCK*n/(m * (1<<(p+1))); if (clk>f-delta && clk<f+delta) { delta=clk>f?clk-f:f-clk; *mm=m; *nn=n; *pp=p; } } } }}static void wait_pm2(struct pm2fb_info* i) { WAIT_FIFO(i, 1); pm2_WR(i, PM2R_SYNC, 0); DEFRW(); do { while (pm2_RD(i, PM2R_OUT_FIFO_WORDS)==0); DEFR(); } while (pm2_RD(i, PM2R_OUT_FIFO)!=PM2TAG(PM2R_SYNC));}static void pm2_set_memclock(struct pm2fb_info* info, u32 clk) { int i; unsigned char m, n, p; pm2_mnp(clk, &m, &n, &p); WAIT_FIFO(info, 10); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 6); DEFW(); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_1, m); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_2, n); DEFW(); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 8|p); DEFW(); pm2_RDAC_RD(info, PM2I_RD_MEMORY_CLOCK_STATUS); DEFR(); for (i=256; i && !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);}static void pm2_set_pixclock(struct pm2fb_info* info, u32 clk) { int i; unsigned char m, n, p; switch (info->type) { case PM2_TYPE_PERMEDIA2: pm2_mnp(clk, &m, &n, &p); WAIT_FIFO(info, 10); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0); DEFW(); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n); DEFW(); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p); DEFW(); pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS); DEFR(); for (i=256; i && !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--); break; case PM2_TYPE_PERMEDIA2V: pm2v_mnp(clk/2, &m, &n, &p); WAIT_FIFO(info, 8); pm2_WR(info, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8); pm2v_RDAC_WR(info, PM2VI_RD_CLK0_PRESCALE, m); pm2v_RDAC_WR(info, PM2VI_RD_CLK0_FEEDBACK, n); pm2v_RDAC_WR(info, PM2VI_RD_CLK0_POSTSCALE, p); pm2_WR(info, PM2VR_RD_INDEX_HIGH, 0); break; }}static void clear_palette(struct pm2fb_info* p) { int i=256; WAIT_FIFO(p, 1); pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0); DEFW(); while (i--) { WAIT_FIFO(p, 3); pm2_WR(p, PM2R_RD_PALETTE_DATA, 0); pm2_WR(p, PM2R_RD_PALETTE_DATA, 0); pm2_WR(p, PM2R_RD_PALETTE_DATA, 0); }}static void set_color(struct pm2fb_info* p, unsigned char regno, unsigned char r, unsigned char g, unsigned char b) { WAIT_FIFO(p, 4); pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno); DEFW(); pm2_WR(p, PM2R_RD_PALETTE_DATA, r); DEFW(); pm2_WR(p, PM2R_RD_PALETTE_DATA, g); DEFW(); pm2_WR(p, PM2R_RD_PALETTE_DATA, b);}static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) { WAIT_FIFO(i, 2);#ifdef __LITTLE_ENDIAN pm2_WR(i, PM2R_APERTURE_ONE, 0); pm2_WR(i, PM2R_APERTURE_TWO, 0);#else switch (p->depth) { case 8: case 24: pm2_WR(i, PM2R_APERTURE_ONE, 0); pm2_WR(i, PM2R_APERTURE_TWO, 1); break; case 16: pm2_WR(i, PM2R_APERTURE_ONE, 2); pm2_WR(i, PM2R_APERTURE_TWO, 1); break; case 32: pm2_WR(i, PM2R_APERTURE_ONE, 1); pm2_WR(i, PM2R_APERTURE_TWO, 1); break; }#endif}static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { u32 clrmode=0; u32 txtmap=0; u32 pixsize=0; u32 clrformat=0; u32 xres; u32 video, tmp; if (i->type == PM2_TYPE_PERMEDIA2V) { WAIT_FIFO(i, 1); pm2_WR(i, PM2VR_RD_INDEX_HIGH, 0); } xres=(p->width+31)&~31; set_aperture(i, p); DEFRW(); WAIT_FIFO(i, 27); pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0: PM2F_COLOR_KEY_TEST_OFF); switch (p->depth) { case 8: pm2_WR(i, PM2R_FB_READ_PIXEL, 0); clrformat=0x0e; break; case 16: pm2_WR(i, PM2R_FB_READ_PIXEL, 1); clrmode=PM2F_RD_TRUECOLOR|0x06; txtmap=PM2F_TEXTEL_SIZE_16; pixsize=1; clrformat=0x70; break; case 32: pm2_WR(i, PM2R_FB_READ_PIXEL, 2); clrmode=PM2F_RD_TRUECOLOR|0x08; txtmap=PM2F_TEXTEL_SIZE_32; pixsize=2; clrformat=0x20; break; case 24: pm2_WR(i, PM2R_FB_READ_PIXEL, 4); clrmode=PM2F_RD_TRUECOLOR|0x09; txtmap=PM2F_TEXTEL_SIZE_24; pixsize=4; clrformat=0x20; break; } pm2_WR(i, PM2R_SCREEN_SIZE, (p->height<<16)|p->width); pm2_WR(i, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE); pm2_WR(i, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE); pm2_WR(i, PM2R_FB_READ_MODE, partprod(xres)); pm2_WR(i, PM2R_LB_READ_MODE, partprod(xres)); pm2_WR(i, PM2R_TEXTURE_MAP_FORMAT, txtmap|partprod(xres)); pm2_WR(i, PM2R_H_TOTAL, p->htotal); pm2_WR(i, PM2R_HS_START, p->hsstart); pm2_WR(i, PM2R_HS_END, p->hsend); pm2_WR(i, PM2R_HG_END, p->hbend); pm2_WR(i, PM2R_HB_END, p->hbend); pm2_WR(i, PM2R_V_TOTAL, p->vtotal); pm2_WR(i, PM2R_VS_START, p->vsstart); pm2_WR(i, PM2R_VS_END, p->vsend); pm2_WR(i, PM2R_VB_END, p->vbend); pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride); DEFW(); pm2_WR(i, PM2R_SCREEN_BASE, p->base); /* HW cursor needs /VSYNC for recognizing vert retrace */ video=p->video & ~(PM2F_HSYNC_ACT_LOW|PM2F_VSYNC_ACT_LOW); video|=PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH; switch (i->type) { case PM2_TYPE_PERMEDIA2: tmp = PM2F_RD_PALETTE_WIDTH_8; pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB| PM2F_RD_GUI_ACTIVE|clrmode); if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) tmp |= 4; /* invert hsync */ if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) tmp |= 8; /* invert vsync */ pm2_RDAC_WR(i, PM2I_RD_MISC_CONTROL, tmp); break; case PM2_TYPE_PERMEDIA2V: tmp = 0; pm2v_RDAC_WR(i, PM2VI_RD_PIXEL_SIZE, pixsize); pm2v_RDAC_WR(i, PM2VI_RD_COLOR_FORMAT, clrformat); if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) tmp |= 1; /* invert hsync */ if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) tmp |= 4; /* invert vsync */ pm2v_RDAC_WR(i, PM2VI_RD_SYNC_CONTROL, tmp); pm2v_RDAC_WR(i, PM2VI_RD_MISC_CONTROL, 1); break; } pm2_WR(i, PM2R_VIDEO_CONTROL, video); pm2_set_pixclock(i, p->pixclock);};/* * copy with packed pixels (8/16bpp only). */static void pm2fb_pp_copy(struct pm2fb_info* i, s32 xsrc, s32 ysrc, s32 x, s32 y, s32 w, s32 h) { s32 scale=i->current_par.depth==8?2:1; s32 offset; if (!w || !h) return; WAIT_FIFO(i, 7); pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE| PM2F_CONFIG_FB_PACKED_DATA| PM2F_CONFIG_FB_READ_SOURCE_ENABLE); pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0); pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16| ((xsrc-x)&0xfff)); offset=(x&0x3)-(xsrc&0x3); pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale)); pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale)); pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w)); DEFW(); pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE| (x<xsrc?PM2F_INCREASE_X:0)| (y<ysrc?PM2F_INCREASE_Y:0)); wait_pm2(i);}/* * block operation. copy=0: rectangle fill, copy=1: rectangle copy. */static void pm2fb_block_op(struct pm2fb_info* i, int copy, s32 xsrc, s32 ysrc, s32 x, s32 y, s32 w, s32 h, u32 color) { if (!w || !h) return; WAIT_FIFO(i, 6); pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE| PM2F_CONFIG_FB_READ_SOURCE_ENABLE); pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0); if (copy) pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16| ((xsrc-x)&0xfff)); else pm2_WR(i, PM2R_FB_BLOCK_COLOR, color); pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x); pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w); DEFW(); pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE| (x<xsrc?PM2F_INCREASE_X:0)| (y<ysrc?PM2F_INCREASE_Y:0)| (copy?0:PM2F_RENDER_FASTFILL)); wait_pm2(i);}/*************************************************************************** * Begin of generic initialization functions ***************************************************************************/static void pm2fb_reset(struct pm2fb_info* p) { if (p->type == PM2_TYPE_PERMEDIA2V) pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0); pm2_WR(p, PM2R_RESET_STATUS, 0); DEFRW(); while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET); DEFRW();#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT DPRINTK("FIFO disconnect enabled\n"); pm2_WR(p, PM2R_FIFO_DISCON, 1); DEFRW();#endif if (board_table[p->board].init) board_table[p->board].init(p); WAIT_FIFO(p, 48); pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)& ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED)); pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L)); pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L)); pm2_WR(p, PM2R_FIFO_CONTROL, 0); pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION); pm2_WR(p, PM2R_APERTURE_ONE, 0); pm2_WR(p, PM2R_APERTURE_TWO, 0); pm2_WR(p, PM2R_LB_READ_FORMAT, 0); pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0); pm2_WR(p, PM2R_LB_READ_MODE, 0); pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0); pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0); pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0); pm2_WR(p, PM2R_WINDOW_ORIGIN, 0); pm2_WR(p, PM2R_FB_WINDOW_BASE, 0); pm2_WR(p, PM2R_LB_WINDOW_BASE, 0); pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L)); pm2_WR(p, PM2R_FB_HARD_WRITE_MASK, ~(0L)); pm2_WR(p, PM2R_FB_READ_PIXEL, 0); pm2_WR(p, PM2R_DITHER_MODE, 0); pm2_WR(p, PM2R_AREA_STIPPLE_MODE, 0); pm2_WR(p, PM2R_DEPTH_MODE, 0); pm2_WR(p, PM2R_STENCIL_MODE, 0); pm2_WR(p, PM2R_TEXTURE_ADDRESS_MODE, 0); pm2_WR(p, PM2R_TEXTURE_READ_MODE, 0); pm2_WR(p, PM2R_TEXEL_LUT_MODE, 0); pm2_WR(p, PM2R_YUV_MODE, 0); pm2_WR(p, PM2R_COLOR_DDA_MODE, 0); pm2_WR(p, PM2R_TEXTURE_COLOR_MODE, 0); pm2_WR(p, PM2R_FOG_MODE, 0); pm2_WR(p, PM2R_ALPHA_BLEND_MODE, 0); pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0); pm2_WR(p, PM2R_STATISTICS_MODE, 0); pm2_WR(p, PM2R_SCISSOR_MODE, 0); switch (p->type) { case PM2_TYPE_PERMEDIA2: pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */ pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0); pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8); break; case PM2_TYPE_PERMEDIA2V: pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1); /* 8bit */ break; } pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0); pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0); pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0); pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0); pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0); clear_palette(p); if (p->memclock) pm2_set_memclock(p, p->memclock);}static int __init pm2fb_conf(struct pm2fb_info* p){ for (p->board=0; board_table[p->board].detect && !(board_table[p->board].detect(p)); p->board++); if (!board_table[p->board].detect) { DPRINTK("no board found.\n"); return 0; } DPRINTK("found board: %s\n", board_table[p->board].name); p->regions.p_fb=p->regions.fb_base; if (!request_mem_region(p->regions.p_fb, p->regions.fb_size, "pm2fb")) { printk (KERN_ERR "pm2fb: cannot reserve fb memory, abort\n"); return 0; } p->regions.v_fb=MMAP(p->regions.p_fb, p->regions.fb_size);#ifndef PM2FB_BE_APERTURE p->regions.p_regs=p->regions.rg_base;#else p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE;#endif if (!request_mem_region(p->regions.p_regs, PM2_REGS_SIZE, "pm2fb")) { printk (KERN_ERR "pm2fb: cannot reserve mmio memory, abort\n"); UNMAP(p->regions.v_fb, p->regions.fb_size); return 0; } p->regions.v_regs=MMAP(p->regions.p_regs, PM2_REGS_SIZE);#ifdef PM2FB_HW_CURSOR p->cursor = pm2_init_cursor(p);#endif return 1;}/*************************************************************************** * Begin of per-board initialization functions ***************************************************************************//* * Phase5 CvisionPPC/BVisionPPC */#ifdef CONFIG_FB_PM2_CVPPCstatic int cvppc_PCI_init(struct cvppc_par* p) { extern u32 powerup_PCI_present; if (!powerup_PCI_present) { DPRINTK("no PCI bridge detected\n"); return 0; } if (!(p->pci_config=MMAP(CVPPC_PCI_CONFIG, 256))) { DPRINTK("unable to map PCI config region\n"); return 0; } if (RD32(p->pci_config, PCI_VENDOR_ID)!= ((PCI_DEVICE_ID_TI_TVP4020<<16)|PCI_VENDOR_ID_TI)) { DPRINTK("bad vendorID/deviceID\n"); return 0; } if (!(p->pci_bridge=MMAP(CSPPC_PCI_BRIDGE, 256))) { DPRINTK("unable to map PCI bridge\n"); return 0; } WR32(p->pci_bridge, CSPPC_BRIDGE_ENDIAN, CSPPCF_BRIDGE_BIG_ENDIAN); DEFW(); if (pm2fb_options.flags & OPTF_OLD_MEM) WR32(p->pci_config, PCI_CACHE_LINE_SIZE, 0xff00); WR32(p->pci_config, PCI_BASE_ADDRESS_0, CVPPC_REGS_REGION); WR32(p->pci_config, PCI_BASE_ADDRESS_1, CVPPC_FB_APERTURE_ONE); WR32(p->pci_config, PCI_BASE_ADDRESS_2, CVPPC_FB_APERTURE_TWO); WR32(p->pci_config, PCI_ROM_ADDRESS, CVPPC_ROM_ADDRESS); DEFW(); WR32(p->pci_config, PCI_COMMAND, 0xef000000 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); return 1;}static int __init cvppc_detect(struct pm2fb_info* p) { if (!cvppc_PCI_init(&p->board_par.cvppc)) return 0; p->type = PM2_TYPE_PERMEDIA2; p->regions.fb_base=CVPPC_FB_APERTURE_ONE; p->regions.fb_size=CVPPC_FB_SIZE; p->regions.rg_base=CVPPC_REGS_REGION; p->memclock=CVPPC_MEMCLOCK; return 1;}static void cvppc_init(struct pm2fb_info* p) { WAIT_FIFO(p, 3); pm2_WR(p, PM2R_MEM_CONTROL, 0); pm2_WR(p, PM2R_BOOT_ADDRESS, 0x30); DEFW(); if (pm2fb_options.flags & OPTF_OLD_MEM) pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_OLD); else pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_NEW);}#endif /* CONFIG_FB_PM2_CVPPC *//* * Generic PCI detection routines */#ifdef CONFIG_FB_PM2_PCIstruct { unsigned short vendor, device; char *name; pm2type_t type;} pm2pci_cards[] __initdata = {{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020, "Texas Instruments TVP4020", PM2_TYPE_PERMEDIA2 },{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2, "3dLabs Permedia 2", PM2_TYPE_PERMEDIA2 },{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V, "3dLabs Permedia 2v", PM2_TYPE_PERMEDIA2V },{ 0, 0 }};static int __init pm2pci_detect(struct pm2fb_info* p) { struct pm2pci_par* pci=&p->board_par.pci; struct pci_dev* dev; int i; unsigned char* m;#ifdef __sparc__ struct pcidev_cookie *pcp;#endif memset(pci, 0, sizeof(struct pm2pci_par)); if (!pci_present()) { DPRINTK("no PCI bus found.\n"); return 0; } DPRINTK("scanning PCI bus for known chipsets...\n"); pci_for_each_dev(dev) { for (i = 0; pm2pci_cards[i].vendor; i++) if (pm2pci_cards[i].vendor == dev->vendor && pm2pci_cards[i].device == dev->device) { pci->dev = dev; p->type = pm2pci_cards[i].type; DPRINTK("... found %s\n", pm2pci_cards[i].name); break; } if (pci->dev) break; } if (!pci->dev) { DPRINTK("no PCI board found.\n"); return 0; } DPRINTK("PCI board @%08lx %08lx %08lx rom %08lx\n", pci->dev->resource[0].start, pci->dev->resource[1].start, pci->dev->resource[2].start, pci->dev->resource[PCI_ROM_RESOURCE].start);#ifdef __sparc__ p->regions.rg_base= pci->dev->resource[0].start; p->regions.fb_base= pci->dev->resource[1].start; pcp = pci->dev->sysdata; /* If the user has not asked for a particular mode, lets guess */ if (pcp->prom_node && !(pm2fb_options.flags & OPTF_USER)) { char timing[256], *q, *r; unsigned long w, h; int i; prom_getstring(pcp->prom_node, "timing-numbers", timing, 256); /* FIXME: Find out what the actual pixclock is and other values as well */ if (timing[0]) { w = simple_strtoul(timing, &q, 0); h = 0; if (q == timing) w = 0; if (w) { for (i = 0; i < 3; i++) { for (r = q; *r && (*r < '0' || *r > '9'); r++);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -