*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
static int libretto;
static int nostretch;
static int nopciburst;
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
#ifdef MODULE
MODULE_AUTHOR("(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
-MODULE_PARM(internal, "i");
+module_param(internal, bool, 0);
MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");
-MODULE_PARM(external, "i");
+module_param(external, bool, 0);
MODULE_PARM_DESC(external, "Enable output on external CRT.");
-MODULE_PARM(libretto, "i");
+module_param(libretto, bool, 0);
MODULE_PARM_DESC(libretto, "Force Libretto 100/110 800x480 LCD.");
-MODULE_PARM(nostretch, "i");
+module_param(nostretch, bool, 0);
MODULE_PARM_DESC(nostretch,
"Disable stretching of modes smaller than LCD.");
-MODULE_PARM(nopciburst, "i");
+module_param(nopciburst, bool, 0);
MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
-MODULE_PARM(mode_option, "s");
+module_param(mode_option, charp, 0);
MODULE_PARM_DESC(mode_option, "Preferred video mode ('640x480-8@60', etc)");
#endif
};
#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);
switch (depth) {
case 8:
- size = sizeof(bios8) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios8);
mode = bios8;
break;
case 16:
- size = sizeof(bios16) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios16);
mode = bios16;
break;
case 24:
- size = sizeof(bios24) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios24);
mode = bios24;
break;
#ifdef NO_32BIT_SUPPORT_YET
case 32:
- size = sizeof(bios32) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios32);
mode = bios32;
break;
#endif
*/
static int paletteEnabled = 0;
-inline void VGAenablePalette(void)
+static inline void VGAenablePalette(void)
{
vga_r(NULL, VGA_IS1_RC);
vga_w(NULL, VGA_ATT_W, 0x00);
paletteEnabled = 1;
}
-inline void VGAdisablePalette(void)
+static 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)
+static inline void VGAwATTR(u8 index, u8 value)
{
if (paletteEnabled)
index &= ~0x20;
vga_wattr(NULL, index, value);
}
-void vgaHWProtect(int on)
+static void vgaHWProtect(int on)
{
unsigned char tmp;
*/
static inline int neo2200_sync(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
- int waitcycles;
+ struct neofb_par *par = info->par;
- while (par->neo2200->bltStat & 1)
- waitcycles++;
+ while (readl(&par->neo2200->bltStat) & 1);
return 0;
}
static inline void neo2200_accel_init(struct fb_info *info,
struct fb_var_screeninfo *var)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
- Neo2200 *neo2200 = par->neo2200;
+ struct neofb_par *par = info->par;
+ Neo2200 __iomem *neo2200 = par->neo2200;
u32 bltMod, pitch;
neo2200_sync(info);
return;
}
- neo2200->bltStat = bltMod << 16;
- neo2200->pitch = (pitch << 16) | pitch;
+ writel(bltMod << 16, &neo2200->bltStat);
+ writel((pitch << 16) | pitch, &neo2200->pitch);
}
/* --------------------------------------------------------------------- */
static int
neofb_open(struct fb_info *info, int user)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
if (!cnt) {
static int
neofb_release(struct fb_info *info, int user)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
if (!cnt)
static int
neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
unsigned int pixclock = var->pixclock;
struct xtimings timings;
int memlen, vramlen;
static int neofb_set_par(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
struct xtimings timings;
unsigned char temp;
int i, clock_hi = 0;
par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */
+ /* Initialize: by default, we want display config register to be read */
+ par->PanelDispCntlRegRead = 1;
+
/* Enable any user specified display devices. */
par->PanelDispCntlReg1 = 0x00;
if (par->internal_display)
/* If the user did not specify any display devices, then... */
if (par->PanelDispCntlReg1 == 0x00) {
/* Default to internal (i.e., LCD) only. */
- par->PanelDispCntlReg1 |= 0x02;
+ par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
}
/* If we are using a fixed mode, then tell the chip we are. */
static void neofb_update_start(struct fb_info *info,
struct fb_var_screeninfo *var)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
struct vgastate *state = &par->state;
int oldExtCRTDispAddr;
int Base;
/*
* (Un)Blank the display.
*/
-int neofb_blank(int blank_mode, struct fb_info *info)
+static int neofb_blank(int blank_mode, struct fb_info *info)
{
/*
* Blank the screen if blank_mode != 0, else unblank.
* wms...Enable VESA DPMS compatible powerdown mode
* run "setterm -powersave powerdown" to take advantage
*/
- struct neofb_par *par = (struct neofb_par *)info->par;
- int seqflags, lcdflags, dpmsflags, reg;
+ 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 4: /* powerdown - both sync lines down */
+ 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 |
}
#endif
break;
- case 3: /* hsync off */
+ 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 2: /* vsync off */
+ 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 1: /* just blank screen (backlight stays on) */
+ case FB_BLANK_NORMAL: /* just blank screen (backlight stays on) */
seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
- lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
- dpmsflags = 0; /* no hsync/vsync suppression */
+ /*
+ * 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 0: /* unblank */
+ case FB_BLANK_UNBLANK: /* unblank */
seqflags = 0; /* Enable sequencer */
- lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
+ lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
dpmsflags = 0x00; /* no hsync/vsync suppression */
#ifdef CONFIG_TOSHIBA
/* Do we still need this ? */
static void
neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
u_long dst, rop;
dst = rect->dx + rect->dy * info->var.xres_virtual;
neo2200_wait_fifo(info, 4);
/* set blt control */
- par->neo2200->bltCntl = NEO_BC3_FIFO_EN |
- NEO_BC0_SRC_IS_FG | NEO_BC3_SKIP_MAPPING |
- // NEO_BC3_DST_XY_ADDR |
- // NEO_BC3_SRC_XY_ADDR |
- rop;
+ 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:
- par->neo2200->fgColor = rect->color;
+ writel(rect->color, &par->neo2200->fgColor);
break;
case 16:
case 24:
- par->neo2200->fgColor =
- ((u32 *) (info->pseudo_palette))[rect->color];
+ writel(((u32 *) (info->pseudo_palette))[rect->color],
+ &par->neo2200->fgColor);
break;
}
- par->neo2200->dstStart =
- dst * ((info->var.bits_per_pixel + 7) >> 3);
- par->neo2200->xyExt =
- (rect->height << 16) | (rect->width & 0xffff);
+ writel(dst * ((info->var.bits_per_pixel + 7) >> 3),
+ &par->neo2200->dstStart);
+ writel((rect->height << 16) | (rect->width & 0xffff),
+ &par->neo2200->xyExt);
}
static void
neo2200_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 = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
u_long src, dst, bltCntl;
bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
neo2200_wait_fifo(info, 4);
/* set blt control */
- par->neo2200->bltCntl = bltCntl;
+ writel(bltCntl, &par->neo2200->bltCntl);
- par->neo2200->srcStart = src;
- par->neo2200->dstStart = dst;
- par->neo2200->xyExt =
- (area->height << 16) | (area->width & 0xffff);
+ writel(src, &par->neo2200->srcStart);
+ writel(dst, &par->neo2200->dstStart);
+ writel((area->height << 16) | (area->width & 0xffff),
+ &par->neo2200->xyExt);
}
static void
neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ 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;
switch (info->var.bits_per_pixel) {
case 8:
- par->neo2200->fgColor = image->fg_color;
- par->neo2200->bgColor = image->bg_color;
+ writel(image->fg_color, &par->neo2200->fgColor);
+ writel(image->bg_color, &par->neo2200->bgColor);
break;
case 16:
case 24:
- par->neo2200->fgColor =
- ((u32 *) (info->pseudo_palette))[image->fg_color];
- par->neo2200->bgColor =
- ((u32 *) (info->pseudo_palette))[image->bg_color];
+ writel(((u32 *) (info->pseudo_palette))[image->fg_color],
+ &par->neo2200->fgColor);
+ writel(((u32 *) (info->pseudo_palette))[image->bg_color],
+ &par->neo2200->bgColor);
break;
}
- par->neo2200->bltCntl = NEO_BC0_SYS_TO_VID |
+ writel(NEO_BC0_SYS_TO_VID |
NEO_BC3_SKIP_MAPPING | bltCntl_flags |
// NEO_BC3_DST_XY_ADDR |
- 0x0c0000;
+ 0x0c0000, &par->neo2200->bltCntl);
- par->neo2200->srcStart = 0;
+ writel(0, &par->neo2200->srcStart);
// par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);
- par->neo2200->dstStart =
- ((image->dx & 0xffff) * (info->var.bits_per_pixel >> 3) +
- image->dy * info->fix.line_length);
- par->neo2200->xyExt =
- (image->height << 16) | (image->width & 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(par->mmio_vbase + 0x100000, image->data, data_len);
+ memcpy_toio(par->mmio_vbase + 0x100000, image->data, data_len);
}
static void
.fb_fillrect = neofb_fillrect,
.fb_copyarea = neofb_copyarea,
.fb_imageblit = neofb_imageblit,
- .fb_cursor = soft_cursor,
};
/* --------------------------------------------------------------------- */
static int __devinit neo_map_mmio(struct fb_info *info,
struct pci_dev *dev)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
DBG("neo_map_mmio");
- info->fix.mmio_start = pci_resource_start(dev, 1);
+ 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
static void neo_unmap_mmio(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
DBG("neo_unmap_mmio");
#endif
/* Clear framebuffer, it's all white in memory after boot */
- memset(info->screen_base, 0, info->fix.smem_len);
+ memset_io(info->screen_base, 0, info->fix.smem_len);
/* Allocate Cursor drawing pad.
info->fix.smem_len -= PAGE_SIZE;
#ifdef CONFIG_MTRR
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
mtrr_del(par->mtrr, info->fix.smem_start,
info->fix.smem_len);
static int __devinit neo_scan_monitor(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
unsigned char type, display;
int w;
static int __devinit neo_init_hw(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int videoRam = 896;
int maxClock = 65000;
int CursorMem = 1024;
printk(KERN_DEBUG "--- Neo extended register dump ---\n");
for (int w = 0; w < 0x85; w++)
printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
- (void *) vga_rcrt(NULL, w);
+ (void *) vga_rcrt(NULL, w));
for (int w = 0; w < 0xC7; w++)
printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
(void *) vga_rgfx(NULL, w));
maxWidth = 1280;
maxHeight = 1024; /* ???? */
- par->neo2200 = (Neo2200 *) par->mmio_vbase;
+ par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
case FB_ACCEL_NEOMAGIC_NM2230:
videoRam = 3008;
maxWidth = 1280;
maxHeight = 1024; /* ???? */
- par->neo2200 = (Neo2200 *) par->mmio_vbase;
+ par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
case FB_ACCEL_NEOMAGIC_NM2360:
videoRam = 4096;
maxWidth = 1280;
maxHeight = 1024; /* ???? */
- par->neo2200 = (Neo2200 *) par->mmio_vbase;
+ par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
case FB_ACCEL_NEOMAGIC_NM2380:
videoRam = 6144;
maxWidth = 1280;
maxHeight = 1024; /* ???? */
- par->neo2200 = (Neo2200 *) par->mmio_vbase;
+ par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
}
/*
struct fb_info *info;
struct neofb_par *par;
- info = framebuffer_alloc(sizeof(struct neofb_par) + sizeof(u32) * 256, &dev->dev);
+ info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
if (!info)
return NULL;
par->internal_display = internal;
par->external_display = external;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
switch (info->fix.accel) {
case FB_ACCEL_NEOMAGIC_NM2070:
break;
case FB_ACCEL_NEOMAGIC_NM2200:
sprintf(info->fix.id, "MagicGraph 256AV");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2230:
sprintf(info->fix.id, "MagicGraph 256AV+");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2360:
sprintf(info->fix.id, "MagicGraph 256ZX");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2380:
sprintf(info->fix.id, "MagicGraph 256XL+");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
}
info->fix.accel = id->driver_data;
info->fbops = &neofb_ops;
- info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_COPYAREA |
- FBINFO_HWACCEL_COPYAREA;
- info->pseudo_palette = (void *) (par + 1);
+ info->pseudo_palette = par->palette;
return info;
}
/* ************************* init in-kernel code ************************** */
-int __init neofb_setup(char *options)
+#ifndef MODULE
+static int __init neofb_setup(char *options)
{
char *this_opt;
}
return 0;
}
+#endif /* MODULE */
-int __init neofb_init(void)
+static int __init neofb_init(void)
{
#ifndef MODULE
char *option = NULL;