📄 neofb.c
字号:
!= (par->VCLK3NumeratorHigh & ~0x0F))))) { vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow); if (clock_hi) { temp = vga_rgfx(NULL, 0x8F); temp &= 0x0F; /* Save bits 3:0 */ temp |= (par->VCLK3NumeratorHigh & ~0x0F); vga_wgfx(NULL, 0x8F, temp); } vga_wgfx(NULL, 0x9F, par->VCLK3Denominator); } if (par->biosMode) vga_wcrt(NULL, 0x23, par->biosMode); vga_wgfx(NULL, 0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */ /* Program vertical extension register */ if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 || info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 || info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 || info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) { vga_wcrt(NULL, 0x70, par->VerticalExt); } vgaHWProtect(0); /* Turn on screen */ /* Calling this also locks offset registers required in update_start */ neoLock(&par->state); info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel >> 3); switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380: neo2200_accel_init(info, &info->var); break; default: break; } return 0;}/* * Pan or Wrap the Display */static int neofb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ struct neofb_par *par = info->par; struct vgastate *state = &par->state; int oldExtCRTDispAddr; int Base; DBG("neofb_update_start"); Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2; Base *= (var->bits_per_pixel + 7) / 8; neoUnlock(); /* * These are the generic starting address registers. */ vga_wcrt(state->vgabase, 0x0C, (Base & 0x00FF00) >> 8); vga_wcrt(state->vgabase, 0x0D, (Base & 0x00FF)); /* * Make sure we don't clobber some other bits that might already * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't * be needed. */ oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E); vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0))); neoLock(state); return 0;}static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *fb){ if (regno >= fb->cmap.len || regno > 255) return -EINVAL; if (fb->var.bits_per_pixel <= 8) { outb(regno, 0x3c8); outb(red >> 10, 0x3c9); outb(green >> 10, 0x3c9); outb(blue >> 10, 0x3c9); } else if (regno < 16) { switch (fb->var.bits_per_pixel) { case 16: ((u32 *) fb->pseudo_palette)[regno] = ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break; case 24: ((u32 *) fb->pseudo_palette)[regno] = ((red & 0xff00) << 8) | ((green & 0xff00)) | ((blue & 0xff00) >> 8); break;#ifdef NO_32BIT_SUPPORT_YET case 32: ((u32 *) fb->pseudo_palette)[regno] = ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) | ((green & 0xff00)) | ((blue & 0xff00) >> 8); break;#endif default: return 1; } } return 0;}/* * (Un)Blank the display. */static int neofb_blank(int blank_mode, struct fb_info *info){ /* * Blank the screen if blank_mode != 0, else unblank. * Return 0 if blanking succeeded, != 0 if un-/blanking failed due to * e.g. a video mode which doesn't support it. Implements VESA suspend * and powerdown modes for monitors, and backlight control on LCDs. * blank_mode == 0: unblanked (backlight on) * blank_mode == 1: blank (backlight on) * blank_mode == 2: suspend vsync (backlight off) * blank_mode == 3: suspend hsync (backlight off) * blank_mode == 4: powerdown (backlight off) * * wms...Enable VESA DPMS compatible powerdown mode * run "setterm -powersave powerdown" to take advantage */ struct neofb_par *par = info->par; int seqflags, lcdflags, dpmsflags, reg, tmpdisp; /* * Read back the register bits related to display configuration. They might * have been changed underneath the driver via Fn key stroke. */ neoUnlock(); tmpdisp = vga_rgfx(NULL, 0x20) & 0x03; neoLock(&par->state); /* In case we blank the screen, we want to store the possibly new * configuration in the driver. During un-blank, we re-apply this setting, * since the LCD bit will be cleared in order to switch off the backlight. */ if (par->PanelDispCntlRegRead) { par->PanelDispCntlReg1 = tmpdisp; } par->PanelDispCntlRegRead = !blank_mode; switch (blank_mode) { case FB_BLANK_POWERDOWN: /* powerdown - both sync lines down */ seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */ lcdflags = 0; /* LCD off */ dpmsflags = NEO_GR01_SUPPRESS_HSYNC | NEO_GR01_SUPPRESS_VSYNC;#ifdef CONFIG_TOSHIBA /* Do we still need this ? */ /* attempt to turn off backlight on toshiba; also turns off external */ { SMMRegisters regs; regs.eax = 0xff00; /* HCI_SET */ regs.ebx = 0x0002; /* HCI_BACKLIGHT */ regs.ecx = 0x0000; /* HCI_DISABLE */ tosh_smm(®s); }#endif break; case FB_BLANK_HSYNC_SUSPEND: /* hsync off */ seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */ lcdflags = 0; /* LCD off */ dpmsflags = NEO_GR01_SUPPRESS_HSYNC; break; case FB_BLANK_VSYNC_SUSPEND: /* vsync off */ seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */ lcdflags = 0; /* LCD off */ dpmsflags = NEO_GR01_SUPPRESS_VSYNC; break; case FB_BLANK_NORMAL: /* just blank screen (backlight stays on) */ seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */ /* * During a blank operation with the LID shut, we might store "LCD off" * by mistake. Due to timing issues, the BIOS may switch the lights * back on, and we turn it back off once we "unblank". * * So here is an attempt to implement ">=" - if we are in the process * of unblanking, and the LCD bit is unset in the driver but set in the * register, we must keep it. */ lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */ dpmsflags = 0x00; /* no hsync/vsync suppression */ break; case FB_BLANK_UNBLANK: /* unblank */ seqflags = 0; /* Enable sequencer */ lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */ dpmsflags = 0x00; /* no hsync/vsync suppression */#ifdef CONFIG_TOSHIBA /* Do we still need this ? */ /* attempt to re-enable backlight/external on toshiba */ { SMMRegisters regs; regs.eax = 0xff00; /* HCI_SET */ regs.ebx = 0x0002; /* HCI_BACKLIGHT */ regs.ecx = 0x0001; /* HCI_ENABLE */ tosh_smm(®s); }#endif break; default: /* Anything else we don't understand; return 1 to tell * fb_blank we didn't aactually do anything */ return 1; } neoUnlock(); reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags; vga_wseq(NULL, 0x01, reg); reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags; vga_wgfx(NULL, 0x20, reg); reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags; vga_wgfx(NULL, 0x01, reg); neoLock(&par->state); return 0;}static voidneo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect){ struct neofb_par *par = info->par; u_long dst, rop; dst = rect->dx + rect->dy * info->var.xres_virtual; rop = rect->rop ? 0x060000 : 0x0c0000; neo2200_wait_fifo(info, 4); /* set blt control */ writel(NEO_BC3_FIFO_EN | NEO_BC0_SRC_IS_FG | NEO_BC3_SKIP_MAPPING | // NEO_BC3_DST_XY_ADDR | // NEO_BC3_SRC_XY_ADDR | rop, &par->neo2200->bltCntl); switch (info->var.bits_per_pixel) { case 8: writel(rect->color, &par->neo2200->fgColor); break; case 16: case 24: writel(((u32 *) (info->pseudo_palette))[rect->color], &par->neo2200->fgColor); break; } writel(dst * ((info->var.bits_per_pixel + 7) >> 3), &par->neo2200->dstStart); writel((rect->height << 16) | (rect->width & 0xffff), &par->neo2200->xyExt);}static voidneo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area){ u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy; struct neofb_par *par = info->par; u_long src, dst, bltCntl; bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000; if ((dy > sy) || ((dy == sy) && (dx > sx))) { /* Start with the lower right corner */ sy += (area->height - 1); dy += (area->height - 1); sx += (area->width - 1); dx += (area->width - 1); bltCntl |= NEO_BC0_X_DEC | NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC; } src = sx * (info->var.bits_per_pixel >> 3) + sy*info->fix.line_length; dst = dx * (info->var.bits_per_pixel >> 3) + dy*info->fix.line_length; neo2200_wait_fifo(info, 4); /* set blt control */ writel(bltCntl, &par->neo2200->bltCntl); writel(src, &par->neo2200->srcStart); writel(dst, &par->neo2200->dstStart); writel((area->height << 16) | (area->width & 0xffff), &par->neo2200->xyExt);}static voidneo2200_imageblit(struct fb_info *info, const struct fb_image *image){ struct neofb_par *par = info->par; int s_pitch = (image->width * image->depth + 7) >> 3; int scan_align = info->pixmap.scan_align - 1; int buf_align = info->pixmap.buf_align - 1; int bltCntl_flags, d_pitch, data_len; // The data is padded for the hardware d_pitch = (s_pitch + scan_align) & ~scan_align; data_len = ((d_pitch * image->height) + buf_align) & ~buf_align; neo2200_sync(info); if (image->depth == 1) { if (info->var.bits_per_pixel == 24 && image->width < 16) { /* FIXME. There is a bug with accelerated color-expanded * transfers in 24 bit mode if the image being transferred * is less than 16 bits wide. This is due to insufficient * padding when writing the image. We need to adjust * struct fb_pixmap. Not yet done. */ cfb_imageblit(info, image); return; } bltCntl_flags = NEO_BC0_SRC_MONO; } else if (image->depth == info->var.bits_per_pixel) { bltCntl_flags = 0; } else { /* We don't currently support hardware acceleration if image * depth is different from display */ cfb_imageblit(info, image); return; } switch (info->var.bits_per_pixel) { case 8: writel(image->fg_color, &par->neo2200->fgColor); writel(image->bg_color, &par->neo2200->bgColor); break; case 16: case 24: writel(((u32 *) (info->pseudo_palette))[image->fg_color], &par->neo2200->fgColor); writel(((u32 *) (info->pseudo_palette))[image->bg_color], &par->neo2200->bgColor); break; } writel(NEO_BC0_SYS_TO_VID | NEO_BC3_SKIP_MAPPING | bltCntl_flags | // NEO_BC3_DST_XY_ADDR | 0x0c0000, &par->neo2200->bltCntl); writel(0, &par->neo2200->srcStart);// par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff); writel(((image->dx & 0xffff) * (info->var.bits_per_pixel >> 3) + image->dy * info->fix.line_length), &par->neo2200->dstStart); writel((image->height << 16) | (image->width & 0xffff), &par->neo2200->xyExt); memcpy_toio(par->mmio_vbase + 0x100000, image->data, data_len);}static voidneofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect){ switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380: neo2200_fillrect(info, rect); break; default: cfb_fillrect(info, rect); break; } }static voidneofb_copyarea(struct fb_info *info, const struct fb_copyarea *area){ switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380: neo2200_copyarea(info, area); break; default: cfb_copyarea(info, area); break; } }static voidneofb_imageblit(struct fb_info *info, const struct fb_image *image){ switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380: neo2200_imageblit(info, image); break; default: cfb_imageblit(info, image); break; }}static int neofb_sync(struct fb_info *info){ switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380: neo2200_sync(info); break; default: break; } return 0; }/*static voidneofb_draw_cursor(struct fb_info *info, u8 *dst, u8 *src, unsigned int width){ //memset_io(info->sprite.addr, 0xff, 1);}static intneofb_cursor(struct fb_info *info, struct fb_cursor *cursor){ struct neofb_par *par = (struct neofb_par *) info->par; * Disable cursor * write_le32(NEOREG_CURSCNTL, ~NEO_CURS_ENABLE, par); if (cursor->set & FB_CUR_SETPOS) { u32 x = cursor->image.dx; u32 y = cursor->image.dy; info->cursor.image.dx = x; info->cursor.image.dy = y; write_le32(NEOREG_CURSX, x, par); write_le32(NEOREG_CURSY, y, par); } if (cursor->set & FB_CUR_SETSIZE) { info->cursor.image.height = cursor->image.height; info->cursor.image.width = cursor->image.width; } if (cursor->set & FB_CUR_SETHOT) info->cursor.hot = cursor->hot; if (cursor->set & FB_CUR_SETCMAP) { if (cursor->image.depth == 1) { u32 fg = cursor->image.fg_color; u32 bg = cursor->image.bg_color; info->cursor.image.fg_color = fg; info->cursor.image.bg_color = bg; fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00); bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00); write_le32(NEOREG_CURSFGCOLOR, fg, par); write_le32(NEOREG_CURSBGCOLOR, bg, par); } } if (cursor->set & FB_CUR_SETSHAPE) fb_load_cursor_image(info); if (info->cursor.enable) write_le32(NEOREG_CURSCNTL, NEO_CURS_ENABLE, par); return 0;}*/static struct fb_ops neofb_ops = { .owner = THIS_MODULE, .fb_open = neofb_open, .fb_release = neofb_release, .fb_check_var = neofb_check_var, .fb_set_par = neofb_set_par, .fb_setcolreg = neofb_setcolreg, .fb_pan_display = neofb_pan_display, .fb_blank = neofb_blank, .fb_sync = neofb_sync, .fb_fillrect = neofb_fillrect, .fb_copyarea = neofb_copyarea, .fb_imageblit = neofb_imageblit,};/* --------------------------------------------------------------------- */static struct fb_videomode __devinitdata mode800x480 = { .xres = 800, .yres = 480, .pixclock = 25000, .left_margin = 88, .right_margin = 40, .upper_margin = 23, .lower_margin = 1, .hsync_len = 128, .vsync_len = 4, .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, .vmode = FB_VMODE_NONINTERLACED};static int __devinit neo_map_mmio(struct fb_info *info, struct pci_dev *dev){ struct neofb_par *par = info->par; DBG("neo_map_mmio"); switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2070: info->fix.mmio_start = pci_resource_start(dev, 0)+ 0x100000; break; case FB_ACCEL_NEOMAGIC_NM2090: case FB_ACCEL_NEOMAGIC_NM2093: info->fix.mmio_start = pci_resource_start(dev, 0)+ 0x200000; break; case FB_ACCEL_NEOMAGIC_NM2160: case FB_ACCEL_NEOMAGIC_NM2097: case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380: info->fix.mmio_start = pci_resource_start(dev, 1); break; default: info->fix.mmio_start = pci_resource_start(dev, 0); } info->fix.mmio_len = MMIO_SIZE; if (!request_mem_region (info->fix.mmio_start, MMIO_SIZE, "memory mapped I/O")) { printk("neofb: memory mapped IO in use\n"); return -EBUSY; } par->mmio_vbase = ioremap(info->fix.mmio_start, MMIO_SIZE); if (!par->mmio_vbase) { printk("neofb: unable to map memory mapped IO\n"); release_mem_region(info->fix.mmio_start, info->fix.mmio_len); return -ENOMEM; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -