Commit c14b0803 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] fbdev: Neomagic driver update.

From: James Simmons <jsimmons@infradead.org>

Here is a updated driver for the neomagic.
parent 68f11205
......@@ -22,7 +22,7 @@ obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgb
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
......
......@@ -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_screeninfo *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_info *info,
{
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();
......@@ -534,6 +556,36 @@ static inline void neo2200_accel_init(struct fb_info *info,
/* --------------------------------------------------------------------- */
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)
{
......@@ -672,15 +724,12 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
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->yres_virtual = vramlen * 8 / (var->xres_virtual *
var->bits_per_pixel);
memlen =
var->xres_virtual * var->bits_per_pixel *
memlen = var->xres_virtual * var->bits_per_pixel *
var->yres_virtual / 8;
}
......@@ -981,13 +1030,13 @@ static int neofb_set_par(struct fb_info *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 *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 *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 *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 *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 *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 *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_info *info,
/*
* 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_var_screeninfo *var,
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, const struct fb_fillrect *rect)
}
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, const struct fb_fillrect *rect)
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, const struct fb_copyarea *area)
(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, const struct fb_image *image)
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)
......@@ -1467,6 +1514,8 @@ neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
static void
neofb_imageblit(struct fb_info *info, const struct fb_image *image)
{
/*
if (image->depth == 1) {
switch (info->fix.accel) {
case FB_ACCEL_NEOMAGIC_NM2200:
case FB_ACCEL_NEOMAGIC_NM2230:
......@@ -1478,6 +1527,9 @@ neofb_imageblit(struct fb_info *info, const struct fb_image *image)
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 fb_info *info,
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;
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;
}
......@@ -1679,27 +1790,30 @@ static int __devinit neo_map_video(struct fb_info *info,
/* 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
iounmap(info->screen_base);
info->screen_base = NULL;
release_mem_region(info->fix.smem_start,
info->fix.smem_len);
}
}
static int __devinit neo_init_hw(struct fb_info *info)
......@@ -1723,16 +1837,16 @@ static int __devinit neo_init_hw(struct fb_info *info)
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 +1856,8 @@ static int __devinit neo_init_hw(struct fb_info *info)
}
/* 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 +1982,16 @@ static int __devinit neo_init_hw(struct fb_info *info)
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 +2001,12 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
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 +2056,18 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
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 +2090,24 @@ static int __devinit neofb_probe(struct pci_dev *dev,
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 +2128,12 @@ static int __devinit neofb_probe(struct pci_dev *dev,
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 +2144,14 @@ static int __devinit neofb_probe(struct pci_dev *dev,
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 +2223,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 +2238,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 +2253,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);
......@@ -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
......@@ -116,14 +130,14 @@ typedef volatile struct {
__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 {
struct vgastate state;
atomic_t ref_count;
unsigned char MiscOutReg; /* Misc */
unsigned char CRTC[25]; /* Crtc Controller */
......@@ -163,6 +177,8 @@ struct neofb_par {
int mtrr;
#endif
u8 *mmio_vbase;
u8 cursorOff;
u8 *cursorPad; /* Must die !! */
Neo2200 *neo2200;
......@@ -185,81 +201,4 @@ typedef struct {
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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment