From: James Simmons <jsimmons@infradead.org> Here is a updated driver for the neomagic. http://phoenix.infradead.org:~/jsimmons/neofb.diff.gz The patch is a bit big. I tested on my laptop. --- 25-akpm/drivers/video/Makefile | 2 25-akpm/drivers/video/neofb.c | 509 ++++++++++++++++++++++----------------- 25-akpm/include/video/neomagic.h | 269 +++++++------------- 3 files changed, 399 insertions(+), 381 deletions(-) diff -puN drivers/video/Makefile~neomagic-driver-update drivers/video/Makefile --- 25/drivers/video/Makefile~neomagic-driver-update 2004-04-21 18:11:53.905078352 -0700 +++ 25-akpm/drivers/video/Makefile 2004-04-21 18:11:53.911077440 -0700 @@ -22,7 +22,7 @@ obj-$(CONFIG_FB_Q40) += q40 obj-$(CONFIG_FB_ATARI) += atafb.o obj-$(CONFIG_FB_68328) += 68328fb.o obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_CONTROL) += controlfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_PLATINUM) += platinumfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o diff -puN drivers/video/neofb.c~neomagic-driver-update drivers/video/neofb.c --- 25/drivers/video/neofb.c~neomagic-driver-update 2004-04-21 18:11:53.906078200 -0700 +++ 25-akpm/drivers/video/neofb.c 2004-04-21 18:11:53.916076680 -0700 @@ -81,13 +81,13 @@ extern int tosh_smm(SMMRegisters *regs); #include <asm/mtrr.h> #endif +#include <video/vga.h> #include <video/neomagic.h> -#define NEOFB_VERSION "0.4.1" +#define NEOFB_VERSION "0.4.2" /* --------------------------------------------------------------------- */ -static int disabled; static int internal; static int external; static int libretto; @@ -100,8 +100,6 @@ static int nopciburst; MODULE_AUTHOR("(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips"); -MODULE_PARM(disabled, "i"); -MODULE_PARM_DESC(disabled, "Disable this driver's initialization."); MODULE_PARM(internal, "i"); MODULE_PARM_DESC(internal, "Enable output on internal LCD Display."); MODULE_PARM(external, "i"); @@ -152,6 +150,16 @@ static biosMode bios32[] = { }; #endif +static inline u32 read_le32(int regindex, const struct neofb_par *par) +{ + return readl(par->neo2200 + par->cursorOff + regindex); +} + +static inline void write_le32(int regindex, u32 val, const struct neofb_par *par) +{ + writel(val, par->neo2200 + par->cursorOff + regindex); +} + static int neoFindMode(int xres, int yres, int depth) { int xres_s; @@ -363,44 +371,61 @@ static int vgaHWInit(const struct fb_var par->Attribute[18] = 0x0F; par->Attribute[19] = 0x00; par->Attribute[20] = 0x00; - return 0; } -static void vgaHWLock(void) +static void vgaHWLock(struct vgastate *state) { /* Protect CRTC[0-7] */ - VGAwCR(0x11, VGArCR(0x11) | 0x80); + vga_wcrt(state->vgabase, 0x11, vga_rcrt(state->vgabase, 0x11) | 0x80); } static void vgaHWUnlock(void) { /* Unprotect CRTC[0-7] */ - VGAwCR(0x11, VGArCR(0x11) & ~0x80); + vga_wcrt(NULL, 0x11, vga_rcrt(NULL, 0x11) & ~0x80); } -static void neoLock(void) +static void neoLock(struct vgastate *state) { - VGAwGR(0x09, 0x00); - vgaHWLock(); + vga_wgfx(state->vgabase, 0x09, 0x00); + vgaHWLock(state); } static void neoUnlock(void) { vgaHWUnlock(); - VGAwGR(0x09, 0x26); + vga_wgfx(NULL, 0x09, 0x26); } /* - * vgaHWSeqReset - * perform a sequencer reset. + * VGA Palette management */ -void vgaHWSeqReset(int start) +static int paletteEnabled = 0; + +inline void VGAenablePalette(void) { - if (start) - VGAwSEQ(0x00, 0x01); /* Synchronous Reset */ + vga_r(NULL, VGA_IS1_RC); + vga_w(NULL, VGA_ATT_W, 0x00); + paletteEnabled = 1; +} + +inline void VGAdisablePalette(void) +{ + vga_r(NULL, VGA_IS1_RC); + vga_w(NULL, VGA_ATT_W, 0x20); + paletteEnabled = 0; +} + +inline void VGAwATTR(u8 index, u8 value) +{ + if (paletteEnabled) + index &= ~0x20; else - VGAwSEQ(0x00, 0x03); /* End Reset */ + index |= 0x20; + + vga_r(NULL, VGA_IS1_RC); + vga_wattr(NULL, index, value); } void vgaHWProtect(int on) @@ -411,21 +436,18 @@ void vgaHWProtect(int on) /* * Turn off screen and disable sequencer. */ - tmp = VGArSEQ(0x01); - - vgaHWSeqReset(1); /* start synchronous reset */ - VGAwSEQ(0x01, tmp | 0x20); /* disable the display */ + tmp = vga_rseq(NULL, 0x01); + vga_wseq(NULL, 0x00, 0x01); /* Synchronous Reset */ + vga_wseq(NULL, 0x01, tmp | 0x20); /* disable the display */ VGAenablePalette(); } else { /* * Reenable sequencer, then turn on screen. */ - - tmp = VGArSEQ(0x01); - - VGAwSEQ(0x01, tmp & ~0x20); /* reenable display */ - vgaHWSeqReset(0); /* clear synchronousreset */ + tmp = vga_rseq(NULL, 0x01); + vga_wseq(NULL, 0x01, tmp & ~0x20); /* reenable display */ + vga_wseq(NULL, 0x00, 0x03); /* clear synchronousreset */ VGAdisablePalette(); } @@ -436,19 +458,19 @@ static void vgaHWRestore(const struct fb { int i; - VGAwMISC(par->MiscOutReg); + vga_w(NULL, VGA_MIS_W, par->MiscOutReg); for (i = 1; i < 5; i++) - VGAwSEQ(i, par->Sequencer[i]); + vga_wseq(NULL, i, par->Sequencer[i]); /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */ - VGAwCR(17, par->CRTC[17] & ~0x80); + vga_wcrt(NULL, 17, par->CRTC[17] & ~0x80); for (i = 0; i < 25; i++) - VGAwCR(i, par->CRTC[i]); + vga_wcrt(NULL, i, par->CRTC[i]); for (i = 0; i < 9; i++) - VGAwGR(i, par->Graphics[i]); + vga_wgfx(NULL, i, par->Graphics[i]); VGAenablePalette(); @@ -535,6 +557,36 @@ static inline void neo2200_accel_init(st /* --------------------------------------------------------------------- */ static int +neofb_open(struct fb_info *info, int user) +{ + struct neofb_par *par = (struct neofb_par *) info->par; + int cnt = atomic_read(&par->ref_count); + + if (cnt) { + memset(&par->state, 0, sizeof(struct vgastate)); + par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; + save_vga(&par->state); + } + atomic_inc(&par->ref_count); + return 0; +} + +static int +neofb_release(struct fb_info *info, int user) +{ + struct neofb_par *par = (struct neofb_par *) info->par; + int cnt = atomic_read(&par->ref_count); + + if (!cnt) + return -EINVAL; + if (cnt == 1) { + restore_vga(&par->state); + } + atomic_dec(&par->ref_count); + return 0; +} + +static int neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct neofb_par *par = (struct neofb_par *) info->par; @@ -672,16 +724,13 @@ neofb_check_var(struct fb_var_screeninfo if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; - memlen = - var->xres_virtual * var->bits_per_pixel * var->yres_virtual / - 8; + memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual >> 3; + if (memlen > vramlen) { - var->yres_virtual = - vramlen * 8 / (var->xres_virtual * - var->bits_per_pixel); - memlen = - var->xres_virtual * var->bits_per_pixel * - var->yres_virtual / 8; + var->yres_virtual = vramlen * 8 / (var->xres_virtual * + var->bits_per_pixel); + memlen = var->xres_virtual * var->bits_per_pixel * + var->yres_virtual / 8; } /* we must round yres/xres down, we already rounded y/xres_virtual up @@ -981,13 +1030,13 @@ static int neofb_set_par(struct fb_info } /* alread unlocked above */ - /* BOGUS VGAwGR (0x09, 0x26); */ + /* BOGUS vga_wgfx(NULL, 0x09, 0x26); */ /* don't know what this is, but it's 0 from bootup anyway */ - VGAwGR(0x15, 0x00); + vga_wgfx(NULL, 0x15, 0x00); /* was set to 0x01 by my bios in text and vesa modes */ - VGAwGR(0x0A, par->GeneralLockReg); + vga_wgfx(NULL, 0x0A, par->GeneralLockReg); /* * The color mode needs to be set before calling vgaHWRestore @@ -996,7 +1045,7 @@ static int neofb_set_par(struct fb_info * NOTE: Make sure we don't change bits make sure we don't change * any reserved bits. */ - temp = VGArGR(0x90); + temp = vga_rgfx(NULL, 0x90); switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2070: temp &= 0xF0; /* Save bits 7:4 */ @@ -1015,7 +1064,7 @@ static int neofb_set_par(struct fb_info break; } - VGAwGR(0x90, temp); + vga_wgfx(NULL, 0x90, temp); /* * In some rare cases a lockup might occur if we don't delay @@ -1027,9 +1076,9 @@ static int neofb_set_par(struct fb_info * Disable horizontal and vertical graphics and text expansions so * that vgaHWRestore works properly. */ - temp = VGArGR(0x25); + temp = vga_rgfx(NULL, 0x25); temp &= 0x39; - VGAwGR(0x25, temp); + vga_wgfx(NULL, 0x25, temp); /* * Sleep for 200ms to make sure that the two operations above have @@ -1041,19 +1090,18 @@ static int neofb_set_par(struct fb_info * This function handles restoring the generic VGA registers. */ vgaHWRestore(info, par); - - VGAwGR(0x0E, par->ExtCRTDispAddr); - VGAwGR(0x0F, par->ExtCRTOffset); - temp = VGArGR(0x10); + vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr); + vga_wgfx(NULL, 0x0F, par->ExtCRTOffset); + temp = vga_rgfx(NULL, 0x10); temp &= 0x0F; /* Save bits 3:0 */ temp |= (par->SysIfaceCntl1 & ~0x0F); /* VESA Bios sets bit 1! */ - VGAwGR(0x10, temp); + vga_wgfx(NULL, 0x10, temp); - VGAwGR(0x11, par->SysIfaceCntl2); - VGAwGR(0x15, 0 /*par->SingleAddrPage */ ); - VGAwGR(0x16, 0 /*par->DualAddrPage */ ); + vga_wgfx(NULL, 0x11, par->SysIfaceCntl2); + vga_wgfx(NULL, 0x15, 0 /*par->SingleAddrPage */ ); + vga_wgfx(NULL, 0x16, 0 /*par->DualAddrPage */ ); - temp = VGArGR(0x20); + temp = vga_rgfx(NULL, 0x20); switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2070: temp &= 0xFC; /* Save bits 7:2 */ @@ -1074,79 +1122,78 @@ static int neofb_set_par(struct fb_info temp |= (par->PanelDispCntlReg1 & ~0x98); break; } - VGAwGR(0x20, temp); + vga_wgfx(NULL, 0x20, temp); - temp = VGArGR(0x25); + temp = vga_rgfx(NULL, 0x25); temp &= 0x38; /* Save bits 5:3 */ temp |= (par->PanelDispCntlReg2 & ~0x38); - VGAwGR(0x25, temp); + vga_wgfx(NULL, 0x25, temp); if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) { - temp = VGArGR(0x30); + temp = vga_rgfx(NULL, 0x30); temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */ temp |= (par->PanelDispCntlReg3 & ~0xEF); - VGAwGR(0x30, temp); + vga_wgfx(NULL, 0x30, temp); } - VGAwGR(0x28, par->PanelVertCenterReg1); - VGAwGR(0x29, par->PanelVertCenterReg2); - VGAwGR(0x2a, par->PanelVertCenterReg3); + vga_wgfx(NULL, 0x28, par->PanelVertCenterReg1); + vga_wgfx(NULL, 0x29, par->PanelVertCenterReg2); + vga_wgfx(NULL, 0x2a, par->PanelVertCenterReg3); if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) { - VGAwGR(0x32, par->PanelVertCenterReg4); - VGAwGR(0x33, par->PanelHorizCenterReg1); - VGAwGR(0x34, par->PanelHorizCenterReg2); - VGAwGR(0x35, par->PanelHorizCenterReg3); + vga_wgfx(NULL, 0x32, par->PanelVertCenterReg4); + vga_wgfx(NULL, 0x33, par->PanelHorizCenterReg1); + vga_wgfx(NULL, 0x34, par->PanelHorizCenterReg2); + vga_wgfx(NULL, 0x35, par->PanelHorizCenterReg3); } if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2160) - VGAwGR(0x36, par->PanelHorizCenterReg4); + vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4); 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) { - VGAwGR(0x36, par->PanelHorizCenterReg4); - VGAwGR(0x37, par->PanelVertCenterReg5); - VGAwGR(0x38, par->PanelHorizCenterReg5); + vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4); + vga_wgfx(NULL, 0x37, par->PanelVertCenterReg5); + vga_wgfx(NULL, 0x38, par->PanelHorizCenterReg5); clock_hi = 1; } /* Program VCLK3 if needed. */ - if (par->ProgramVCLK && ((VGArGR(0x9B) != par->VCLK3NumeratorLow) - || (VGArGR(0x9F) != par->VCLK3Denominator) - || (clock_hi && ((VGArGR(0x8F) & ~0x0f) - != (par-> - VCLK3NumeratorHigh & + if (par->ProgramVCLK && ((vga_rgfx(NULL, 0x9B) != par->VCLK3NumeratorLow) + || (vga_rgfx(NULL, 0x9F) != par->VCLK3Denominator) + || (clock_hi && ((vga_rgfx(NULL, 0x8F) & ~0x0f) + != (par->VCLK3NumeratorHigh & ~0x0F))))) { - VGAwGR(0x9B, par->VCLK3NumeratorLow); + vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow); if (clock_hi) { - temp = VGArGR(0x8F); + temp = vga_rgfx(NULL, 0x8F); temp &= 0x0F; /* Save bits 3:0 */ temp |= (par->VCLK3NumeratorHigh & ~0x0F); - VGAwGR(0x8F, temp); + vga_wgfx(NULL, 0x8F, temp); } - VGAwGR(0x9F, par->VCLK3Denominator); + vga_wgfx(NULL, 0x9F, par->VCLK3Denominator); } if (par->biosMode) - VGAwCR(0x23, par->biosMode); + vga_wcrt(NULL, 0x23, par->biosMode); - VGAwGR(0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */ + 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) { - VGAwCR(0x70, par->VerticalExt); + vga_wcrt(NULL, 0x70, par->VerticalExt); } vgaHWProtect(0); /* Turn on screen */ /* Calling this also locks offset registers required in update_start */ - neoLock(); + neoLock(&par->state); info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel >> 3); @@ -1167,6 +1214,8 @@ static int neofb_set_par(struct fb_info static void neofb_update_start(struct fb_info *info, struct fb_var_screeninfo *var) { + struct neofb_par *par = (struct neofb_par *) info->par; + struct vgastate *state = &par->state; int oldExtCRTDispAddr; int Base; @@ -1180,18 +1229,18 @@ static void neofb_update_start(struct fb /* * These are the generic starting address registers. */ - VGAwCR(0x0C, (Base & 0x00FF00) >> 8); - VGAwCR(0x0D, (Base & 0x00FF)); + 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 = VGArGR(0x0E); - VGAwGR(0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0))); + oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E); + vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0))); - neoLock(); + neoLock(state); } /* @@ -1227,7 +1276,7 @@ static int neofb_pan_display(struct fb_v 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 >= NR_PALETTE) + if (regno >= 255) return -EINVAL; switch (fb->var.bits_per_pixel) { @@ -1353,7 +1402,7 @@ neo2200_fillrect(struct fb_info *info, c } par->neo2200->dstStart = - dst * ((info->var.bits_per_pixel + 7) / 8); + dst * ((info->var.bits_per_pixel + 7) >> 3); par->neo2200->xyExt = (rect->height << 16) | (rect->width & 0xffff); } @@ -1361,24 +1410,20 @@ neo2200_fillrect(struct fb_info *info, c static void neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area) { - struct neofb_par *par = (struct neofb_par *) info->par; u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy; + struct neofb_par *par = (struct neofb_par *) info->par; u_long src, dst, bltCntl; bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000; - if (sy < dy) { + if ((dy > sy) || ((dy == sy) && (dx > sx))) { + /* Start with the lower right corner */ sy += (area->height - 1); dy += (area->height - 1); - - bltCntl |= NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC; - } - - if (area->sx < area->dx) { sx += (area->width - 1); dx += (area->width - 1); - bltCntl |= NEO_BC0_X_DEC; + 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; @@ -1395,6 +1440,7 @@ neo2200_copyarea(struct fb_info *info, c (area->height << 16) | (area->width & 0xffff); } +/* static void neo2200_imageblit(struct fb_info *info, const struct fb_image *image) { @@ -1431,6 +1477,7 @@ neo2200_imageblit(struct fb_info *info, memcpy(par->mmio_vbase + 0x100000, image->data, (image->width * image->height) >> 3); } +*/ static void neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) @@ -1439,7 +1486,7 @@ neofb_fillrect(struct fb_info *info, con case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: - case FB_ACCEL_NEOMAGIC_NM2380: + case FB_ACCEL_NEOMAGIC_NM2380: neo2200_fillrect(info, rect); break; default: @@ -1467,17 +1514,22 @@ neofb_copyarea(struct fb_info *info, con static void neofb_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; - } +/* + if (image->depth == 1) { + 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; + } + } else +*/ + cfb_imageblit(info, image); } static int @@ -1496,8 +1548,67 @@ neofb_sync(struct fb_info *info) return 0; } +/* +static void +neofb_draw_cursor(struct fb_info *info, u8 *dst, u8 *src, unsigned int width) +{ + //memset_io(info->sprite.addr, 0xff, 1); +} + +static int +neofb_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, @@ -1631,31 +1742,31 @@ static int __devinit neo_map_mmio(struct return 0; } -static void __devinit neo_unmap_mmio(struct fb_info *info) +static void neo_unmap_mmio(struct fb_info *info) { struct neofb_par *par = (struct neofb_par *) info->par; DBG("neo_unmap_mmio"); - if (par->mmio_vbase) { - iounmap(par->mmio_vbase); - par->mmio_vbase = NULL; + iounmap(par->mmio_vbase); + par->mmio_vbase = NULL; - release_mem_region(info->fix.mmio_start, - info->fix.mmio_len); - } + release_mem_region(info->fix.mmio_start, + info->fix.mmio_len); } static int __devinit neo_map_video(struct fb_info *info, struct pci_dev *dev, int video_len) { + //unsigned long addr; + DBG("neo_map_video"); info->fix.smem_start = pci_resource_start(dev, 0); info->fix.smem_len = video_len; - if (!request_mem_region - (info->fix.smem_start, info->fix.smem_len, "frame buffer")) { + if (!request_mem_region(info->fix.smem_start, info->fix.smem_len, + "frame buffer")) { printk("neofb: frame buffer in use\n"); return -EBUSY; } @@ -1673,33 +1784,38 @@ static int __devinit neo_map_video(struc #ifdef CONFIG_MTRR ((struct neofb_par *)(info->par))->mtrr = - mtrr_add(info->fix.smem_start, pci_resource_len(dev, 0), - MTRR_TYPE_WRCOMB, 1); + mtrr_add(info->fix.smem_start, pci_resource_len(dev, 0), + MTRR_TYPE_WRCOMB, 1); #endif /* Clear framebuffer, it's all white in memory after boot */ memset(info->screen_base, 0, info->fix.smem_len); + + /* Allocate Cursor drawing pad. + info->fix.smem_len -= PAGE_SIZE; + addr = info->fix.smem_start + info->fix.smem_len; + write_le32(NEOREG_CURSMEMPOS, ((0x000f & (addr >> 10)) << 8) | + ((0x0ff0 & (addr >> 10)) >> 4), par); + addr = (unsigned long) info->screen_base + info->fix.smem_len; + info->sprite.addr = (u8 *) addr; */ return 0; } -static void __devinit neo_unmap_video(struct fb_info *info) +static void neo_unmap_video(struct fb_info *info) { - DBG("neo_unmap_video"); - if (info->screen_base) { #ifdef CONFIG_MTRR - struct neofb_par *par = (struct neofb_par *) info->par; - mtrr_del(par->mtrr, info->fix.smem_start, - info->fix.smem_len); -#endif + struct neofb_par *par = (struct neofb_par *) info->par; - iounmap(info->screen_base); - info->screen_base = NULL; + mtrr_del(par->mtrr, info->fix.smem_start, + info->fix.smem_len); +#endif + iounmap(info->screen_base); + info->screen_base = NULL; - release_mem_region(info->fix.smem_start, - info->fix.smem_len); - } + release_mem_region(info->fix.smem_start, + info->fix.smem_len); } static int __devinit neo_init_hw(struct fb_info *info) @@ -1723,16 +1839,16 @@ static int __devinit neo_init_hw(struct printk(KERN_DEBUG "--- Neo extended register dump ---\n"); for (w = 0; w < 0x85; w++) printk(KERN_DEBUG "CR %p: %p\n", (void *) w, - (void *) VGArCR(w)); + (void *) vga_rcrt(NULL, w); for (w = 0; w < 0xC7; w++) printk(KERN_DEBUG "GR %p: %p\n", (void *) w, - (void *) VGArGR(w)); + (void *) vga_rgfx(NULL, w)); #endif /* Determine the panel type */ - VGAwGR(0x09, 0x26); - type = VGArGR(0x21); - display = VGArGR(0x20); + vga_wgfx(NULL, 0x09, 0x26); + type = vga_rgfx(NULL, 0x21); + display = vga_rgfx(NULL, 0x20); if (!par->internal_display && !par->external_display) { par->internal_display = display & 2 || !(display & 3) ? 1 : 0; par->external_display = display & 1; @@ -1742,8 +1858,8 @@ static int __devinit neo_init_hw(struct } /* Determine panel width -- used in NeoValidMode. */ - w = VGArGR(0x20); - VGAwGR(0x09, 0x00); + w = vga_rgfx(NULL, 0x20); + vga_wgfx(NULL, 0x09, 0x00); switch ((w & 0x18) >> 3) { case 0x00: par->NeoPanelWidth = 640; @@ -1868,10 +1984,16 @@ static int __devinit neo_init_hw(struct par->neo2200 = (Neo2200 *) par->mmio_vbase; break; } - +/* + info->sprite.size = CursorMem; + info->sprite.scan_align = 1; + info->sprite.buf_align = 1; + info->sprite.flags = FB_PIXMAP_IO; + info->sprite.outbuf = neofb_draw_cursor; +*/ par->maxClock = maxClock; - - return videoRam * 1024; + par->cursorOff = CursorOff; + return ((videoRam * 1024)); } @@ -1881,15 +2003,12 @@ static struct fb_info *__devinit neo_all struct fb_info *info; struct neofb_par *par; - info = kmalloc(sizeof(struct fb_info) + sizeof(struct neofb_par) + - sizeof(u32) * 17, GFP_KERNEL); + info = framebuffer_alloc(sizeof(struct neofb_par) + sizeof(u32) * 256, &dev->dev); if (!info) return NULL; - memset(info, 0, sizeof(struct fb_info) + sizeof(struct neofb_par) + sizeof(u32) * 17); - - par = (struct neofb_par *) (info + 1); + par = info->par; info->fix.accel = id->driver_data; @@ -1939,23 +2058,18 @@ static struct fb_info *__devinit neo_all info->fbops = &neofb_ops; info->flags = FBINFO_FLAG_DEFAULT; - info->par = par; info->pseudo_palette = (void *) (par + 1); - - fb_alloc_cmap(&info->cmap, NR_PALETTE, 0); - return info; } -static void __devinit neo_free_fb_info(struct fb_info *info) +static void neo_free_fb_info(struct fb_info *info) { if (info) { /* * Free the colourmap */ - fb_alloc_cmap(&info->cmap, 0, 0); - - kfree(info); + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); } } @@ -1978,21 +2092,24 @@ static int __devinit neofb_probe(struct err = -ENOMEM; info = neo_alloc_fb_info(dev, id); if (!info) - goto failed; + return err; err = neo_map_mmio(info, dev); if (err) - goto failed; + goto err_map_mmio; video_len = neo_init_hw(info); if (video_len < 0) { err = video_len; - goto failed; + goto err_init_hw; } err = neo_map_video(info, dev, video_len); if (err) - goto failed; + goto err_init_hw; + + if (neofb_check_var(&info->var, info)) + goto err_map_video; /* * Calculate the hsync and vsync frequencies. Note that @@ -2013,10 +2130,12 @@ static int __devinit neofb_probe(struct info->fix.smem_len >> 10, info->var.xres, info->var.yres, h_sync / 1000, h_sync % 1000, v_sync); + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) + goto err_map_video; err = register_framebuffer(info); if (err < 0) - goto failed; + goto err_reg_fb; printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); @@ -2027,11 +2146,14 @@ static int __devinit neofb_probe(struct pci_set_drvdata(dev, info); return 0; - failed: +err_reg_fb: + fb_dealloc_cmap(&info->cmap); +err_map_video: neo_unmap_video(info); +err_init_hw: neo_unmap_mmio(info); +err_map_mmio: neo_free_fb_info(info); - return err; } @@ -2103,24 +2225,6 @@ static struct pci_driver neofb_driver = .remove = __devexit_p(neofb_remove) }; -/* **************************** init-time only **************************** */ - -static void __init neo_init(void) -{ - DBG("neo_init"); - pci_register_driver(&neofb_driver); -} - -/* **************************** exit-time only **************************** */ - -static void __exit neo_done(void) -{ - DBG("neo_done"); - pci_unregister_driver(&neofb_driver); -} - -#ifndef MODULE - /* ************************* init in-kernel code ************************** */ int __init neofb_setup(char *options) @@ -2136,8 +2240,6 @@ int __init neofb_setup(char *options) if (!*this_opt) continue; - if (!strncmp(this_opt, "disabled", 8)) - disabled = 1; if (!strncmp(this_opt, "internal", 8)) internal = 1; if (!strncmp(this_opt, "external", 8)) @@ -2153,41 +2255,18 @@ int __init neofb_setup(char *options) return 0; } -static int __initdata initialized = 0; - int __init neofb_init(void) { - DBG("neofb_init"); - - if (disabled) - return -ENXIO; - - if (!initialized) { - initialized = 1; - neo_init(); - } - - /* never return failure, user can hotplug card later... */ - return 0; + return pci_register_driver(&neofb_driver); } -#else - -/* *************************** init module code **************************** */ +#ifdef MODULE -int __init init_module(void) +static void __exit neofb_exit(void) { - DBG("init_module"); - - if (disabled) - return -ENXIO; - - neo_init(); - - /* never return failure; user can hotplug card later... */ - return 0; + pci_unregister_driver(&neofb_driver); } +module_init(neofb_init); +module_exit(neofb_exit); #endif /* MODULE */ - -module_exit(neo_done); diff -puN include/video/neomagic.h~neomagic-driver-update include/video/neomagic.h --- 25/include/video/neomagic.h~neomagic-driver-update 2004-04-21 18:11:53.907078048 -0700 +++ 25-akpm/include/video/neomagic.h 2004-04-21 18:11:53.918076376 -0700 @@ -55,6 +55,20 @@ #define NEO_MODE1_X_1600 0x1c00 #define NEO_MODE1_BLT_ON_ADDR 0x2000 +/* These are offseted in MMIO space by par->CursorOff */ +#define NEOREG_CURSCNTL 0x00 +#define NEOREG_CURSX 0x04 +#define NEOREG_CURSY 0x08 +#define NEOREG_CURSBGCOLOR 0x0C +#define NEOREG_CURSFGCOLOR 0x10 +#define NEOREG_CURSMEMPOS 0x14 + +#define NEO_CURS_DISABLE 0x00000000 +#define NEO_CURS_ENABLE 0x00000001 +#define NEO_ICON64_ENABLE 0x00000008 +#define NEO_ICON128_ENABLE 0x0000000C +#define NEO_ICON_BLANK 0x00000010 + #ifdef __KERNEL__ #ifdef NEOFB_DEBUG @@ -75,191 +89,116 @@ struct xtimings { - unsigned int pixclock; - unsigned int HDisplay; - unsigned int HSyncStart; - unsigned int HSyncEnd; - unsigned int HTotal; - unsigned int VDisplay; - unsigned int VSyncStart; - unsigned int VSyncEnd; - unsigned int VTotal; - unsigned int sync; - int dblscan; - int interlaced; + unsigned int pixclock; + unsigned int HDisplay; + unsigned int HSyncStart; + unsigned int HSyncEnd; + unsigned int HTotal; + unsigned int VDisplay; + unsigned int VSyncStart; + unsigned int VSyncEnd; + unsigned int VTotal; + unsigned int sync; + int dblscan; + int interlaced; }; /* --------------------------------------------------------------------- */ typedef volatile struct { - __u32 bltStat; - __u32 bltCntl; - __u32 xpColor; - __u32 fgColor; - __u32 bgColor; - __u32 pitch; - __u32 clipLT; - __u32 clipRB; - __u32 srcBitOffset; - __u32 srcStart; - __u32 reserved0; - __u32 dstStart; - __u32 xyExt; - - __u32 reserved1[19]; - - __u32 pageCntl; - __u32 pageBase; - __u32 postBase; - __u32 postPtr; - __u32 dataPtr; + __u32 bltStat; + __u32 bltCntl; + __u32 xpColor; + __u32 fgColor; + __u32 bgColor; + __u32 pitch; + __u32 clipLT; + __u32 clipRB; + __u32 srcBitOffset; + __u32 srcStart; + __u32 reserved0; + __u32 dstStart; + __u32 xyExt; + + __u32 reserved1[19]; + + __u32 pageCntl; + __u32 pageBase; + __u32 postBase; + __u32 postPtr; + __u32 dataPtr; } Neo2200; -#define NR_PALETTE 256 - #define MMIO_SIZE 0x200000 #define NEO_EXT_CR_MAX 0x85 #define NEO_EXT_GR_MAX 0xC7 struct neofb_par { - - unsigned char MiscOutReg; /* Misc */ - unsigned char CRTC[25]; /* Crtc Controller */ - unsigned char Sequencer[5]; /* Video Sequencer */ - unsigned char Graphics[9]; /* Video Graphics */ - unsigned char Attribute[21]; /* Video Atribute */ - - unsigned char GeneralLockReg; - unsigned char ExtCRTDispAddr; - unsigned char ExtCRTOffset; - unsigned char SysIfaceCntl1; - unsigned char SysIfaceCntl2; - unsigned char ExtColorModeSelect; - unsigned char biosMode; - - unsigned char PanelDispCntlReg1; - unsigned char PanelDispCntlReg2; - unsigned char PanelDispCntlReg3; - unsigned char PanelVertCenterReg1; - unsigned char PanelVertCenterReg2; - unsigned char PanelVertCenterReg3; - unsigned char PanelVertCenterReg4; - unsigned char PanelVertCenterReg5; - unsigned char PanelHorizCenterReg1; - unsigned char PanelHorizCenterReg2; - unsigned char PanelHorizCenterReg3; - unsigned char PanelHorizCenterReg4; - unsigned char PanelHorizCenterReg5; - - int ProgramVCLK; - unsigned char VCLK3NumeratorLow; - unsigned char VCLK3NumeratorHigh; - unsigned char VCLK3Denominator; - unsigned char VerticalExt; + struct vgastate state; + atomic_t ref_count; + + unsigned char MiscOutReg; /* Misc */ + unsigned char CRTC[25]; /* Crtc Controller */ + unsigned char Sequencer[5]; /* Video Sequencer */ + unsigned char Graphics[9]; /* Video Graphics */ + unsigned char Attribute[21]; /* Video Atribute */ + + unsigned char GeneralLockReg; + unsigned char ExtCRTDispAddr; + unsigned char ExtCRTOffset; + unsigned char SysIfaceCntl1; + unsigned char SysIfaceCntl2; + unsigned char ExtColorModeSelect; + unsigned char biosMode; + + unsigned char PanelDispCntlReg1; + unsigned char PanelDispCntlReg2; + unsigned char PanelDispCntlReg3; + unsigned char PanelVertCenterReg1; + unsigned char PanelVertCenterReg2; + unsigned char PanelVertCenterReg3; + unsigned char PanelVertCenterReg4; + unsigned char PanelVertCenterReg5; + unsigned char PanelHorizCenterReg1; + unsigned char PanelHorizCenterReg2; + unsigned char PanelHorizCenterReg3; + unsigned char PanelHorizCenterReg4; + unsigned char PanelHorizCenterReg5; + + int ProgramVCLK; + unsigned char VCLK3NumeratorLow; + unsigned char VCLK3NumeratorHigh; + unsigned char VCLK3Denominator; + unsigned char VerticalExt; #ifdef CONFIG_MTRR - int mtrr; + int mtrr; #endif - u8 *mmio_vbase; - - Neo2200 *neo2200; - - /* Panels size */ - int NeoPanelWidth; - int NeoPanelHeight; - - int maxClock; - - int pci_burst; - int lcd_stretch; - int internal_display; - int external_display; - int libretto; + u8 *mmio_vbase; + u8 cursorOff; + u8 *cursorPad; /* Must die !! */ + + Neo2200 *neo2200; + + /* Panels size */ + int NeoPanelWidth; + int NeoPanelHeight; + + int maxClock; + + int pci_burst; + int lcd_stretch; + int internal_display; + int external_display; + int libretto; }; typedef struct { - int x_res; - int y_res; - int mode; + int x_res; + int y_res; + int mode; } biosMode; -/* vga IO functions */ -static inline u8 VGArCR (u8 index) -{ - outb (index, 0x3d4); - return inb (0x3d5); -} - -static inline void VGAwCR (u8 index, u8 val) -{ - outb (index, 0x3d4); - outb (val, 0x3d5); -} - -static inline u8 VGArGR (u8 index) -{ - outb (index, 0x3ce); - return inb (0x3cf); -} - -static inline void VGAwGR (u8 index, u8 val) -{ - outb (index, 0x3ce); - outb (val, 0x3cf); -} - -static inline u8 VGArSEQ (u8 index) -{ - outb (index, 0x3c4); - return inb (0x3c5); -} - -static inline void VGAwSEQ (u8 index, u8 val) -{ - outb (index, 0x3c4); - outb (val, 0x3c5); -} - - -static int paletteEnabled = 0; - -static inline void VGAenablePalette (void) -{ - u8 tmp; - - tmp = inb (0x3da); - outb (0x00, 0x3c0); - paletteEnabled = 1; -} - -static inline void VGAdisablePalette (void) -{ - u8 tmp; - - tmp = inb (0x3da); - outb (0x20, 0x3c0); - paletteEnabled = 0; -} - -static inline void VGAwATTR (u8 index, u8 value) -{ - u8 tmp; - - if (paletteEnabled) - index &= ~0x20; - else - index |= 0x20; - - tmp = inb (0x3da); - outb (index, 0x3c0); - outb (value, 0x3c0); -} - -static inline void VGAwMISC (u8 value) -{ - outb (value, 0x3c2); -} #endif - _