summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJames Simmons <jsimmons@maxwell.earthlink.net>2002-12-31 01:59:18 -0800
committerJames Simmons <jsimmons@maxwell.earthlink.net>2002-12-31 01:59:18 -0800
commit0d80a81821bd4f7eb554135dec3f400519525af8 (patch)
tree75f6a0b833400fe039db0e3d85fba360eedfb0e7 /drivers
parent572f2a49e4297c946a77721b72db960984b78a6d (diff)
parent9f880dd8ed32ee57c3489409e321675fde1544cf (diff)
Synced to Linus tree,
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/vt.c2
-rw-r--r--drivers/video/Kconfig68
-rw-r--r--drivers/video/Makefile17
-rw-r--r--drivers/video/aty/atyfb_base.c33
-rw-r--r--drivers/video/aty128fb.c100
-rw-r--r--drivers/video/cfbcopyarea.c5
-rw-r--r--drivers/video/cfbfillrect.c5
-rw-r--r--drivers/video/cfbimgblt.c106
-rw-r--r--drivers/video/chipsfb.c574
-rw-r--r--drivers/video/console/Kconfig36
-rw-r--r--drivers/video/console/Makefile38
-rw-r--r--drivers/video/console/dummycon.c6
-rw-r--r--drivers/video/console/fbcon-sti.c289
-rw-r--r--drivers/video/console/fbcon.c304
-rw-r--r--drivers/video/console/fbcon.h17
-rw-r--r--drivers/video/console/font.h45
-rw-r--r--drivers/video/console/font_6x11.c2
-rw-r--r--drivers/video/console/font_8x16.c2
-rw-r--r--drivers/video/console/font_8x8.c2
-rw-r--r--drivers/video/console/font_acorn_8x8.c3
-rw-r--r--drivers/video/console/font_mini_4x6.c2
-rw-r--r--drivers/video/console/font_pearl_8x8.c2
-rw-r--r--drivers/video/console/font_sun12x22.c2
-rw-r--r--drivers/video/console/font_sun8x16.c2
-rw-r--r--drivers/video/console/mdacon.c24
-rw-r--r--drivers/video/console/newport_con.c2
-rw-r--r--drivers/video/console/sti.h289
-rw-r--r--drivers/video/console/sticon.c390
-rw-r--r--drivers/video/console/sticore.c1130
-rw-r--r--drivers/video/controlfb.c37
-rw-r--r--drivers/video/fbmem.c364
-rw-r--r--drivers/video/fbmon.c334
-rw-r--r--drivers/video/i810/Makefile22
-rw-r--r--drivers/video/i810/i810.h300
-rw-r--r--drivers/video/i810/i810_accel.c513
-rw-r--r--drivers/video/i810/i810_dvt.c308
-rw-r--r--drivers/video/i810/i810_gtf.c275
-rw-r--r--drivers/video/i810/i810_main.c2245
-rw-r--r--drivers/video/i810/i810_main.h205
-rw-r--r--drivers/video/i810/i810_regs.h274
-rw-r--r--drivers/video/igafb.c100
-rw-r--r--drivers/video/offb.c5
-rw-r--r--drivers/video/pmagb-b-fb.h2
-rw-r--r--drivers/video/radeonfb.c38
-rw-r--r--drivers/video/riva/fbdev.c308
-rw-r--r--drivers/video/riva/nv_type.h58
-rw-r--r--drivers/video/riva/riva_hw.c128
-rw-r--r--drivers/video/riva/riva_hw.h110
-rw-r--r--drivers/video/riva/riva_tbl.h99
-rw-r--r--drivers/video/riva/rivafb.h7
-rw-r--r--drivers/video/skeletonfb.c220
-rw-r--r--drivers/video/sstfb.c1970
-rw-r--r--drivers/video/sstfb.h68
-rw-r--r--drivers/video/sticore.h5
-rw-r--r--drivers/video/stifb.c136
-rw-r--r--drivers/video/tdfxfb.c11
-rw-r--r--drivers/video/vga16fb.c70
-rw-r--r--drivers/video/vgastate.c7
58 files changed, 7915 insertions, 3801 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 0920a11c3683..828df90fb64b 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -130,7 +130,7 @@ extern void console_map_init(void);
extern void prom_con_init(void);
#endif
#ifdef CONFIG_MDA_CONSOLE
-extern void mda_console_init(void);
+extern int mda_console_init(void);
#endif
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
extern int fb_console_init(void);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e0f0af3145ba..254ad4f26c0d 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -295,27 +295,21 @@ config FB_VGA16
vga16fb.o.
config FB_STI
- bool "Generic STI frame buffer device support"
+ bool "HP STI frame buffer device support"
depends on FB && PARISC
+ default y
---help---
STI refers to the HP "Standard Text Interface" which is a set of
BIOS routines contained in a ROM chip in HP PA-RISC based machines.
- Enabling this option will implement the linux framebuffer device and
- an fbcon color text console using calls to the STI BIOS routines.
- The HP framebuffer device is usually planar, uses a strange memory
- layout, and changing the plane mask to create colored pixels
- requires a call to the STI routines, so do not expect /dev/fb to
- actually be useful. However, it is the best we have as far as
- graphics on the HP chipsets due to lack of hardware level
- documentation for the various on-board HP chipsets used in these
- systems. It is sufficient for basic text console functions,
- including fonts.
-
- You should probably enable this option, unless you are having
- trouble getting video when booting the kernel (make sure it isn't
- just that you are running the console on the serial port, though).
- Really old HP boxes may not have STI, and must use the PDC BIOS
- console or the IODC BIOS.
+ Enabling this option will implement the linux framebuffer device
+ using calls to the STI BIOS routines for initialisation.
+
+ If you enable this option, you will get a planar framebuffer device
+ /dev/fb which will work on the most common HP graphic cards of the
+ NGLE family, including the artist chips (in the 7xx and Bxxx series),
+ HCRX, HCRX24, CRX, CRX24 and VisEG series.
+
+ It is safe to enable this option, so you should probably say "Y".
config FB_MAC
bool "Generic Macintosh display support"
@@ -471,6 +465,44 @@ config FB_RIVA
module will be called rivafb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
+config FB_I810
+ tristate "Intel 810/815 support (EXPERIMENTAL)"
+ depends on FB && AGP && AGP_INTEL && EXPERIMENTAL && PCI
+ help
+ This driver supports the on-board graphics built in to the Intel 810
+ and 815 chipsets. Say Y if you have and plan to use such a board.
+
+ The driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want).
+ The module will be called i810fb.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
+ For more information, please read
+ <file:Documentation/fb/intel810.txt>
+
+config FB_I810_GTF
+ bool "use VESA Generalized Timing Formula"
+ depends on FB_I810
+ help
+ If you say Y, then the VESA standard, Generalized Timing Formula
+ or GTF, will be used to calculate the required video timing values
+ per video mode. Since the GTF allows nondiscrete timings
+ (nondiscrete being a range of values as opposed to discrete being a
+ set of values), you'll be able to use any combination of horizontal
+ and vertical resolutions, and vertical refresh rates without having
+ to specify your own timing parameters. This is especially useful
+ to maximize the performance of an aging display, or if you just
+ have a display with nonstandard dimensions. A VESA compliant
+ monitor is recommended, but can still work with non-compliant ones.
+ If you need or want this, then select this option. The timings may
+ not be compliant with Intel's recommended values. Use at your own
+ risk.
+
+ If you say N, the driver will revert to discrete video timings
+ using a set recommended by Intel in their documentation.
+
+ If unsure, say N.
+
config FB_MATROX
tristate "Matrox acceleration"
depends on FB && PCI
@@ -759,7 +791,7 @@ config FB_TRIDENT
The driver is also available as a module ( = code which can be
inserted and removed from the running kernel whenever you want). The
- module will be called rivafb.o. If you want to compile it as a
+ module will be called tridentfb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config FB_PM3
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 7faee8111c81..c147b6de431e 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -12,8 +12,7 @@ export-objs := fbmem.o fbcmap.o fbmon.o modedb.o softcursor.o cfbfillrect.o
obj-$(CONFIG_VT) += console/
-# Add fbmon.o back into obj-$(CONFIG_FB) in 2.5.x
-obj-$(CONFIG_FB) += fbmem.o fbcmap.o modedb.o softcursor.o
+obj-$(CONFIG_FB) += fbmem.o fbmon.o fbcmap.o modedb.o softcursor.o
# Only include macmodes.o if we have FB support and are PPC
ifeq ($(CONFIG_FB),y)
obj-$(CONFIG_PPC) += macmodes.o
@@ -27,13 +26,13 @@ obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o
obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_ATARI) += atafb.o
obj-$(CONFIG_FB_ATY128) += aty128fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_RADEON) += radeonfb.o
+obj-$(CONFIG_FB_RADEON) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblit.o
+obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CONTROL) += controlfb.o
obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
-obj-$(CONFIG_FB_CT65550) += chipsfb.o
+obj-$(CONFIG_FB_CT65550) += chipsfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_ANAKIN) += anakinfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CYBER) += cyberfb.o
@@ -42,7 +41,7 @@ obj-$(CONFIG_FB_SGIVW) += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbim
obj-$(CONFIG_FB_3DFX) += tdfxfb.o
obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_HP300) += hpfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_OF) += offb.o cfbfillrect.o cfbimgblit.o cfbcopyarea.o
+obj-$(CONFIG_FB_OF) += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o
obj-$(CONFIG_FB_CLGEN) += clgenfb.o
@@ -63,7 +62,7 @@ obj-$(CONFIG_FB_TCX) += tcxfb.o sbusfb.o
obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o
obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o
obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o
-obj-$(CONFIG_FB_STI) += stifb.o console/sticore.o
+obj-$(CONFIG_FB_STI) += stifb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
@@ -74,6 +73,8 @@ obj-$(CONFIG_FB_RIVA) += riva/ cfbfillrect.o cfbcopyarea.o \
cfbimgblt.o vgastate.o
obj-$(CONFIG_FB_SIS) += sis/
obj-$(CONFIG_FB_ATY) += aty/ cfbimgblt.o
+obj-$(CONFIG_FB_I810) += i810/ cfbfillrect.o cfbcopyarea.o \
+ cfbimgblt.o vgastate.o
obj-$(CONFIG_FB_SUN3) += sun3fb.o
obj-$(CONFIG_FB_HGA) += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
@@ -82,7 +83,7 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt
obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_E1355) += epson1355fb.o
obj-$(CONFIG_FB_PVR2) += pvr2fb.o
-obj-$(CONFIG_FB_VOODOO1) += sstfb.o
+obj-$(CONFIG_FB_VOODOO1) += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
# Files generated that shall be removed upon make clean
clean-files := promcon_tbl.c
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 2f2154c677b2..cc51b69b25d2 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -70,7 +70,7 @@
#ifdef __powerpc__
#include <asm/prom.h>
-#include <video/macmodes.h>
+#include "../macmodes.h"
#endif
#ifdef __sparc__
#include <asm/pbm.h>
@@ -84,9 +84,6 @@
#ifdef CONFIG_BOOTX_TEXT
#include <asm/btext.h>
#endif
-#ifdef CONFIG_NVRAM
-#include <linux/nvram.h>
-#endif
#ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h>
#endif
@@ -226,14 +223,9 @@ static char *mode_option __initdata = NULL;
#endif
#ifdef CONFIG_PPC
-#ifdef CONFIG_NVRAM_NOT_DEFINED
-static int default_vmode __initdata = VMODE_NVRAM;
-static int default_cmode __initdata = CMODE_NVRAM;
-#else
static int default_vmode __initdata = VMODE_CHOOSE;
static int default_cmode __initdata = CMODE_CHOOSE;
#endif
-#endif
#ifdef CONFIG_ATARI
static unsigned int mach64_count __initdata = 0;
@@ -984,6 +976,7 @@ static int atyfb_release(struct fb_info *info, int user)
var.yres_virtual =
var.yres;
}
+ fb_set_var(&var, -1, info);
}
}
}
@@ -1246,8 +1239,8 @@ static void atyfb_save_palette(struct atyfb_par *par, int enter)
static void atyfb_palette(int enter)
{
- struct fb_info *info;
struct atyfb_par *par;
+ struct fb_info *info;
int i;
for (i = 0; i < FB_MAX; i++) {
@@ -1409,16 +1402,16 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
{
struct fb_info *info;
- struct atyfb_par *par = (struct atyfb_par *) info->fb.par;
+ struct atyfb_par *par;
int result;
result = PBOOK_SLEEP_OK;
for (info = first_display; info != NULL; info = par->next) {
- struct fb_fix_screeninfo fix;
int nb;
- nb = fb_display[fg_console].var.yres * info->fix.line_length;
+ par = (struct atyfb_par *) info->fb.par;
+ nb = info->var.yres * info->fix.line_length;
switch (when) {
case PBOOK_SLEEP_REQUEST:
@@ -1436,7 +1429,7 @@ static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
if (par->blitter_may_be_busy)
wait_for_idle(par);
/* Stop accel engine (stop bus mastering) */
- if (par->accel_flags & FB_ACCELF_TEXT)
+ if (info->accel_flags & FB_ACCELF_TEXT)
aty_reset_engine(par);
/* Backup fb content */
@@ -1841,14 +1834,6 @@ static int __init aty_init(struct fb_info *info, const char *name)
(&var, info, mode_option, 8))
var = default_var;
} else {
-#ifdef CONFIG_NVRAM
- if (default_vmode == VMODE_NVRAM) {
- default_vmode = nvram_read_byte(NV_VMODE);
- if (default_vmode <= 0
- || default_vmode > VMODE_MAX)
- default_vmode = VMODE_CHOOSE;
- }
-#endif
if (default_vmode == VMODE_CHOOSE) {
if (M64_HAS(G3_PB_1024x768))
/* G3 PowerBook with 1024x768 LCD */
@@ -1870,10 +1855,6 @@ static int __init aty_init(struct fb_info *info, const char *name)
if (default_vmode <= 0
|| default_vmode > VMODE_MAX)
default_vmode = VMODE_640_480_60;
-#ifdef CONFIG_NVRAM
- if (default_cmode == CMODE_NVRAM)
- default_cmode = nvram_read_byte(NV_CMODE);
-#endif
if (default_cmode < CMODE_8
|| default_cmode > CMODE_32)
default_cmode = CMODE_8;
diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c
index 5545dbdb50ac..1179f00d6635 100644
--- a/drivers/video/aty128fb.c
+++ b/drivers/video/aty128fb.c
@@ -56,8 +56,6 @@
#include <asm/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
-#include <linux/selection.h>
-#include <linux/console.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <asm/io.h>
@@ -65,10 +63,7 @@
#ifdef CONFIG_ALL_PPC
#include <asm/prom.h>
#include <asm/pci-bridge.h>
-#include <video/macmodes.h>
-#ifdef CONFIG_NVRAM
-#include <linux/nvram.h>
-#endif
+#include "macmodes.h"
#endif
#ifdef CONFIG_ADB_PMU
@@ -285,7 +280,6 @@ struct aty128_constants {
struct aty128_crtc {
u32 gen_cntl;
- u32 ext_cntl;
u32 h_total, h_sync_strt_wid;
u32 v_total, v_sync_strt_wid;
u32 pitch;
@@ -326,10 +320,13 @@ struct aty128fb_par {
unsigned char *save_framebuffer;
int pm_reg;
int crt_on, lcd_on;
+ struct pci_dev *pdev;
+ struct fb_info *next;
#endif
- unsigned char red[64]; /* see comments in aty128fb_setcolreg */
- unsigned char green[64];
- unsigned char blue[64];
+ u8 red[32]; /* see aty128fb_setcolreg */
+ u8 green[64];
+ u8 blue[32];
+ u32 pseudo_palette[16]; /* used for TRUECOLOR */
};
#ifdef CONFIG_PMAC_PBOOK
@@ -337,6 +334,7 @@ int aty128_sleep_notify(struct pmu_sleep_notifier *self, int when);
static struct pmu_sleep_notifier aty128_sleep_notifier = {
aty128_sleep_notify, SLEEP_LEVEL_VIDEO,
};
+static struct fb_info *aty128_fb = NULL;
#endif
#define round_div(n, d) ((n+(d/2))/d)
@@ -1203,7 +1201,11 @@ aty128fb_set_par(struct fb_info *info)
{
struct aty128fb_par *par = info->par;
u32 config;
-
+ int err;
+
+ if ((err = aty128_decode_var(&info->var, par)) != 0)
+ return err;
+
if (par->blitter_may_be_busy)
wait_for_idle(par);
@@ -1271,15 +1273,22 @@ static int
aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par)
{
int err;
+ struct aty128_crtc crtc;
+ struct aty128_pll pll;
+ struct aty128_ddafifo fifo_reg;
- if ((err = aty128_var_to_crtc(var, &par->crtc, par)))
+ if ((err = aty128_var_to_crtc(var, &crtc, par)))
return err;
- if ((err = aty128_var_to_pll(var->pixclock, &par->pll, par)))
+ if ((err = aty128_var_to_pll(var->pixclock, &pll, par)))
return err;
- if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.depth, par)))
+ if ((err = aty128_ddafifo(&fifo_reg, &pll, crtc.depth, par)))
return err;
+
+ par->crtc = crtc;
+ par->pll = pll;
+ par->fifo_reg = fifo_reg;
par->accel_flags = var->accel_flags;
return 0;
@@ -1312,12 +1321,13 @@ aty128_encode_var(struct fb_var_screeninfo *var,
static int
aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct aty128fb_par *par = info->par;
+ struct aty128fb_par par;
int err;
- if ((err = aty128_decode_var(var, par)) != 0)
+ par = *(struct aty128fb_par *)info->par;
+ if ((err = aty128_decode_var(var, &par)) != 0)
return err;
- aty128_encode_var(var, par);
+ aty128_encode_var(var, &par);
return 0;
}
@@ -1602,7 +1612,12 @@ aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
#endif /* CONFIG_PMAC_BACKLIGHT */
#ifdef CONFIG_PMAC_PBOOK
par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
- pmu_register_sleep_notifier(&aty128_sleep_notifier);
+ if (aty128_fb == NULL) {
+ /* XXX can only put one chip to sleep */
+ aty128_fb = info;
+ } else
+ printk(KERN_WARNING "aty128fb: can only sleep one Rage 128\n");
+ par->pdev = pdev;
#endif
printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
@@ -1647,8 +1662,7 @@ aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* We have the resources. Now virtualize them */
- size = sizeof(struct fb_info) + sizeof(struct aty128fb_par) +
- sizeof(u32)*16;
+ size = sizeof(struct fb_info) + sizeof(struct aty128fb_par);
if (!(info = kmalloc(size, GFP_ATOMIC))) {
printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
goto err_unmap_out;
@@ -1656,9 +1670,7 @@ aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
memset(info, 0, size);
par = (struct aty128fb_par *)(info + 1);
- info->pseudo_palette = (void *) (par + 1);
-
- memset(info, 0, sizeof(struct fb_info));
+ info->pseudo_palette = par->pseudo_palette;
info->par = par;
info->fix = aty128fb_fix;
@@ -1758,6 +1770,10 @@ static void __devexit aty128_remove(struct pci_dev *pdev)
pci_resource_len(pdev, 1));
release_mem_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
+#ifdef CONFIG_PMAC_PBOOK
+ if (info == aty128_fb)
+ aty128_fb = NULL;
+#endif
kfree(info);
}
#endif /* CONFIG_PCI */
@@ -2008,7 +2024,7 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
}
}
- if (par->crtc.depth == 16) {
+ if (par->crtc.depth == 16 && regno > 0) {
/*
* With the 5-6-5 split of bits for RGB at 16 bits/pixel, we
* have 32 slots for R and B values but 64 slots for G values.
@@ -2016,12 +2032,13 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* goes in a different slot, and we have to avoid disturbing
* the other fields in the slots we touch.
*/
- par->red[regno] = red;
par->green[regno] = green;
- par->blue[regno] = blue;
- if (regno > 0 && regno < 32)
+ if (regno < 32) {
+ par->red[regno] = red;
+ par->blue[regno] = blue;
aty128_st_pal(regno * 8, red, par->green[regno*2],
blue, par);
+ }
red = par->red[regno/2];
blue = par->blue[regno/2];
regno <<= 2;
@@ -2213,6 +2230,7 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
{
u32 pmgt;
u16 pwr_command;
+ struct pci_dev *pdev = par->pdev;
if (!par->pm_reg)
return;
@@ -2237,17 +2255,16 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
aty_st_le32(BUS_CNTL1, 0x00000010);
aty_st_le32(MEM_POWER_MISC, 0x0c830000);
mdelay(100);
- pci_read_config_word(par->pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
+ pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
/* Switch PCI power management to D2 */
- pci_write_config_word(par->pdev, par->pm_reg+PCI_PM_CTRL,
+ pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL,
(pwr_command & ~PCI_PM_CTRL_STATE_MASK) | 2);
- pci_read_config_word(par->pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
+ pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
} else {
/* Switch back PCI power management to D0 */
mdelay(100);
- pci_write_config_word(par->pdev, par->pm_reg+PCI_PM_CTRL, 0);
- mdelay(100);
- pci_read_config_word(par->pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
+ pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, 0);
+ pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
mdelay(100);
}
}
@@ -2259,10 +2276,13 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
int
aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
{
- int result = PBOOK_SLEEP_OK, nb;
- struct fb_info *info = info; /* FIXME!!! How do find which framebuffer */
- struct aty128fb_par *par = info->par;
+ int nb;
+ struct fb_info *info = aty128_fb;
+ struct aty128fb_par *par;
+ if (info == NULL)
+ return PBOOK_SLEEP_OK;
+ par = info->par;
nb = info->var.yres * info->fix.line_length;
switch (when) {
@@ -2311,17 +2331,23 @@ aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
aty128fb_blank(0, info);
break;
}
- return result;
+ return PBOOK_SLEEP_OK;
}
#endif /* CONFIG_PMAC_PBOOK */
int __init aty128fb_init(void)
{
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_register_sleep_notifier(&aty128_sleep_notifier);
+#endif
return pci_module_init(&aty128fb_driver);
}
static void __exit aty128fb_exit(void)
{
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_unregister_sleep_notifier(&aty128_sleep_notifier);
+#endif
pci_unregister_driver(&aty128fb_driver);
}
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index f99a1692d5cb..a009d737eac2 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -400,11 +400,6 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
}
}
-#ifdef MODULE
-int init_module(void) { return 0; };
-void cleanup_module(void) {};
-#endif
-
EXPORT_SYMBOL(cfb_copyarea);
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
index fd272386e6c3..9d4a5735522e 100644
--- a/drivers/video/cfbfillrect.c
+++ b/drivers/video/cfbfillrect.c
@@ -443,11 +443,6 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
}
}
-#ifdef MODULE
-int init_module(void) { return 0; };
-void cleanup_module(void) {};
-#endif
-
EXPORT_SYMBOL(cfb_fillrect);
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
index f47b173b383e..5a343d0ae33f 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -21,13 +21,13 @@
*
* FIXME
* The code for 24 bit is horrible. It copies byte by byte size instead of
- * words like the other sizes. Needs to be optimized.
+ * longs like the other sizes. Needs to be optimized.
*
* Tony:
* Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds
* up the code significantly.
*
- * Code for depths not multiples of BITS_PER_WORD is still kludgy, which is
+ * Code for depths not multiples of BITS_PER_LONG is still kludgy, which is
* still processed a bit at a time.
*
* Also need to add code to deal with cards endians that are different than
@@ -48,11 +48,7 @@
#define DPRINTK(fmt, args...)
#endif
-/* The following code can *not* handle a 64-bit long. */
-#define WORD u32
-#define BITS_PER_WORD 32
-
-static WORD const cfb_tab8[] = {
+static u32 cfb_tab8[] = {
#if defined(__BIG_ENDIAN)
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
@@ -68,7 +64,7 @@ static WORD const cfb_tab8[] = {
#endif
};
-static WORD const cfb_tab16[] = {
+static u32 cfb_tab16[] = {
#if defined(__BIG_ENDIAN)
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
#elif defined(__LITTLE_ENDIAN)
@@ -78,11 +74,11 @@ static WORD const cfb_tab16[] = {
#endif
};
-static WORD const cfb_tab32[] = {
+static u32 cfb_tab32[] = {
0x00000000, 0xffffffff
};
-#if BITS_PER_WORD == 32
+#if BITS_PER_LONG == 32
#define FB_WRITEL fb_writel
#define FB_READL fb_readl
#else
@@ -91,7 +87,7 @@ static WORD const cfb_tab32[] = {
#endif
#if defined (__BIG_ENDIAN)
-#define LEFT_POS(bpp) (BITS_PER_WORD - bpp)
+#define LEFT_POS(bpp) (BITS_PER_LONG - bpp)
#define NEXT_POS(pos, bpp) ((pos) -= (bpp))
#define SHIFT_HIGH(val, bits) ((val) >> (bits))
#define SHIFT_LOW(val, bits) ((val) << (bits))
@@ -103,25 +99,24 @@ static WORD const cfb_tab32[] = {
#endif
static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1,
- WORD start_index, WORD pitch_index)
+ unsigned long start_index, unsigned long pitch_index)
{
/* Draw the penguin */
- int i, n;
- WORD bitmask = SHIFT_LOW(~0UL, BITS_PER_WORD - p->var.bits_per_pixel);
+ unsigned long *dst, *dst2, color = 0, val, shift;
+ int i, n, bpp = p->var.bits_per_pixel;
+ unsigned long null_bits = BITS_PER_LONG - bpp;
u32 *palette = (u32 *) p->pseudo_palette;
- WORD *dst, *dst2, color = 0, val, shift;
- WORD null_bits = BITS_PER_WORD - p->var.bits_per_pixel;
u8 *src = image->data;
- dst2 = (WORD *) dst1;
+ dst2 = (unsigned long *) dst1;
for (i = image->height; i--; ) {
n = image->width;
- dst = (WORD *) dst1;
+ dst = (unsigned long *) dst1;
shift = 0;
val = 0;
if (start_index) {
- WORD start_mask = ~(SHIFT_HIGH(~0UL, start_index));
+ unsigned long start_mask = ~(SHIFT_HIGH(~0UL, start_index));
val = FB_READL(dst) & start_mask;
shift = start_index;
@@ -129,23 +124,24 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8
while (n--) {
if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
p->fix.visual == FB_VISUAL_DIRECTCOLOR )
- color = palette[*src] & bitmask;
+ color = palette[*src];
else
- color = *src & bitmask;
+ color = *src;
+ color <<= LEFT_POS(bpp);
val |= SHIFT_HIGH(color, shift);
if (shift >= null_bits) {
FB_WRITEL(val, dst++);
if (shift == null_bits)
val = 0;
else
- val = SHIFT_LOW(color, BITS_PER_WORD - shift);
+ val = SHIFT_LOW(color, BITS_PER_LONG - shift);
}
- shift += p->var.bits_per_pixel;
- shift &= (BITS_PER_WORD - 1);
+ shift += bpp;
+ shift &= (BITS_PER_LONG - 1);
src++;
}
if (shift) {
- WORD end_mask = SHIFT_HIGH(~0UL, shift);
+ unsigned long end_mask = SHIFT_HIGH(~0UL, shift);
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
}
@@ -153,35 +149,35 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8
if (pitch_index) {
dst2 += p->fix.line_length;
dst1 = (char *) dst2;
- (size_t) dst1 &= ~(sizeof(WORD) - 1);
+ (unsigned long) dst1 &= ~(sizeof(unsigned long) - 1);
start_index += pitch_index;
- start_index &= BITS_PER_WORD - 1;
+ start_index &= BITS_PER_LONG - 1;
}
}
}
static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1,
- WORD fgcolor, WORD bgcolor,
- WORD start_index, WORD pitch_index)
+ unsigned long fgcolor, unsigned long bgcolor,
+ unsigned long start_index, unsigned long pitch_index)
{
- WORD i, j, l = 8;
- WORD shift, color, bpp = p->var.bits_per_pixel;
- WORD *dst, *dst2, val, pitch = p->fix.line_length;
- WORD null_bits = BITS_PER_WORD - bpp;
+ unsigned long i, j, l = 8;
+ unsigned long shift, color, bpp = p->var.bits_per_pixel;
+ unsigned long *dst, *dst2, val, pitch = p->fix.line_length;
+ unsigned long null_bits = BITS_PER_LONG - bpp;
u8 *src = image->data;
- dst2 = (WORD *) dst1;
+ dst2 = (unsigned long *) dst1;
for (i = image->height; i--; ) {
shift = 0;
val = 0;
j = image->width;
- dst = (WORD *) dst1;
+ dst = (unsigned long *) dst1;
/* write leading bits */
if (start_index) {
- WORD start_mask = ~(SHIFT_HIGH(~0UL, start_index));
+ unsigned long start_mask = ~(SHIFT_HIGH(~0UL, start_index));
val = FB_READL(dst) & start_mask;
shift = start_index;
@@ -192,6 +188,7 @@ static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8
color = fgcolor;
else
color = bgcolor;
+ color <<= LEFT_POS(bpp);
val |= SHIFT_HIGH(color, shift);
/* Did the bitshift spill bits to the next long? */
@@ -200,15 +197,15 @@ static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8
if (shift == null_bits)
val = 0;
else
- val = SHIFT_LOW(color, BITS_PER_WORD - shift);
+ val = SHIFT_LOW(color, BITS_PER_LONG - shift);
}
shift += bpp;
- shift &= (BITS_PER_WORD - 1);
+ shift &= (BITS_PER_LONG - 1);
if (!l) { l = 8; src++; };
}
/* write trailing bits */
if (shift) {
- WORD end_mask = SHIFT_HIGH(~0UL, shift);
+ unsigned long end_mask = SHIFT_HIGH(~0UL, shift);
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
}
@@ -217,24 +214,24 @@ static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8
if (pitch_index) {
dst2 += pitch;
dst1 = (char *) dst2;
- (size_t) dst1 &= ~(sizeof(WORD) - 1);
+ (unsigned long) dst1 &= ~(sizeof(unsigned long) - 1);
start_index += pitch_index;
- start_index &= BITS_PER_WORD - 1;
+ start_index &= BITS_PER_LONG - 1;
}
}
}
static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1,
- WORD fgcolor, WORD bgcolor)
+ unsigned long fgcolor, unsigned long bgcolor)
{
int i, j, k, l = 8, n;
- WORD bit_mask, end_mask, eorx;
- WORD fgx = fgcolor, bgx = bgcolor, pad, bpp = p->var.bits_per_pixel;
- WORD tmp = (1 << bpp) - 1;
- WORD ppw = BITS_PER_WORD/bpp, ppos;
- WORD *dst;
+ unsigned long bit_mask, end_mask, eorx;
+ unsigned long fgx = fgcolor, bgx = bgcolor, pad, bpp = p->var.bits_per_pixel;
+ unsigned long tmp = (1 << bpp) - 1;
+ unsigned long ppw = BITS_PER_LONG/bpp, ppos;
+ unsigned long *dst;
u32 *tab = NULL;
char *src = image->data;
@@ -267,7 +264,7 @@ static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8
k = image->width/ppw;
for (i = image->height; i--; ) {
- dst = (WORD *) dst1;
+ dst = (unsigned long *) dst1;
for (j = k; j--; ) {
l -= ppw;
@@ -295,8 +292,8 @@ static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8
void cfb_imageblit(struct fb_info *p, struct fb_image *image)
{
int x2, y2, vxres, vyres;
- WORD fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
- WORD bpl = sizeof(WORD), bpp = p->var.bits_per_pixel;
+ unsigned long fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
+ unsigned long bpl = sizeof(unsigned long), bpp = p->var.bits_per_pixel;
u8 *dst1;
vxres = p->var.xres_virtual;
@@ -319,7 +316,7 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image)
image->height = y2 - image->dy;
bitstart = (image->dy * p->fix.line_length * 8) + (image->dx * bpp);
- start_index = bitstart & (BITS_PER_WORD - 1);
+ start_index = bitstart & (BITS_PER_LONG - 1);
pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
bitstart /= 8;
@@ -336,7 +333,7 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image)
bgcolor = image->bg_color;
}
- if (BITS_PER_WORD % bpp == 0 && !start_index && !pitch_index &&
+ if (BITS_PER_LONG % bpp == 0 && !start_index && !pitch_index &&
bpp >= 8 && bpp <= 32 && (image->width & 7) == 0)
fast_imageblit(image, p, dst1, fgcolor, bgcolor);
else
@@ -346,11 +343,6 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image)
color_imageblit(image, p, dst1, start_index, pitch_index);
}
-#ifdef MODULE
-int init_module(void) { return 0; };
-void cleanup_module(void) {};
-#endif
-
EXPORT_SYMBOL(cfb_imageblit);
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index ee43294488f1..cd8bb196e904 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -2,7 +2,7 @@
* drivers/video/chipsfb.c -- frame buffer device for
* Chips & Technologies 65550 chip.
*
- * Copyright (C) 1998 Paul Mackerras
+ * Copyright (C) 1998-2002 Paul Mackerras
*
* This file is derived from the Powermac "chips" driver:
* Copyright (C) 1997 Fabio Riccardi.
@@ -26,7 +26,6 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
-#include <linux/selection.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
@@ -39,34 +38,11 @@
#include <linux/pmu.h>
#endif
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/macmodes.h>
-
-struct fb_info_chips {
- struct fb_info info;
- struct fb_fix_screeninfo fix;
- struct fb_var_screeninfo var;
- struct display disp;
- struct {
- __u8 red, green, blue;
- } palette[256];
- struct pci_dev *pdev;
- unsigned long frame_buffer_phys;
- __u8 *frame_buffer;
- unsigned long blitter_regs_phys;
- __u32 *blitter_regs;
- unsigned long blitter_data_phys;
- __u8 *blitter_data;
- struct fb_info_chips *next;
-#ifdef CONFIG_PMAC_PBOOK
- unsigned char *save_framebuffer;
-#endif
-#ifdef FBCON_HAS_CFB16
- u16 fbcon_cfb16_cmap[16];
-#endif
-};
+/*
+ * Since we access the display with inb/outb to fixed port numbers,
+ * we can only handle one 6555x chip. -- paulus
+ */
+static struct fb_info chipsfb_info;
#define write_ind(num, val, ap, dp) do { \
outb((num), (ap)); outb((val), (dp)); \
@@ -98,9 +74,8 @@ struct fb_info_chips {
inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
} while (0)
-static struct fb_info_chips *all_chips;
-
#ifdef CONFIG_PMAC_PBOOK
+static unsigned char *save_framebuffer;
int chips_sleep_notify(struct pmu_sleep_notifier *self, int when);
static struct pmu_sleep_notifier chips_sleep_notifier = {
chips_sleep_notify, SLEEP_LEVEL_VIDEO,
@@ -112,58 +87,29 @@ static struct pmu_sleep_notifier chips_sleep_notifier = {
*/
int chips_init(void);
-static void chips_pci_init(struct pci_dev *dp);
-static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info);
-static int chips_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
-static int chips_set_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
-static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info);
+static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
+static int chipsfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int chipsfb_set_par(struct fb_info *info);
static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int chipsfb_blank(int blank, struct fb_info *info);
static struct fb_ops chipsfb_ops = {
- .owner = THIS_MODULE,
- .fb_get_fix = chips_get_fix,
- .fb_get_var = chips_get_var,
- .fb_set_var = chips_set_var,
- .fb_get_cmap = chips_get_cmap,
- .fb_set_cmap = gen_set_cmap,
- .fb_setcolreg = chipsfb_setcolreg,
- .fb_blank = chipsfb_blank,
+ .owner = THIS_MODULE,
+ .fb_check_var = chipsfb_check_var,
+ .fb_set_par = chipsfb_set_par,
+ .fb_setcolreg = chipsfb_setcolreg,
+ .fb_blank = chipsfb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
};
-static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
- u_int *blue, u_int *transp, struct fb_info *info);
-static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp);
-
-static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info)
+static int chipsfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
- struct fb_info_chips *cp = (struct fb_info_chips *) info;
-
- *fix = cp->fix;
- return 0;
-}
-
-static int chips_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
- struct fb_info_chips *cp = (struct fb_info_chips *) info;
-
- *var = cp->var;
- return 0;
-}
-
-static int chips_set_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
- struct fb_info_chips *cp = (struct fb_info_chips *) info;
- struct display *disp = (con >= 0)? &fb_display[con]: &cp->disp;
-
if (var->xres > 800 || var->yres > 600
|| var->xres_virtual > 800 || var->yres_virtual > 600
|| (var->bits_per_pixel != 8 && var->bits_per_pixel != 16)
@@ -171,198 +117,76 @@ static int chips_set_var(struct fb_var_screeninfo *var, int con,
|| (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
- if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW &&
- var->bits_per_pixel != disp->var.bits_per_pixel) {
- chips_set_bitdepth(cp, disp, con, var->bits_per_pixel);
- }
+ var->xres = var->xres_virtual = 800;
+ var->yres = var->yres_virtual = 600;
return 0;
}
-static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
+static int chipsfb_set_par(struct fb_info *info)
{
- if (con == info->currcon) /* current console? */
- return fb_get_cmap(cmap, kspc, chipsfb_getcolreg, info);
- if (fb_display[con].cmap.len) /* non default colormap? */
- fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
- else {
- int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
- fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+ if (info->var.bits_per_pixel == 16) {
+ write_cr(0x13, 200); // Set line length (doublewords)
+ write_xr(0x81, 0x14); // 15 bit (555) color mode
+ write_xr(0x82, 0x00); // Disable palettes
+ write_xr(0x20, 0x10); // 16 bit blitter mode
+
+ info->fix.line_length = 800*2;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+ info->var.red.offset = 10;
+ info->var.green.offset = 5;
+ info->var.blue.offset = 0;
+ info->var.red.length = info->var.green.length =
+ info->var.blue.length = 5;
+
+ } else {
+ /* p->var.bits_per_pixel == 8 */
+ write_cr(0x13, 100); // Set line length (doublewords)
+ write_xr(0x81, 0x12); // 8 bit color mode
+ write_xr(0x82, 0x08); // Graphics gamma enable
+ write_xr(0x20, 0x00); // 8 bit blitter mode
+
+ info->fix.line_length = 800;
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+ info->var.red.offset = info->var.green.offset =
+ info->var.blue.offset = 0;
+ info->var.red.length = info->var.green.length =
+ info->var.blue.length = 8;
+
}
return 0;
}
-static int chipsfbcon_switch(int con, struct fb_info *info)
-{
- struct fb_info_chips *p = (struct fb_info_chips *) info;
- int new_bpp, old_bpp;
-
- /* Do we have to save the colormap? */
- if (fb_display[info->currcon].cmap.len)
- fb_get_cmap(&fb_display[info->currcon].cmap, 1, chipsfb_getcolreg, info);
-
- new_bpp = fb_display[con].var.bits_per_pixel;
- old_bpp = fb_display[info->currcon].var.bits_per_pixel;
- info->currcon = con;
-
- if (new_bpp != old_bpp)
- chips_set_bitdepth(p, &fb_display[con], con, new_bpp);
-
- do_install_cmap(con, info);
- return 0;
-}
-
-static int chipsfb_updatevar(int con, struct fb_info *info)
-{
- return 0;
-}
-
static int chipsfb_blank(int blank, struct fb_info *info)
{
- struct fb_info_chips *p = (struct fb_info_chips *) info;
- int i;
-
+#ifdef CONFIG_PMAC_BACKLIGHT
// used to disable backlight only for blank > 1, but it seems
// useful at blank = 1 too (saves battery, extends backlight life)
- if (blank) {
-#ifdef CONFIG_PMAC_BACKLIGHT
- set_backlight_enable(0);
-#endif /* CONFIG_PMAC_BACKLIGHT */
- /* get the palette from the chip */
- for (i = 0; i < 256; ++i) {
- outb(i, 0x3c7);
- udelay(1);
- p->palette[i].red = inb(0x3c9);
- p->palette[i].green = inb(0x3c9);
- p->palette[i].blue = inb(0x3c9);
- }
- for (i = 0; i < 256; ++i) {
- outb(i, 0x3c8);
- udelay(1);
- outb(0, 0x3c9);
- outb(0, 0x3c9);
- outb(0, 0x3c9);
- }
- } else {
-#ifdef CONFIG_PMAC_BACKLIGHT
- set_backlight_enable(1);
+ set_backlight_enable(!blank);
#endif /* CONFIG_PMAC_BACKLIGHT */
- for (i = 0; i < 256; ++i) {
- outb(i, 0x3c8);
- udelay(1);
- outb(p->palette[i].red, 0x3c9);
- outb(p->palette[i].green, 0x3c9);
- outb(p->palette[i].blue, 0x3c9);
- }
- }
- return 0;
-}
-
-static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
- u_int *blue, u_int *transp, struct fb_info *info)
-{
- struct fb_info_chips *p = (struct fb_info_chips *) info;
- if (regno > 255)
- return 1;
- *red = (p->palette[regno].red<<8) | p->palette[regno].red;
- *green = (p->palette[regno].green<<8) | p->palette[regno].green;
- *blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
- *transp = 0;
- return 0;
+ return 1; /* get fb_blank to set the colormap to all black */
}
static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
- struct fb_info_chips *p = (struct fb_info_chips *) info;
-
if (regno > 255)
return 1;
red >>= 8;
green >>= 8;
blue >>= 8;
- p->palette[regno].red = red;
- p->palette[regno].green = green;
- p->palette[regno].blue = blue;
outb(regno, 0x3c8);
udelay(1);
outb(red, 0x3c9);
outb(green, 0x3c9);
outb(blue, 0x3c9);
-#ifdef FBCON_HAS_CFB16
- if (regno < 16)
- p->fbcon_cfb16_cmap[regno] = ((red & 0xf8) << 7)
- | ((green & 0xf8) << 2) | ((blue & 0xf8) >> 3);
-#endif
-
return 0;
}
-static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp)
-{
- int err;
- struct fb_fix_screeninfo* fix = &p->fix;
- struct fb_var_screeninfo* var = &p->var;
-
- if (bpp == 16) {
- if (con == p->info.currcon) {
- write_cr(0x13, 200); // Set line length (doublewords)
- write_xr(0x81, 0x14); // 15 bit (555) color mode
- write_xr(0x82, 0x00); // Disable palettes
- write_xr(0x20, 0x10); // 16 bit blitter mode
- }
-
- fix->line_length = 800*2;
- fix->visual = FB_VISUAL_TRUECOLOR;
-
- var->red.offset = 10;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 5;
-
-#ifdef FBCON_HAS_CFB16
- disp->dispsw = &fbcon_cfb16;
- disp->dispsw_data = p->fbcon_cfb16_cmap;
-#else
- disp->dispsw = &fbcon_dummy;
-#endif
- } else if (bpp == 8) {
- if (con == p->info.currcon) {
- write_cr(0x13, 100); // Set line length (doublewords)
- write_xr(0x81, 0x12); // 8 bit color mode
- write_xr(0x82, 0x08); // Graphics gamma enable
- write_xr(0x20, 0x00); // 8 bit blitter mode
- }
-
- fix->line_length = 800;
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
-
- var->red.offset = var->green.offset = var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 8;
-
-#ifdef FBCON_HAS_CFB8
- disp->dispsw = &fbcon_cfb8;
-#else
- disp->dispsw = &fbcon_dummy;
-#endif
- }
-
- var->bits_per_pixel = bpp;
- disp->line_length = p->fix.line_length;
- disp->visual = fix->visual;
- disp->var = *var;
-
- if (p->info.changevar)
- (*p->info.changevar)(con);
-
- if ((err = fb_alloc_cmap(&disp->cmap, 0, 0)))
- return;
- do_install_cmap(con, (struct fb_info *)p);
-}
-
struct chips_init_reg {
unsigned char addr;
unsigned char data;
@@ -473,7 +297,7 @@ static struct chips_init_reg chips_init_xr[] = {
{ 0xa8, 0x00 }
};
-static void __init chips_hw_init(struct fb_info_chips *p)
+static void __init chips_hw_init(void)
{
int i;
@@ -492,12 +316,12 @@ static void __init chips_hw_init(struct fb_info_chips *p)
write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
}
-static void __init init_chips(struct fb_info_chips *p)
-{
- int i;
-
- strcpy(p->fix.id, "C&T 65550");
- p->fix.smem_start = p->frame_buffer_phys;
+static struct fb_fix_screeninfo chipsfb_fix __initdata = {
+ .id = "C&T 65550",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_PSEUDOCOLOR,
+ .accel = FB_ACCEL_NONE,
+ .line_length = 800,
// FIXME: Assumes 1MB frame buffer, but 65550 supports 1MB or 2MB.
// * "3500" PowerBook G3 (the original PB G3) has 2MB.
@@ -506,115 +330,75 @@ static void __init init_chips(struct fb_info_chips *p)
// for a second pair of DRAMs. (Thanks, Apple!)
// * 3400 has 1MB (I think). Don't know if it's expandable.
// -- Tim Seufert
- p->fix.smem_len = 0x100000; // 1MB
- p->fix.type = FB_TYPE_PACKED_PIXELS;
- p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- p->fix.line_length = 800;
-
- p->var.xres = 800;
- p->var.yres = 600;
- p->var.xres_virtual = 800;
- p->var.yres_virtual = 600;
- p->var.bits_per_pixel = 8;
- p->var.red.length = p->var.green.length = p->var.blue.length = 8;
- p->var.height = p->var.width = -1;
- p->var.vmode = FB_VMODE_NONINTERLACED;
- p->var.pixclock = 10000;
- p->var.left_margin = p->var.right_margin = 16;
- p->var.upper_margin = p->var.lower_margin = 16;
- p->var.hsync_len = p->var.vsync_len = 8;
-
- p->disp.var = p->var;
- p->disp.cmap.red = NULL;
- p->disp.cmap.green = NULL;
- p->disp.cmap.blue = NULL;
- p->disp.cmap.transp = NULL;
- p->disp.visual = p->fix.visual;
- p->disp.type = p->fix.type;
- p->disp.type_aux = p->fix.type_aux;
- p->disp.line_length = p->fix.line_length;
- p->disp.can_soft_blank = 1;
- p->disp.dispsw = &fbcon_cfb8;
- p->disp.scrollmode = SCROLL_YREDRAW;
-
- strcpy(p->info.modename, p->fix.id);
- p->info.node = NODEV;
- p->info.fbops = &chipsfb_ops;
- p->info.screen_base = p->frame_buffer;
- p->info.disp = &p->disp;
- p->info.currcon = -1;
- p->info.fontname[0] = 0;
- p->info.changevar = NULL;
- p->info.switch_con = &chipsfbcon_switch;
- p->info.updatevar = &chipsfb_updatevar;
- p->info.flags = FBINFO_FLAG_DEFAULT;
-
- for (i = 0; i < 16; ++i) {
- int j = color_table[i];
- p->palette[i].red = default_red[j];
- p->palette[i].green = default_grn[j];
- p->palette[i].blue = default_blu[j];
- }
+ .smem_len = 0x100000, /* 1MB */
+};
- if (register_framebuffer(&p->info) < 0) {
- kfree(p);
- return;
- }
+static struct fb_var_screeninfo chipsfb_var __initdata = {
+ .xres = 800,
+ .yres = 600,
+ .xres_virtual = 800,
+ .yres_virtual = 600,
+ .bits_per_pixel = 8,
+ .red = { .length = 8 },
+ .green = { .length = 8 },
+ .blue = { .length = 8 },
+ .height = -1,
+ .width = -1,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .pixclock = 10000,
+ .left_margin = 16,
+ .right_margin = 16,
+ .upper_margin = 16,
+ .lower_margin = 16,
+ .hsync_len = 8,
+ .vsync_len = 8,
+};
- printk("fb%d: Chips 65550 frame buffer (%dK RAM detected)\n",
- minor(p->info.node), p->fix.smem_len / 1024);
+static void __init init_chips(struct fb_info *p, unsigned long addr)
+{
+ p->fix = chipsfb_fix;
+ p->fix.smem_start = addr;
- chips_hw_init(p);
+ p->var = chipsfb_var;
-#ifdef CONFIG_PMAC_PBOOK
- if (all_chips == NULL)
- pmu_register_sleep_notifier(&chips_sleep_notifier);
-#endif /* CONFIG_PMAC_PBOOK */
- p->next = all_chips;
- all_chips = p;
-}
+ p->node = NODEV;
+ p->fbops = &chipsfb_ops;
+ p->flags = FBINFO_FLAG_DEFAULT;
-int __init chips_init(void)
-{
- struct pci_dev *dp = NULL;
+ fb_alloc_cmap(&p->cmap, 256, 0);
+
+ if (register_framebuffer(p) < 0) {
+ printk(KERN_ERR "C&T 65550 framebuffer failed to register\n");
+ return;
+ }
+
+ printk(KERN_INFO "fb%d: Chips 65550 frame buffer (%dK RAM detected)\n",
+ minor(p->node), p->fix.smem_len / 1024);
- while ((dp = pci_find_device(PCI_VENDOR_ID_CT,
- PCI_DEVICE_ID_CT_65550, dp)) != NULL)
- if ((dp->class >> 16) == PCI_BASE_CLASS_DISPLAY)
- chips_pci_init(dp);
- return all_chips? 0: -ENODEV;
+ chips_hw_init();
}
-static void __init chips_pci_init(struct pci_dev *dp)
+static int __devinit
+chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
{
- struct fb_info_chips *p;
+ struct fb_info *p = &chipsfb_info;
unsigned long addr, size;
unsigned short cmd;
if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
- return;
- addr = dp->resource[0].start;
- size = dp->resource[0].end + 1 - addr;
+ return -ENODEV;
+ addr = pci_resource_start(dp, 0);
+ size = pci_resource_len(dp, 0);
if (addr == 0)
- return;
- p = kmalloc(sizeof(*p), GFP_ATOMIC);
- if (p == 0)
- return;
- memset(p, 0, sizeof(*p));
- if (!request_mem_region(addr, size, "chipsfb")) {
- kfree(p);
- return;
- }
+ return -ENODEV;
+ if (p->screen_base != 0)
+ return -EBUSY;
+ if (!request_mem_region(addr, size, "chipsfb"))
+ return -EBUSY;
+
#ifdef __BIG_ENDIAN
addr += 0x800000; // Use big-endian aperture
#endif
- p->pdev = dp;
- p->frame_buffer_phys = addr;
- p->frame_buffer = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
- p->blitter_regs_phys = addr + 0x400000;
- p->blitter_regs = ioremap(addr + 0x400000, 0x1000);
- p->blitter_data_phys = addr + 0x410000;
- p->blitter_data = ioremap(addr + 0x410000, 0x10000);
/* we should use pci_enable_device here, but,
the device doesn't declare its I/O ports in its BARs
@@ -623,15 +407,68 @@ static void __init chips_pci_init(struct pci_dev *dp)
cmd |= 3; /* enable memory and IO space */
pci_write_config_word(dp, PCI_COMMAND, cmd);
- /* Clear the entire framebuffer */
- memset(p->frame_buffer, 0, 0x100000);
-
#ifdef CONFIG_PMAC_BACKLIGHT
/* turn on the backlight */
set_backlight_enable(1);
#endif /* CONFIG_PMAC_BACKLIGHT */
- init_chips(p);
+ p->screen_base = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
+ if (p->screen_base == NULL) {
+ release_mem_region(addr, size);
+ return -ENOMEM;
+ }
+
+ init_chips(p, addr);
+
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_register_sleep_notifier(&chips_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+
+ /* Clear the entire framebuffer */
+ memset(p->screen_base, 0, 0x100000);
+
+ pci_set_drvdata(dp, p);
+ return 0;
+}
+
+static void __devexit chipsfb_remove(struct pci_dev *dp)
+{
+ struct fb_info *p = pci_get_drvdata(dp);
+
+ if (p != &chipsfb_info || p->screen_base == NULL)
+ return;
+ unregister_framebuffer(p);
+ iounmap(p->screen_base);
+ p->screen_base = NULL;
+ release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0));
+
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_unregister_sleep_notifier(&chips_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+}
+
+static struct pci_device_id chipsfb_pci_tbl[] __devinitdata = {
+ { PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_65550, PCI_ANY_ID, PCI_ANY_ID },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, chipsfb_pci_tbl);
+
+static struct pci_driver chipsfb_driver = {
+ .name = "chipsfb",
+ .id_table = chipsfb_pci_tbl,
+ .probe = chipsfb_pci_init,
+ .remove = __devexit_p(chipsfb_remove),
+};
+
+int __init chips_init(void)
+{
+ return pci_module_init(&chipsfb_driver);
+}
+
+static void __exit chipsfb_exit(void)
+{
+ pci_unregister_driver(&chipsfb_driver);
}
#ifdef CONFIG_PMAC_PBOOK
@@ -642,40 +479,37 @@ static void __init chips_pci_init(struct pci_dev *dp)
int
chips_sleep_notify(struct pmu_sleep_notifier *self, int when)
{
- struct fb_info_chips *p;
-
- for (p = all_chips; p != NULL; p = p->next) {
- int nb = p->var.yres * p->fix.line_length;
-
- switch (when) {
- case PBOOK_SLEEP_REQUEST:
- p->save_framebuffer = vmalloc(nb);
- if (p->save_framebuffer == NULL)
- return PBOOK_SLEEP_REFUSE;
- break;
- case PBOOK_SLEEP_REJECT:
- if (p->save_framebuffer) {
- vfree(p->save_framebuffer);
- p->save_framebuffer = 0;
- }
- break;
-
- case PBOOK_SLEEP_NOW:
- chipsfb_blank(1, (struct fb_info *)p);
- if (p->save_framebuffer)
- memcpy(p->save_framebuffer,
- p->frame_buffer, nb);
- break;
- case PBOOK_WAKE:
- if (p->save_framebuffer) {
- memcpy(p->frame_buffer,
- p->save_framebuffer, nb);
- vfree(p->save_framebuffer);
- p->save_framebuffer = 0;
- }
- chipsfb_blank(0, (struct fb_info *)p);
- break;
+ struct fb_info *p = &chipsfb_info;
+ int nb = p->var.yres * p->fix.line_length;
+
+ if (p->screen_base == NULL)
+ return PBOOK_SLEEP_OK;
+
+ switch (when) {
+ case PBOOK_SLEEP_REQUEST:
+ save_framebuffer = vmalloc(nb);
+ if (save_framebuffer == NULL)
+ return PBOOK_SLEEP_REFUSE;
+ break;
+ case PBOOK_SLEEP_REJECT:
+ if (save_framebuffer) {
+ vfree(save_framebuffer);
+ save_framebuffer = 0;
+ }
+ break;
+ case PBOOK_SLEEP_NOW:
+ chipsfb_blank(1, p);
+ if (save_framebuffer)
+ memcpy(save_framebuffer, p->screen_base, nb);
+ break;
+ case PBOOK_WAKE:
+ if (save_framebuffer) {
+ memcpy(p->screen_base, save_framebuffer, nb);
+ vfree(save_framebuffer);
+ save_framebuffer = 0;
}
+ chipsfb_blank(0, p);
+ break;
}
return PBOOK_SLEEP_OK;
}
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index bf88c5c88d8d..014a63c6ec45 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -66,13 +66,30 @@ config SGI_NEWPORT_CONSOLE
# bool 'IODC console' CONFIG_IODC_CONSOLE
config STI_CONSOLE
- bool "STI console"
+ bool "STI text console"
depends on PARISC
+ default y
help
The STI console is the builtin display/keyboard on HP-PARISC
machines. Say Y here to build support for it into your kernel.
The alternative is to use your primary serial port as a console.
+config DUMMY_CONSOLE_COLUMNS
+ int "Initial number of STI console screen columns" if STI_CONSOLE
+ depends on STI_CONSOLE || FB_STI
+ default "160"
+ help
+ The default value is 160, which should fit a 1280x1024 monitor.
+ Select 80 if you use a 640x480 resolution by default.
+
+config DUMMY_CONSOLE_ROWS
+ int "Initial number of STI console screen rows" if STI_CONSOLE
+ depends on STI_CONSOLE || FB_STI
+ default "64"
+ help
+ The default value is 64, which should fit a 1280x1024 monitor.
+ Select 25 if you use a 640x480 resolution by default.
+
config PROM_CONSOLE
bool "PROM console"
depends on SPARC32 || SPARC64
@@ -120,19 +137,6 @@ config FBCON_ADVANCED
If unsure, say N.
# Guess what we need
-config FBCON_STI
- tristate
- depends on !FBCON_ADVANCED && FRAMEBUFFER_CONSOLE && FB_STI
- default y
-
-config FONTWIDTH8_ONLY
- bool "Support only 8 pixels wide fonts"
- depends on FRAMEBUFFER_CONSOLE
- help
- Answer Y here will make the kernel provide only the 8x8 fonts (these
- are the less readable).
-
- If unsure, say N.
config FONT_SUN8x16
bool "Sparc console 8x16 font"
@@ -142,7 +146,7 @@ config FONT_SUN8x16
config FONT_SUN12x22
bool "Sparc console 12x22 font (not supported by all drivers)"
- depends on FRAMEBUFFER_CONSOLE && !FONTWIDTH8_ONLY && (!SPARC32 && !SPARC64 && FONTS || SPARC32 || SPARC64)
+ depends on FRAMEBUFFER_CONSOLE && (!SPARC32 && !SPARC64 && FONTS || SPARC32 || SPARC64)
help
This is the high resolution console font for Sun machines with very
big letters (like the letters used in the SPARC PROM). If the
@@ -191,7 +195,7 @@ config FONT_8x16
config FONT_6x11
bool "Mac console 6x11 font (not supported by all drivers)" if FONTS
- depends on FRAMEBUFFER_CONSOLE && !FONTWIDTH8_ONLY
+ depends on FRAMEBUFFER_CONSOLE
default y if !SPARC32 && !SPARC64 && !FONTS && MAC
help
Small console font with Macintosh-style high-half glyphs. Some Mac
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index 8c43a43cdf34..4d05b169ccbb 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -10,30 +10,16 @@ export-objs := fbcon.o fonts.o
# Font handling
font-objs := fonts.o
-ifeq ($(CONFIG_FONT_SUN8x16),y)
- font-objs += font_sun8x16.o
-endif
-ifeq ($(CONFIG_FONT_SUN12x22),y)
- font-objs += font_sun12x22.o
-endif
-ifeq ($(CONFIG_FONT_8x8),y)
- font-objs += font_8x8.o
-endif
-ifeq ($(CONFIG_FONT_8x16),y)
- font-objs += font_8x16.o
-endif
-ifeq ($(CONFIG_FONT_6x11),y)
- font-objs += font_6x11.o
-endif
-ifeq ($(CONFIG_FONT_PEARL_8x8),y)
- font-objs += font_pearl_8x8.o
-endif
-ifeq ($(CONFIG_FONT_ACORN_8x8),y)
- font-objs += font_acorn_8x8.o
-endif
-ifeq ($(CONFIG_FONT_MINI_4x6),y)
- font-objs += font_mini_4x6.o
-endif
+font-objs-$(CONFIG_FONT_SUN8x16) += font_sun8x16.o
+font-objs-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o
+font-objs-$(CONFIG_FONT_8x8) += font_8x8.o
+font-objs-$(CONFIG_FONT_8x16) += font_8x16.o
+font-objs-$(CONFIG_FONT_6x11) += font_6x11.o
+font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o
+font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o
+font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o
+
+font-objs += $(font-objs-y)
# Each configuration option enables a list of files.
@@ -45,9 +31,7 @@ obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o font.o
-# Generic Low Level Drivers
-
-obj-$(CONFIG_FBCON_STI) += fbcon-sti.o
+obj-$(CONFIG_FB_STI) += sticore.o
# Files generated that shall be removed upon make clean
clean-files := promcon_tbl.c
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index ba38857c8e3e..1fd54dc426d8 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -20,8 +20,10 @@
#define DUMMY_COLUMNS ORIG_VIDEO_COLS
#define DUMMY_ROWS ORIG_VIDEO_LINES
#elif defined(__hppa__)
-#define DUMMY_COLUMNS 80 /* fixme ! (mine uses 160x64 at 1280x1024) */
-#define DUMMY_ROWS 25
+/* set by Kconfig. Use 80x25 for 640x480 and 160x64 for 1280x1024 */
+#include <linux/config.h>
+#define DUMMY_COLUMNS CONFIG_DUMMY_CONSOLE_COLUMNS
+#define DUMMY_ROWS CONFIG_DUMMY_CONSOLE_ROWS
#else
#define DUMMY_COLUMNS 80
#define DUMMY_ROWS 25
diff --git a/drivers/video/console/fbcon-sti.c b/drivers/video/console/fbcon-sti.c
deleted file mode 100644
index 35015f8c5592..000000000000
--- a/drivers/video/console/fbcon-sti.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * linux/drivers/video/fbcon-sti.c -- Low level frame buffer
- * operations for generic HP video boards using STI (standard
- * text interface) firmware
- *
- * Based on linux/drivers/video/fbcon-artist.c
- * Created 5 Apr 1997 by Geert Uytterhoeven
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details. */
-
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-#include <linux/string.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <asm/gsc.h> /* for gsc_read/write */
-#include <asm/types.h>
-
-#include <video/fbcon.h>
-#include <video/fbcon-mfb.h>
-
-#include "../sticore.h"
-
-static inline u32
-ram2log(void * addr)
-{
- return (unsigned long) addr;
-}
-
-/* All those functions need better names. */
-
-static void
-memcpy_fromhp_tohp(void *dest, void *src, int count)
-{
- unsigned long d = ram2log(dest);
- unsigned long s = ram2log(src);
-
- count += 3;
- count &= ~3; /* XXX */
-
- while(count) {
- count --;
- gsc_writel(~gsc_readl(s), d);
- d += 32*4;
- s += 32*4;
- }
-}
-
-
-static void
-memset_tohp(void *dest, u32 word, int count)
-{
- unsigned long d = ram2log(dest);
-
- count += 3;
- count &= ~3;
-
- while(count) {
- count--;
- gsc_writel(word, d);
- d += 32;
- }
-}
-
-static u8
-readb_hp(void *src)
-{
- unsigned long s = ram2log(src);
-
- return ~gsc_readb(s);
-}
-
-static void
-writeb_hp(u8 b, void *dst)
-{
- unsigned long d = ram2log(dst);
-
- if((d&0xf0000000) != 0xf0000000) {
- printk("writeb_hp %02x %p (%08lx) (%p)\n",
- b, dst, d, __builtin_return_address(0));
- return;
- }
-
- gsc_writeb(b, d);
-}
-
-static void
-fbcon_sti_setup(struct display *p)
-{
- /* in kernel 2.5 the value of sadly line_length disapeared */
- if (p->var.xres_virtual /*line_length*/)
- p->next_line = p->var.xres_virtual>>3;
- else
- p->next_line = 2048; /* default STI value */
- p->next_plane = 0;
-}
-
-static void
-fbcon_sti_bmove(struct display *p, int sy, int sx,
- int dy, int dx,
- int height, int width)
-{
-#if 0 /* Unfortunately, still broken */
- sti_bmove(default_sti /* FIXME */, sy, sx, dy, dx, height, width);
-#else
- u8 *src, *dest;
- u_int rows;
-
- if (sx == 0 && dx == 0 && width == p->next_line) {
- src = p->fb_info->screen_base+sy*fontheight(p)*width;
- dest = p->fb_info->screen_base+dy*fontheight(p)*width;
- memcpy_fromhp_tohp(dest, src, height*fontheight(p)*width);
- } else if (dy <= sy) {
- src = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx;
- dest = p->fb_info->screen_base+dy*fontheight(p)*p->next_line+dx;
- for (rows = height*fontheight(p); rows--;) {
- memcpy_fromhp_tohp(dest, src, width);
- src += p->next_line;
- dest += p->next_line;
- }
- } else {
- src = p->fb_info->screen_base+((sy+height)*fontheight(p)-1)*p->next_line+sx;
- dest = p->fb_info->screen_base+((dy+height)*fontheight(p)-1)*p->next_line+dx;
- for (rows = height*fontheight(p); rows--;) {
- memcpy_fromhp_tohp(dest, src, width);
- src -= p->next_line;
- dest -= p->next_line;
- }
- }
-#endif
-}
-
-static void
-fbcon_sti_clear(struct vc_data *conp,
- struct display *p, int sy, int sx,
- int height, int width)
-{
- u8 *dest;
- u_int rows;
- int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
-
- dest = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx;
-
- if (sx == 0 && width == p->next_line) {
- if (inverse)
- memset_tohp(dest, ~0, height*fontheight(p)*width);
- else
- memset_tohp(dest, 0, height*fontheight(p)*width);
- } else
- for (rows = height*fontheight(p); rows--; dest += p->next_line)
- if (inverse)
- memset_tohp(dest, 0xffffffff, width);
- else
- memset_tohp(dest, 0x00000000, width);
-}
-
-static void fbcon_sti_putc(struct vc_data *conp,
- struct display *p, int c,
- int yy, int xx)
-{
- u8 *dest, *cdat;
- u_int rows, bold, revs, underl;
- u8 d;
-
- dest = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
- cdat = p->fontdata+(c&p->charmask)*fontheight(p);
- bold = attr_bold(p,c);
- revs = attr_reverse(p,c);
- underl = attr_underline(p,c);
-
- for (rows = fontheight(p); rows--; dest += p->next_line) {
- d = *cdat++;
- if (underl && !rows)
- d = 0xff;
- else if (bold)
- d |= d>>1;
- if (revs)
- d = ~d;
- writeb_hp (d, dest);
- }
-}
-
-static void fbcon_sti_putcs(struct vc_data *conp,
- struct display *p,
- const unsigned short *s,
- int count, int yy, int xx)
-{
- u8 *dest, *dest0, *cdat;
- u_int rows, bold, revs, underl;
- u8 d;
- u16 c;
-
- if(((unsigned)xx > 200) || ((unsigned) yy > 200)) {
- printk("refusing to putcs %p %p %p %d %d %d (%p)\n",
- conp, p, s, count, yy, xx, __builtin_return_address(0));
- return;
- }
-
-
- dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
- if(((u32)dest0&0xf0000000)!=0xf0000000) {
- printk("refusing to putcs %p %p %p %d %d %d (%p) %p = %p + %d * %d * %ld + %d\n",
- conp, p, s, count, yy, xx, __builtin_return_address(0),
- dest0, p->fb_info->screen_base, yy, fontheight(p), p->next_line,
- xx);
- return;
- }
-
- c = scr_readw(s);
- bold = attr_bold(p, c);
- revs = attr_reverse(p, c);
- underl = attr_underline(p, c);
-
- while (count--) {
- c = scr_readw(s++) & p->charmask;
- dest = dest0++;
- cdat = p->fontdata+c*fontheight(p);
- for (rows = fontheight(p); rows--; dest += p->next_line) {
- d = *cdat++;
- if (0 && underl && !rows)
- d = 0xff;
- else if (0 && bold)
- d |= d>>1;
- if (revs)
- d = ~d;
- writeb_hp (d, dest);
- }
- }
-}
-
-static void fbcon_sti_revc(struct display *p,
- int xx, int yy)
-{
- u8 *dest, d;
- u_int rows;
-
- dest = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
- for (rows = fontheight(p); rows--; dest += p->next_line) {
- d = readb_hp(dest);
- writeb_hp (~d, dest);
- }
-}
-
-static void
-fbcon_sti_clear_margins(struct vc_data *conp,
- struct display *p,
- int bottom_only)
-{
- u8 *dest;
- int height, bottom;
- int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
-
-
- /* XXX Need to handle right margin? */
-
- height = p->var.yres - conp->vc_rows * fontheight(p);
- if (!height)
- return;
- bottom = conp->vc_rows + p->yscroll;
- if (bottom >= p->vrows)
- bottom -= p->vrows;
- dest = p->fb_info->screen_base + bottom * fontheight(p) * p->next_line;
- if (inverse)
- memset_tohp(dest, 0xffffffff, height * p->next_line);
- else
- memset_tohp(dest, 0x00000000, height * p->next_line);
-}
-
-
- /*
- * `switch' for the low level operations
- */
-
-struct display_switch fbcon_sti = {
- .setup = fbcon_sti_setup,
- .bmove = fbcon_sti_bmove,
- .clear = fbcon_sti_clear,
- .putc = fbcon_sti_putc,
- .putcs = fbcon_sti_putcs,
- .revc = fbcon_sti_revc,
- .clear_margins =fbcon_sti_clear_margins,
- .fontwidthmask =FONTWIDTH(8)
-};
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 57cd3ca0a32d..a479845950cc 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -73,6 +73,7 @@
#include <linux/fb.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
+#include <linux/font.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -94,11 +95,8 @@
#include <asm/machdep.h>
#include <asm/setup.h>
#endif
-#define INCLUDE_LINUX_LOGO_DATA
-#include <asm/linux_logo.h>
#include "fbcon.h"
-#include "font.h"
#ifdef FBCONDEBUG
# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
@@ -204,8 +202,6 @@ static __inline__ void ypan_down(struct display *p, struct vc_data *vc,
static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy,
int dx, int height, int width, u_int y_break);
-static int fbcon_show_logo(void);
-
#ifdef CONFIG_MAC
/*
* On the Macintoy, there may or may not be a working VBL int. We need to probe
@@ -292,7 +288,10 @@ void gen_set_disp(int con, struct fb_info *info)
struct display *display = fb_display + con;
display->can_soft_blank = info->fbops->fb_blank ? 1 : 0;
- display->scrollmode = SCROLL_YNOMOVE;
+ if (info->var.accel_flags)
+ display->scrollmode = SCROLL_YNOMOVE;
+ else
+ display->scrollmode = SCROLL_YREDRAW;
fbcon_changevar(con);
return;
}
@@ -801,14 +800,6 @@ static int fbcon_changevar(int con)
p->fontdata = font->data;
}
-#ifdef FONTWIDTH8_ONLY
- if (!fontwidthvalid(p, vc->vc_font.width)) {
- /* ++Geert: changed from panic() to `correct and continue' */
- printk(KERN_ERR
- "fbcon_set_display: No support for fontwidth %d\n",
- vc->vc_font.width);
- }
-#endif
updatescrollmode(p, vc);
old_cols = vc->vc_cols;
@@ -927,11 +918,11 @@ static void fbcon_set_display(int con, int init, int logo)
struct display *q = &fb_display[i];
struct vc_data *tmp = vc_cons[i].d;
- if (fontwidthvalid(p, vc->vc_font.width)) {
+ if (!fontwidthvalid(p, vc->vc_font.width)) {
/* If we are not the first console on this
fb, copy the font from that console */
- tmp->vc_font.width = vc->vc_font.width;
- tmp->vc_font.height = vc->vc_font.height;
+ vc->vc_font.width = tmp->vc_font.width;
+ vc->vc_font.height = tmp->vc_font.height;
p->fontdata = q->fontdata;
p->userfont = q->userfont;
if (p->userfont) {
@@ -951,14 +942,6 @@ static void fbcon_set_display(int con, int init, int logo)
p->fontdata = font->data;
}
-#ifdef FONTWIDTH8_ONLY
- if (!fontwidthvalid(p, vc->vc_font.width)) {
- /* ++Geert: changed from panic() to `correct and continue' */
- printk(KERN_ERR
- "fbcon_set_display: No support for fontwidth %d\n",
- vc->vc_font.width);
- }
-#endif
updatescrollmode(p, vc);
old_cols = vc->vc_cols;
@@ -1943,7 +1926,7 @@ static int fbcon_switch(struct vc_data *vc)
accel_clear_margins(vc, p, 0);
if (logo_shown == -2) {
logo_shown = fg_console;
- fbcon_show_logo(); /* This is protected above by initmem_freed */
+ fb_show_logo(info); /* This is protected above by initmem_freed */
update_region(fg_console,
vc->vc_origin + vc->vc_size_row * vc->vc_top,
vc->vc_size_row * (vc->vc_bottom -
@@ -2012,10 +1995,6 @@ static inline int fbcon_get_font(struct vc_data *vc, struct console_font_op *op)
u8 *fontdata = p->fontdata;
int i, j;
-#ifdef CONFIG_FONTWIDTH8_ONLY
- if (fontwidth(p) != 8)
- return -EINVAL;
-#endif
op->width = vc->vc_font.width;
op->height = vc->vc_font.height;
op->charcount = (p->charmask == 0x1ff) ? 512 : 256;
@@ -2030,9 +2009,7 @@ static inline int fbcon_get_font(struct vc_data *vc, struct console_font_op *op)
data += 32;
fontdata += j;
}
- }
-#ifndef CONFIG_FONTWIDTH8_ONLY
- else if (op->width <= 16) {
+ } else if (op->width <= 16) {
j = vc->vc_font.height * 2;
for (i = 0; i < op->charcount; i++) {
memcpy(data, fontdata, j);
@@ -2060,7 +2037,6 @@ static inline int fbcon_get_font(struct vc_data *vc, struct console_font_op *op)
fontdata += j;
}
}
-#endif
return 0;
}
@@ -2213,10 +2189,6 @@ static inline int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
int i, k;
u8 *new_data, *data = op->data, *p;
-#ifdef CONFIG_FONTWIDTH8_ONLY
- if (w != 8)
- return -EINVAL;
-#endif
if ((w <= 0) || (w > 32)
|| (op->charcount != 256 && op->charcount != 512))
return -EINVAL;
@@ -2244,9 +2216,7 @@ static inline int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
data += 32;
p += h;
}
- }
-#ifndef CONFIG_FONTWIDTH8_ONLY
- else if (w <= 16) {
+ } else if (w <= 16) {
h *= 2;
for (i = 0; i < op->charcount; i++) {
memcpy(p, data, h);
@@ -2272,7 +2242,6 @@ static inline int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
p += h;
}
}
-#endif
/* we can do it in u32 chunks because of charcount is 256 or 512, so
font length must be multiple of 256, at least. And 256 is multiple
of 4 */
@@ -2345,8 +2314,7 @@ static struct fb_cmap palette_cmap = {
static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
{
- int unit = vc->vc_num;
- struct display *p = &fb_display[unit];
+ struct display *p = &fb_display[vc->vc_num];
struct fb_info *info = p->fb_info;
int i, j, k;
u8 val;
@@ -2546,253 +2514,6 @@ static int fbcon_set_origin(struct vc_data *vc)
return 0;
}
-static inline unsigned safe_shift(unsigned d, int n)
-{
- return n < 0 ? d >> -n : d << n;
-}
-
-static void __init fbcon_set_logocmap(struct fb_info *info)
-{
- int i, j, n;
-
- for (i = 0; i < LINUX_LOGO_COLORS; i += n) {
- n = LINUX_LOGO_COLORS - i;
- if (n > 16)
- /* palette_cmap provides space for only 16 colors at once */
- n = 16;
- palette_cmap.start = 32 + i;
- palette_cmap.len = n;
- for (j = 0; j < n; ++j) {
- palette_cmap.red[j] =
- (linux_logo_red[i + j] << 8) |
- linux_logo_red[i + j];
- palette_cmap.green[j] =
- (linux_logo_green[i + j] << 8) |
- linux_logo_green[i + j];
- palette_cmap.blue[j] =
- (linux_logo_blue[i + j] << 8) |
- linux_logo_blue[i + j];
- }
- fb_set_cmap(&palette_cmap, 1, info);
- }
-}
-
-static void __init fbcon_set_logo_truepalette(struct fb_info *info, u32 *palette)
-{
- unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
- unsigned char redmask, greenmask, bluemask;
- int redshift, greenshift, blueshift;
- int i;
-
- /*
- * We have to create a temporary palette since console palette is only
- * 16 colors long.
- */
- /* Bug: Doesn't obey msb_right ... (who needs that?) */
- redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8];
- greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
- bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8];
- redshift = info->var.red.offset - (8 - info->var.red.length);
- greenshift = info->var.green.offset - (8 - info->var.green.length);
- blueshift = info->var.blue.offset - (8 - info->var.blue.length);
-
-
- for ( i = 0; i < LINUX_LOGO_COLORS; i++) {
- palette[i+32] = (safe_shift((linux_logo_red[i] & redmask), redshift) |
- safe_shift((linux_logo_green[i] & greenmask), greenshift) |
- safe_shift((linux_logo_blue[i] & bluemask), blueshift));
- }
-}
-
-static void __init fbcon_set_logo_directpalette(struct fb_info *info, u32 *palette)
-{
- int redshift, greenshift, blueshift;
- int i;
-
- redshift = info->var.red.offset;
- greenshift = info->var.green.offset;
- blueshift = info->var.blue.offset;
-
- for (i = 32; i < LINUX_LOGO_COLORS; i++)
- palette[i] = i << redshift | i << greenshift | i << blueshift;
-
-}
-
-static void __init fbcon_set_logo(struct fb_info *info, u8 *logo, int needs_logo)
-{
- int i, j;
-
- switch (needs_logo) {
- case 4:
- for (i = 0; i < (LOGO_W * LOGO_H)/2; i++) {
- logo[i*2] = linux_logo16[i] >> 4;
- logo[(i*2)+1] = linux_logo16[i] & 0xf;
- }
- break;
- case 1:
- case ~1:
- default:
- for (i = 0; i < (LOGO_W * LOGO_H)/8; i++)
- for (j = 0; j < 8; j++)
- logo[i*2] = (linux_logo_bw[i] & (7 - j)) ?
- ((needs_logo == 1) ? 1 : 0) :
- ((needs_logo == 1) ? 0 : 1);
-
- break;
- }
-}
-
-/*
- * Three (3) kinds of logo maps exist. linux_logo (>16 colors), linux_logo_16
- * (16 colors) and linux_logo_bw (2 colors). Depending on the visual format and
- * color depth of the framebuffer, the DAC, the pseudo_palette, and the logo data
- * will be adjusted accordingly.
- *
- * Case 1 - linux_logo:
- * Color exceeds the number of console colors (16), thus we set the hardware DAC
- * using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set.
- *
- * For visuals that require color info from the pseudo_palette, we also construct
- * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
- * will be set.
- *
- * Case 2 - linux_logo_16:
- * The number of colors just matches the console colors, thus there is no need
- * to set the DAC or the pseudo_palette. However, the bitmap is packed, ie,
- * each byte contains color information for two pixels (upper and lower nibble).
- * To be consistent with fb_imageblit() usage, we therefore separate the two
- * nibbles into separate bytes. The "needs_logo" flag will be set to 4.
- *
- * Case 3 - linux_logo_bw:
- * This is similar with Case 2. Each byte contains information for 8 pixels.
- * We isolate each bit and expand each into a byte. The "needs_logo" flag will
- * be set to 1.
- */
-static int __init fbcon_show_logo(void)
- {
- struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */
- struct fb_info *info = p->fb_info;
- struct vc_data *vc = info->display_fg;
- struct fb_image image;
- u32 *palette = NULL, *saved_palette = NULL;
- unsigned char *fb = info->screen_base, *logo_new = NULL;
- int done = 0, x;
- int needs_cmapreset = 0;
- int needs_truepalette = 0;
- int needs_directpalette = 0;
- int needs_logo = 0;
-
- /* Return if the frame buffer is not mapped */
- if (!fb || !info->fbops->fb_imageblit)
- return 0;
-
- image.depth = info->var.bits_per_pixel;
-
- /* reasonable default */
- if (image.depth >= 8)
- image.data = linux_logo;
- else if (image.depth >= 4)
- image.data = linux_logo16;
- else
- image.data = linux_logo_bw;
-
- switch (info->fix.visual) {
- case FB_VISUAL_TRUECOLOR:
- needs_truepalette = 1;
- if (image.depth >= 4 && image.depth <= 8)
- needs_logo = 4;
- else if (image.depth < 4)
- needs_logo = 1;
- break;
- case FB_VISUAL_DIRECTCOLOR:
- if (image.depth >= 24) {
- needs_directpalette = 1;
- needs_cmapreset = 1;
- }
- /* 16 colors */
- else if (image.depth >= 16)
- needs_logo = 4;
- /* 2 colors */
- else
- needs_logo = 1;
- break;
- case FB_VISUAL_MONO01:
- /* reversed 0 = fg, 1 = bg */
- needs_logo = ~1;
- break;
- case FB_VISUAL_MONO10:
- needs_logo = 1;
- break;
- case FB_VISUAL_PSEUDOCOLOR:
- default:
- if (image.depth >= 8)
- needs_cmapreset = 1;
- /* fall through */
- case FB_VISUAL_STATIC_PSEUDOCOLOR:
- /* 16 colors */
- if (image.depth >= 4 && image.depth < 8)
- needs_logo = 4;
- /* 2 colors */
- else if (image.depth < 4)
- needs_logo = 1;
- break;
- }
-
- if (needs_cmapreset)
- fbcon_set_logocmap(info);
-
- if (needs_truepalette || needs_directpalette) {
- palette = kmalloc(256 * 4, GFP_KERNEL);
- if (palette == NULL)
- return 1;
-
- if (needs_truepalette)
- fbcon_set_logo_truepalette(info, palette);
- else
- fbcon_set_logo_directpalette(info, palette);
-
- saved_palette = info->pseudo_palette;
- info->pseudo_palette = palette;
- }
-
- if (needs_logo) {
- logo_new = kmalloc(LOGO_W * LOGO_H, GFP_KERNEL);
- if (logo_new == NULL) {
- if (palette)
- kfree(palette);
- if (saved_palette)
- info->pseudo_palette = saved_palette;
- return 1;
- }
-
- image.data = logo_new;
- fbcon_set_logo(info, logo_new, needs_logo);
- }
-
- image.width = LOGO_W;
- image.height = LOGO_H;
- image.dy = 0;
-
- for (x = 0; x < num_online_cpus() * (LOGO_W + 8) &&
- x < info->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
- image.dx = x;
- info->fbops->fb_imageblit(info, &image);
- done = 1;
- }
-
- if (palette != NULL)
- kfree(palette);
- if (saved_palette != NULL)
- info->pseudo_palette = saved_palette;
- if (logo_new != NULL)
- kfree(logo_new);
- /*
- * Modes not yet supported: packed pixels with depth != 8 (does such a
- * thing exist in reality?)
- */
- return done ? (LOGO_H + vc->vc_font.height - 1) / vc->vc_font.height : 0;
-}
-
/*
* The console `switch' structure for the frame buffer based console
*/
@@ -2823,7 +2544,6 @@ int __init fb_console_init(void)
if (!num_registered_fb)
return -ENODEV;
take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
- __unsafe(THIS_MODULE);
return 0;
}
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index b49beeccc17e..23cc6c5c0504 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -51,28 +51,11 @@ extern struct display fb_display[MAX_NR_CONSOLES];
extern char con2fb_map[MAX_NR_CONSOLES];
extern void set_con2fb_map(int unit, int newidx);
-#define fontheight(p) ((p)->_fontheight)
-
-#ifdef CONFIG_FONTWIDTH8_ONLY
-
-/* fontwidth w is supported by dispsw */
-#define FONTWIDTH(w) (1 << ((8) - 1))
-/* fontwidths w1-w2 inclusive are supported by dispsw */
-#define FONTWIDTHRANGE(w1,w2) FONTWIDTH(8)
-
-#define fontwidth(p) (8)
-
-#else
-
/* fontwidth w is supported by dispsw */
#define FONTWIDTH(w) (1 << ((w) - 1))
/* fontwidths w1-w2 inclusive are supported by dispsw */
#define FONTWIDTHRANGE(w1,w2) (FONTWIDTH(w2+1) - FONTWIDTH(w1))
-#define fontwidth(p) ((p)->_fontwidth)
-
-#endif
-
/*
* Attribute Decoding
*/
diff --git a/drivers/video/console/font.h b/drivers/video/console/font.h
deleted file mode 100644
index 16564d51d28e..000000000000
--- a/drivers/video/console/font.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * font.h -- `Soft' font definitions
- *
- * Created 1995 by Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _VIDEO_CONSOLE_FONT_H
-#define _VIDEO_CONSOLE_FONT_H
-
-#include <video/font.h> /* struct font_desc */
-
-#define VGA8x8_IDX 0
-#define VGA8x16_IDX 1
-#define PEARL8x8_IDX 2
-#define VGA6x11_IDX 3
-#define SUN8x16_IDX 4
-#define SUN12x22_IDX 5
-#define ACORN8x8_IDX 6
-#define MINI4x6_IDX 7
-
-extern struct font_desc font_vga_8x8,
- font_vga_8x16,
- font_pearl_8x8,
- font_vga_6x11,
- font_sun_8x16,
- font_sun_12x22,
- font_acorn_8x8,
- font_mini_4x6;
-
-/* Find a font with a specific name */
-
-extern struct font_desc *find_font(char *name);
-
-/* Get the default font for a specific screen size */
-
-extern struct font_desc *get_default_font(int xres, int yres);
-
-/* Max. length for the name of a predefined font */
-#define MAX_FONT_NAME 32
-
-#endif /* _VIDEO_CONSOLE_FONT_H */
diff --git a/drivers/video/console/font_6x11.c b/drivers/video/console/font_6x11.c
index 062f68d25734..32ff420cf840 100644
--- a/drivers/video/console/font_6x11.c
+++ b/drivers/video/console/font_6x11.c
@@ -4,7 +4,7 @@
/* */
/**********************************************/
-#include "font.h"
+#include <linux/font.h>
#define FONTDATAMAX (11*256)
diff --git a/drivers/video/console/font_8x16.c b/drivers/video/console/font_8x16.c
index a24ea2b6da52..e6f8dbaa122b 100644
--- a/drivers/video/console/font_8x16.c
+++ b/drivers/video/console/font_8x16.c
@@ -4,7 +4,7 @@
/* */
/**********************************************/
-#include "font.h"
+#include <linux/font.h>
#define FONTDATAMAX 4096
diff --git a/drivers/video/console/font_8x8.c b/drivers/video/console/font_8x8.c
index d7cfa088ef89..57fbe266a6b9 100644
--- a/drivers/video/console/font_8x8.c
+++ b/drivers/video/console/font_8x8.c
@@ -4,7 +4,7 @@
/* */
/**********************************************/
-#include "font.h"
+#include <linux/font.h>
#define FONTDATAMAX 2048
diff --git a/drivers/video/console/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c
index 3536c7edce1f..ed0ec4d1e3d7 100644
--- a/drivers/video/console/font_acorn_8x8.c
+++ b/drivers/video/console/font_acorn_8x8.c
@@ -1,8 +1,7 @@
/* Acorn-like font definition, with PC graphics characters */
#include <linux/config.h>
-
-#include "font.h"
+#include <linux/font.h>
static unsigned char acorndata_8x8[] = {
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c
index 8e4cb92c82b7..593b95500a0c 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -39,7 +39,7 @@ __END__;
MSBit to LSBit = left to right.
*/
-#include "font.h"
+#include <linux/font.h>
#define FONTDATAMAX 1536
diff --git a/drivers/video/console/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c
index c84048423cf8..5fa95f118818 100644
--- a/drivers/video/console/font_pearl_8x8.c
+++ b/drivers/video/console/font_pearl_8x8.c
@@ -9,7 +9,7 @@
/* */
/**********************************************/
-#include "font.h"
+#include <linux/font.h>
#define FONTDATAMAX 2048
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c
index 99f01c060fbb..05215d0c3e09 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -1,4 +1,4 @@
-#include "font.h"
+#include <linux/font.h>
#define FONTDATAMAX 11264
diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c
index a8f6d60e8c6e..2af3ab354652 100644
--- a/drivers/video/console/font_sun8x16.c
+++ b/drivers/video/console/font_sun8x16.c
@@ -1,4 +1,4 @@
-#include "font.h"
+#include <linux/font.h>
#define FONTDATAMAX 4096
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 9e88eeb9f479..d5605dc4f79f 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -74,7 +74,7 @@ static char *mda_type_name;
/* console information */
-static int mda_first_vc = 13;
+static int mda_first_vc = 1;
static int mda_last_vc = 16;
static struct vc_data *mda_display_fg = NULL;
@@ -604,28 +604,22 @@ const struct consw mda_con = {
.con_invert_region = mdacon_invert_region,
};
-void __init mda_console_init(void)
+int __init mda_console_init(void)
{
if (mda_first_vc > mda_last_vc)
- return;
+ return 1;
take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0);
-}
-
-#ifdef MODULE
-
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
- mda_console_init();
-
return 0;
}
-void cleanup_module(void)
+void __exit mda_console_exit(void)
{
give_up_console(&mda_con);
}
-#endif
+module_init(mda_console_init);
+module_exit(mda_console_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index fae9b93070ba..148c07239a9a 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -29,7 +29,7 @@
#define INCLUDE_LINUX_LOGO_DATA
#include <asm/linux_logo.h>
-#include "font.h"
+#include <linux/font.h>
#define LOGO_W 80
#define LOGO_H 80
diff --git a/drivers/video/console/sti.h b/drivers/video/console/sti.h
deleted file mode 100644
index feea4fb92fbb..000000000000
--- a/drivers/video/console/sti.h
+++ /dev/null
@@ -1,289 +0,0 @@
-#define STI_REGION_MAX 8
-#define STI_DEV_NAME_LENGTH 32
-
-struct sti_rom_font {
- u16 first_char;
- u16 last_char;
- u8 width;
- u8 height;
- u8 font_type;
- u8 bytes_per_char;
- u32 next_font;
- u8 underline_height;
- u8 underline_pos;
- u8 res008[2];
-};
-
-struct sti_rom {
- u8 type[4];
- u8 res004;
- u8 num_mons;
- u8 revno[2];
- u8 graphics_id[8];
-
- u32 font_start;
- u32 statesize;
- u32 last_addr;
- u32 region_list;
-
- u16 reentsize;
- u16 maxtime;
- u32 mon_tbl_addr;
- u32 user_data_addr;
- u32 sti_mem_req;
-
- u32 user_data_size;
- u16 power;
- u8 bus_support;
- u8 ext_bus_support;
- u8 alt_code_type;
- u8 ext_dd_struct[3];
- u32 cfb_addr;
-
- u32 init_graph;
- u32 state_mgmt;
- u32 font_unpmv;
- u32 block_move;
- u32 self_test;
- u32 excep_hdlr;
- u32 inq_conf;
- u32 set_cm_entry;
- u32 dma_ctrl;
- u8 res040[7 * 4];
-
- u32 init_graph_m68k;
- u32 flow_ctrl;
- u32 user_timing;
- u32 process_mgr;
- u32 sti_util;
- u32 end_addr;
- u32 res0b8;
- u32 res0bc;
-};
-
-struct sti_cooked_font {
- struct sti_rom_font *raw;
- struct sti_cooked_font *next_font;
-};
-
-struct sti_cooked_rom {
- struct sti_rom *raw;
- struct sti_cooked_font *font_start;
- u32 *region_list;
-};
-
-struct sti_glob_cfg_ext {
- u8 curr_mon;
- u8 friendly_boot;
- s16 power;
- s32 freq_ref;
- s32 *sti_mem_addr;
- s32 *future_ptr;
-};
-
-struct sti_glob_cfg {
- s32 text_planes;
- s16 onscreen_x;
- s16 onscreen_y;
- s16 offscreen_x;
- s16 offscreen_y;
- s16 total_x;
- s16 total_y;
- u32 region_ptrs[STI_REGION_MAX];
- s32 reent_lvl;
- s32 *save_addr;
- struct sti_glob_cfg_ext *ext_ptr;
-};
-
-struct sti_init_flags {
- u32 wait : 1;
- u32 reset : 1;
- u32 text : 1;
- u32 nontext : 1;
- u32 clear : 1;
- u32 cmap_blk : 1;
- u32 enable_be_timer : 1;
- u32 enable_be_int : 1;
- u32 no_chg_tx : 1;
- u32 no_chg_ntx : 1;
- u32 no_chg_bet : 1;
- u32 no_chg_bei : 1;
- u32 init_cmap_tx : 1;
- u32 cmt_chg : 1;
- u32 retain_ie : 1;
- u32 pad : 17;
-
- s32 *future_ptr;
-};
-
-struct sti_init_inptr_ext {
- u8 config_mon_type;
- u8 pad[1];
- u16 inflight_data;
- s32 *future_ptr;
-};
-
-struct sti_init_inptr {
- s32 text_planes;
- struct sti_init_inptr_ext *ext_ptr;
-};
-
-struct sti_init_outptr {
- s32 errno;
- s32 text_planes;
- s32 *future_ptr;
-};
-
-struct sti_conf_flags {
- u32 wait : 1;
- u32 pad : 31;
- s32 *future_ptr;
-};
-
-struct sti_conf_inptr {
- s32 *future_ptr;
-};
-
-struct sti_conf_outptr_ext {
- u32 crt_config[3];
- u32 crt_hdw[3];
- s32 *future_ptr;
-};
-
-struct sti_conf_outptr {
- s32 errno;
- s16 onscreen_x;
- s16 onscreen_y;
- s16 offscreen_x;
- s16 offscreen_y;
- s16 total_x;
- s16 total_y;
- s32 bits_per_pixel;
- s32 bits_used;
- s32 planes;
- u8 dev_name[STI_DEV_NAME_LENGTH];
- u32 attributes;
- struct sti_conf_outptr_ext *ext_ptr;
-};
-
-
-struct sti_font_inptr {
- u32 font_start_addr;
- s16 index;
- u8 fg_color;
- u8 bg_color;
- s16 dest_x;
- s16 dest_y;
- s32 *future_ptr;
-};
-
-struct sti_font_flags {
- u32 wait : 1;
- u32 non_text : 1;
- u32 pad : 30;
-
- s32 *future_ptr;
-};
-
-struct sti_font_outptr {
- s32 errno;
- s32 *future_ptr;
-};
-
-struct sti_blkmv_flags {
- u32 wait : 1;
- u32 color : 1;
- u32 clear : 1;
- u32 non_text : 1;
- u32 pad : 28;
- s32 *future_ptr;
-};
-
-struct sti_blkmv_inptr {
- u8 fg_color;
- u8 bg_color;
- s16 src_x;
- s16 src_y;
- s16 dest_x;
- s16 dest_y;
- s16 width;
- s16 height;
- s32 *future_ptr;
-};
-
-struct sti_blkmv_outptr {
- s32 errno;
- s32 *future_ptr;
-};
-
-struct sti_struct {
- spinlock_t lock;
-
- struct sti_cooked_rom *rom;
-
- unsigned long font_unpmv;
- unsigned long block_move;
- unsigned long init_graph;
- unsigned long inq_conf;
-
- struct sti_glob_cfg *glob_cfg;
- struct sti_rom_font *font;
-
- s32 text_planes;
-
- char **mon_strings;
- u32 *regions;
- u8 *pci_regions;
-};
-
-#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
- ({ \
- real32_call( func, (unsigned long)STI_PTR(flags), \
- STI_PTR(inptr), STI_PTR(outptr), \
- glob_cfg); \
- })
-
-/* The latency of the STI functions cannot really be reduced by setting
- * this to 0; STI doesn't seem to be designed to allow calling a different
- * function (or the same function with different arguments) after a
- * function exited with 1 as return value.
- *
- * As all of the functions below could be called from interrupt context,
- * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
- * block. Really bad latency there.
- *
- * Probably the best solution to all this is have the generic code manage
- * the screen buffer and a kernel thread to call STI occasionally.
- *
- * Luckily, the frame buffer guys have the same problem so we can just wait
- * for them to fix it and steal their solution. prumpf
- *
- * Actually, another long-term viable solution is to completely do STI
- * support in userspace - that way we avoid the potential license issues
- * of using proprietary fonts, too. */
-
-#define STI_WAIT 1
-#define STI_PTR(p) ( (typeof(p)) virt_to_phys(p))
-#define PTR_STI(p) ( (typeof(p)) phys_to_virt((unsigned long)p) )
-
-#define sti_onscreen_x(sti) (PTR_STI(sti->glob_cfg)->onscreen_x)
-#define sti_onscreen_y(sti) (PTR_STI(sti->glob_cfg)->onscreen_y)
-#define sti_font_x(sti) (PTR_STI(sti->font)->width)
-#define sti_font_y(sti) (PTR_STI(sti->font)->height)
-
-extern struct sti_struct * sti_init_roms(void);
-
-void sti_init_graph(struct sti_struct *sti);
-void sti_inq_conf(struct sti_struct *sti);
-void sti_putc(struct sti_struct *sti, int c, int y, int x);
-void sti_set(struct sti_struct *sti, int src_y, int src_x,
- int height, int width, u8 color);
-void sti_clear(struct sti_struct *sti, int src_y, int src_x,
- int height, int width);
-void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
- int dst_y, int dst_x, int height, int width);
-
-/* XXX: this probably should not be here, but we rely on STI being
- initialized early and independently of stifb at the moment, so
- there's no other way for stifb to find it. */
-extern struct sti_struct default_sti;
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 634b0289dea7..7294cfedcfac 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -1,7 +1,8 @@
/*
- * linux/drivers/video/sticon.c - console driver using HP's STI firmware
+ * linux/drivers/video/console/sticon.c - console driver using HP's STI firmware
*
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2002 Helge Deller <deller@gmx.de>
*
* Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
* which were
@@ -31,18 +32,7 @@
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
- */
-/*
- * TODO:
- * - call STI in virtual mode rather than in real mode
- * - support for PCI-only STI ROMs (which don't have a traditional region
- * list)
- * - safe detection (i.e. verify there is a graphics device at a given
- * address first, not just read a random device's io space)
- * - support for multiple STI devices in one machine
- * - support for byte-mode STI ROMs
- * - support for just using STI to switch to a colour fb (stifb ?)
- * - try to make it work on m68k hp workstations ;)
+ *
*/
#include <linux/init.h>
@@ -51,92 +41,193 @@
#include <linux/console.h>
#include <linux/errno.h>
#include <linux/vt_kern.h>
+#include <linux/kd.h>
#include <linux/selection.h>
#include <asm/io.h>
-#include "sti.h"
+#include "../sticore.h"
+
+/* switching to graphics mode */
+#define BLANK 0
+static int vga_is_gfx;
+
+
+/* Software scrollback */
+
+static unsigned long softback_buf, softback_curr;
+static unsigned long softback_in;
+static unsigned long /* softback_top, */ softback_end;
+static int softback_lines;
-/* STICON */
-static const char * __init
-sticon_startup(void)
+/* software cursor */
+
+static int cursor_drawn;
+#define CURSOR_DRAW_DELAY (1)
+#define DEFAULT_CURSOR_BLINK_RATE (20)
+
+static int vbl_cursor_cnt;
+
+static inline void cursor_undrawn(void)
{
- return "STI console";
+ vbl_cursor_cnt = 0;
+ cursor_drawn = 0;
}
-static int
-sticon_set_palette(struct vc_data *c, unsigned char *table)
+
+static const char *__init sticon_startup(void)
{
- return -EINVAL;
+ return "STI console";
}
-static int
-sticon_font_op(struct vc_data *c, struct console_font_op *op)
+
+static int sticon_set_palette(struct vc_data *c, unsigned char *table)
{
- return -ENOSYS;
+ return -EINVAL;
+}
+
+static int sticon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+ return -ENOSYS;
}
static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
{
- sti_putc(&default_sti, c, ypos, xpos);
+ int unit = conp->vc_num;
+ int redraw_cursor = 0;
+
+ if (vga_is_gfx || console_blanked)
+ return;
+
+ if (vt_cons[unit]->vc_mode != KD_TEXT)
+ return;
+#if 0
+ if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
+ cursor_undrawn();
+ redraw_cursor = 1;
+ }
+#endif
+
+ sti_putc(default_sti, c, ypos, xpos);
+
+ if (redraw_cursor)
+ vbl_cursor_cnt = CURSOR_DRAW_DELAY;
}
static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
- int count, int ypos, int xpos)
+ int count, int ypos, int xpos)
{
- while(count--) {
- sti_putc(&default_sti, scr_readw(s++), ypos, xpos++);
- }
+ int unit = conp->vc_num;
+ int redraw_cursor = 0;
+
+ if (vga_is_gfx || console_blanked)
+ return;
+
+ if (vt_cons[unit]->vc_mode != KD_TEXT)
+ return;
+
+#if 0
+ if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
+ (p->cursor_x < (xpos + count))) {
+ cursor_undrawn();
+ redraw_cursor = 1;
+ }
+#endif
+
+ while (count--) {
+ sti_putc(default_sti, scr_readw(s++), ypos, xpos++);
+ }
+
+ if (redraw_cursor)
+ vbl_cursor_cnt = CURSOR_DRAW_DELAY;
}
static void sticon_cursor(struct vc_data *conp, int mode)
{
+ unsigned short car1;
+
+ car1 = conp->vc_screenbuf[conp->vc_x + conp->vc_y * conp->vc_cols];
+ switch (mode) {
+ case CM_ERASE:
+ sti_putc(default_sti, car1, conp->vc_y, conp->vc_x);
+ break;
+ case CM_MOVE:
+ case CM_DRAW:
+ switch (conp->vc_cursor_type & 0x0f) {
+ case CUR_UNDERLINE:
+ case CUR_LOWER_THIRD:
+ case CUR_LOWER_HALF:
+ case CUR_TWO_THIRDS:
+ case CUR_BLOCK:
+ sti_putc(default_sti, (car1 & 255) + (0 << 8) + (7 << 11),
+ conp->vc_y, conp->vc_x);
+ break;
+ }
+ break;
+ }
}
-static int sticon_scroll(struct vc_data *conp, int t, int b, int dir,
- int count)
+static int
+sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
{
- struct sti_struct *sti = &default_sti;
-
- if(console_blanked)
- return 0;
-
- sticon_cursor(conp, CM_ERASE);
+ struct sti_struct *sti = default_sti;
- switch(dir) {
- case SM_UP:
- sti_bmove(sti, t+count, 0, t, 0, b-t-count, conp->vc_cols);
- sti_clear(sti, b-count, 0, count, conp->vc_cols);
+ if (vga_is_gfx)
+ return 0;
- break;
+ sticon_cursor(conp, CM_ERASE);
- case SM_DOWN:
- sti_bmove(sti, t, 0, t+count, 0, b-t-count, conp->vc_cols);
- sti_clear(sti, t, 0, count, conp->vc_cols);
+ switch (dir) {
+ case SM_UP:
+ sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
+ sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
+ break;
- break;
- }
+ case SM_DOWN:
+ sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
+ sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
+ break;
+ }
- return 0;
+ return 0;
}
-
-static void sticon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
- int height, int width)
+
+static void
+sticon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
+ int height, int width)
{
- sti_bmove(&default_sti, sy, sx, dy, dx, height, width);
+ if (!width || !height)
+ return;
+#if 0
+ if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
+ (sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
+ ((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
+ (dx <= p->cursor_x) && (p->cursor_x < dx+width)))
+ sticon_cursor(p, CM_ERASE /*|CM_SOFTBACK*/);
+#endif
+
+ sti_bmove(default_sti, sy, sx, dy, dx, height, width);
}
static void sticon_init(struct vc_data *c, int init)
{
- struct sti_struct *sti = &default_sti;
- int vc_cols, vc_rows;
-
- sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
- c->vc_can_do_color = 1;
- vc_cols = PTR_STI(sti->glob_cfg)->onscreen_x / sti_font_x(sti);
- vc_rows = PTR_STI(sti->glob_cfg)->onscreen_y / sti_font_y(sti);
-
- vc_resize(c->vc_num, vc_cols, vc_rows);
+ struct sti_struct *sti = default_sti;
+ int vc_cols, vc_rows;
+
+ sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
+ vc_cols = sti_onscreen_x(sti) / sti->font_width;
+ vc_rows = sti_onscreen_y(sti) / sti->font_height;
+ c->vc_can_do_color = 1;
+
+ if (init) {
+ c->vc_cols = vc_cols;
+ c->vc_rows = vc_rows;
+ } else {
+ /* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
+ /* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
+ vc_resize(c->vc_num, vc_cols, vc_rows);
+/* vc_resize_con(vc_rows, vc_cols, c->vc_num); */
+ }
}
static void sticon_deinit(struct vc_data *c)
@@ -144,71 +235,170 @@ static void sticon_deinit(struct vc_data *c)
}
static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
- int width)
+ int width)
{
- sti_clear(&default_sti, sy, sx, height, width);
+ if (!height || !width)
+ return;
+
+ sti_clear(default_sti, sy, sx, height, width, conp->vc_video_erase_char);
}
static int sticon_switch(struct vc_data *conp)
{
- return 0;
+ return 1; /* needs refreshing */
}
-static int sticon_blank(struct vc_data *conp, int blank)
+static int sticon_set_origin(struct vc_data *conp)
{
- return 0;
+ return 0;
+}
+
+static int sticon_blank(struct vc_data *c, int blank)
+{
+ switch (blank) {
+ case 0: /* unblank */
+ vga_is_gfx = 0;
+ /* Tell console.c that it has to restore the screen itself */
+ return 1;
+ case 1: /* normal blanking */
+ default: /* VESA blanking */
+ if (vga_is_gfx)
+ return 0;
+ sticon_set_origin(c);
+ sti_clear(default_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
+ return 1;
+ case -1: /* Entering graphic mode */
+ sti_clear(default_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
+ vga_is_gfx = 1;
+ return 1;
+ }
+ return 1; /* console needs to restore screen itself */
}
static int sticon_scrolldelta(struct vc_data *conp, int lines)
{
- return 0;
+ return 0;
}
-static int sticon_set_origin(struct vc_data *conp)
+static u16 *sticon_screen_pos(struct vc_data *conp, int offset)
{
- return 0;
+ int line;
+ unsigned long p;
+
+ if (conp->vc_num != fg_console || !softback_lines)
+ return (u16 *)(conp->vc_origin + offset);
+ line = offset / conp->vc_size_row;
+ if (line >= softback_lines)
+ return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row);
+ p = softback_curr + offset;
+ if (p >= softback_end)
+ p += softback_buf - softback_end;
+ return (u16 *)p;
}
-static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, u8 blink, u8 underline, u8 reverse)
+static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos,
+ int *px, int *py)
{
- u8 attr = ((color & 0x70) >> 1) | ((color & 7));
+ int x, y;
+ unsigned long ret;
+ if (pos >= conp->vc_origin && pos < conp->vc_scr_end) {
+ unsigned long offset = (pos - conp->vc_origin) / 2;
+
+ x = offset % conp->vc_cols;
+ y = offset / conp->vc_cols;
+ if (conp->vc_num == fg_console)
+ y += softback_lines;
+ ret = pos + (conp->vc_cols - x) * 2;
+ } else if (conp->vc_num == fg_console && softback_lines) {
+ unsigned long offset = pos - softback_curr;
+
+ if (pos < softback_curr)
+ offset += softback_end - softback_buf;
+ offset /= 2;
+ x = offset % conp->vc_cols;
+ y = offset / conp->vc_cols;
+ ret = pos + (conp->vc_cols - x) * 2;
+ if (ret == softback_end)
+ ret = softback_buf;
+ if (ret == softback_in)
+ ret = conp->vc_origin;
+ } else {
+ /* Should not happen */
+ x = y = 0;
+ ret = conp->vc_origin;
+ }
+ if (px) *px = x;
+ if (py) *py = y;
+ return ret;
+}
- if(reverse) {
- color = ((color>>3)&0x7) | ((color &0x7)<<3);
- }
+static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens,
+ u8 blink, u8 underline, u8 reverse)
+{
+ u8 attr = ((color & 0x70) >> 1) | ((color & 7));
+ if (reverse) {
+ color = ((color >> 3) & 0x7) | ((color & 0x7) << 3);
+ }
- return attr;
+ return attr;
+}
+
+void sticon_invert_region(struct vc_data *conp, u16 *p, int count)
+{
+ int col = 1; /* vga_can_do_color; */
+
+ while (count--) {
+ u16 a = scr_readw(p);
+
+ if (col)
+ a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
+ else
+ a = ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
+
+ scr_writew(a, p++);
+ }
+}
+
+void sticon_save_screen(struct vc_data *conp)
+{
}
struct consw sti_con = {
- .con_startup = sticon_startup,
- .con_init = sticon_init,
- .con_deinit = sticon_deinit,
- .con_clear = sticon_clear,
- .con_putc = sticon_putc,
- .con_putcs = sticon_putcs,
- .con_cursor = sticon_cursor,
- .con_scroll = sticon_scroll,
- .con_bmove = sticon_bmove,
- .con_switch = sticon_switch,
- .con_blank = sticon_blank,
- .con_font_op = sticon_font_op,
- .con_set_palette = sticon_set_palette,
- .con_scrolldelta = sticon_scrolldelta,
- .con_set_origin = sticon_set_origin,
- .con_build_attr = sticon_build_attr,
+ con_startup: sticon_startup,
+ con_init: sticon_init,
+ con_deinit: sticon_deinit,
+ con_clear: sticon_clear,
+ con_putc: sticon_putc,
+ con_putcs: sticon_putcs,
+ con_cursor: sticon_cursor,
+ con_scroll: sticon_scroll,
+ con_bmove: sticon_bmove,
+ con_switch: sticon_switch,
+ con_blank: sticon_blank,
+ con_font_op: sticon_font_op,
+ con_set_palette: sticon_set_palette,
+ con_scrolldelta: sticon_scrolldelta,
+ con_set_origin: sticon_set_origin,
+ con_save_screen: sticon_save_screen,
+ con_build_attr: sticon_build_attr,
+ con_invert_region: sticon_invert_region,
+ con_screen_pos: sticon_screen_pos,
+ con_getxy: sticon_getxy,
};
-static int __init sti_init(void)
+
+
+int __init sticonsole_init(void)
{
- printk("searching for word mode STI ROMs\n");
- if (sti_init_roms()) {
- pdc_console_die();
- take_over_console(&sti_con, 0, MAX_NR_CONSOLES-1, 1);
- return 0;
- } else
- return -ENODEV;
+ if (sti_init_roms()) {
+ if (conswitchp == &dummy_con) {
+ printk(KERN_INFO "sticon: Initializing STI text console.\n");
+ take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1);
+ }
+ return 0;
+ } else
+ return -ENODEV;
}
-module_init(sti_init)
+module_init(sticonsole_init);
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 8437e1570ed3..df348f124ffa 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -1,22 +1,40 @@
+/*
+ * linux/drivers/video/console/sticore.c -
+ * core code for console driver using HP's STI firmware
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Portions Copyright (C) 2001-2002 Helge Deller <deller@gmx.de>
+ * Portions Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+ *
+ * TODO:
+ * - call STI in virtual mode rather than in real mode
+ * - screen blanking with state_mgmt() in text mode STI ?
+ * - try to make it work on m68k hp workstations ;)
+ * - clean up the cache flushing functions
+ *
+ */
+
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/font.h>
-#include <asm/uaccess.h>
#include <asm/pgalloc.h>
-#include <asm/io.h>
+#include <asm/hardware.h>
-#include "sti.h"
+#include "../sticore.h"
-struct sti_struct default_sti = {
- SPIN_LOCK_UNLOCKED,
-};
+#define STI_DRIVERVERSION "0.9"
+
+struct sti_struct *default_sti;
+
+static int num_sti_roms; /* # of STI ROMS found */
+static struct sti_struct *sti_roms[MAX_STI_ROMS]; /* ptr to each sti_struct */
-static struct sti_font_flags default_font_flags = {
- STI_WAIT, 0, 0, NULL
-};
/* The colour indices used by STI are
* 0 - Black
@@ -31,31 +49,36 @@ static struct sti_font_flags default_font_flags = {
* So we have the same colours as VGA (basically one bit each for R, G, B),
* but have to translate them, anyway. */
-static u8 col_trans[8] = {
+static const u8 col_trans[8] = {
0, 6, 4, 5,
2, 7, 3, 1
};
#define c_fg(sti, c) col_trans[((c>> 8) & 7)]
#define c_bg(sti, c) col_trans[((c>>11) & 7)]
-#define c_index(sti, c) (c&0xff)
-
-static struct sti_init_flags default_init_flags = {
- STI_WAIT, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL
+#define c_index(sti, c) ((c) & 0xff)
+
+static const struct sti_init_flags default_init_flags = {
+ .wait = STI_WAIT,
+ .reset = 1,
+ .text = 1,
+ .nontext = 1,
+ .no_chg_bet = 1,
+ .no_chg_bei = 1,
+ .init_cmap_tx = 1,
};
-void
+int
sti_init_graph(struct sti_struct *sti)
{
- struct sti_init_inptr_ext inptr_ext = {
- 0, { 0 }, 0, NULL
- };
+ struct sti_init_inptr_ext inptr_ext = { 0, };
struct sti_init_inptr inptr = {
- 3, STI_PTR(&inptr_ext)
+ 3, /* # of text planes (3 is maximum for STI) */
+ STI_PTR(&inptr_ext)
};
- struct sti_init_outptr outptr = { 0 };
+ struct sti_init_outptr outptr = { 0, };
unsigned long flags;
- s32 ret;
+ int ret;
spin_lock_irqsave(&sti->lock, flags);
@@ -64,42 +87,50 @@ sti_init_graph(struct sti_struct *sti)
spin_unlock_irqrestore(&sti->lock, flags);
+ if (ret < 0) {
+ printk(KERN_ERR "STI init_graph failed (ret %d, errno %d)\n",ret,outptr.errno);
+ return -1;
+ }
+
sti->text_planes = outptr.text_planes;
+ return 0;
}
-static struct sti_conf_flags default_conf_flags = {
- STI_WAIT, 0, NULL
-};
+static const struct sti_conf_flags default_conf_flags = {
+ wait: STI_WAIT,
+ };
void
sti_inq_conf(struct sti_struct *sti)
{
- struct sti_conf_inptr inptr = { NULL };
- struct sti_conf_outptr_ext outptr_ext = { .future_ptr = NULL };
- struct sti_conf_outptr outptr = {
- .ext_ptr = STI_PTR(&outptr_ext)
- };
+ struct sti_conf_inptr inptr = { 0 };
unsigned long flags;
s32 ret;
+
+ sti->outptr.ext_ptr = STI_PTR(&sti->outptr_ext);
do {
spin_lock_irqsave(&sti->lock, flags);
ret = STI_CALL(sti->inq_conf, &default_conf_flags,
- &inptr, &outptr, sti->glob_cfg);
+ &inptr, &sti->outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
- } while(ret == 1);
+ } while (ret == 1);
}
+static const struct sti_font_flags default_font_flags = {
+ wait: STI_WAIT,
+ non_text: 0,
+};
+
void
sti_putc(struct sti_struct *sti, int c, int y, int x)
{
struct sti_font_inptr inptr = {
- (u32) sti->font, c_index(sti, c), c_fg(sti, c), c_bg(sti, c),
- x * sti_font_x(sti), y * sti_font_y(sti), NULL
- };
- struct sti_font_outptr outptr = {
- 0, NULL
+ STI_PTR(sti->font->raw),
+ c_index(sti, c), c_fg(sti, c), c_bg(sti, c),
+ x * sti->font_width, y * sti->font_height, 0
};
+ struct sti_font_outptr outptr = { 0, };
s32 ret;
unsigned long flags;
@@ -108,11 +139,13 @@ sti_putc(struct sti_struct *sti, int c, int y, int x)
ret = STI_CALL(sti->font_unpmv, &default_font_flags,
&inptr, &outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
- } while(ret == 1);
+ } while (ret == 1);
}
-static struct sti_blkmv_flags clear_blkmv_flags = {
- STI_WAIT, 1, 1, 0, 0, NULL
+static const struct sti_blkmv_flags clear_blkmv_flags = {
+ .wait = STI_WAIT,
+ .color = 1,
+ .clear = 1,
};
void
@@ -124,10 +157,10 @@ sti_set(struct sti_struct *sti, int src_y, int src_x,
src_x, src_y ,
src_x, src_y ,
width, height,
- NULL
+ 0
};
- struct sti_blkmv_outptr outptr = { 0, NULL };
- s32 ret = 0;
+ struct sti_blkmv_outptr outptr = { 0, };
+ s32 ret;
unsigned long flags;
do {
@@ -135,22 +168,22 @@ sti_set(struct sti_struct *sti, int src_y, int src_x,
ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
&inptr, &outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
- } while(ret == 1);
+ } while (ret == 1);
}
void
sti_clear(struct sti_struct *sti, int src_y, int src_x,
- int height, int width)
+ int height, int width, int c)
{
struct sti_blkmv_inptr inptr = {
- 0, 0,
- src_x * sti_font_x(sti), src_y * sti_font_y(sti),
- src_x * sti_font_x(sti), src_y * sti_font_y(sti),
- width * sti_font_x(sti), height* sti_font_y(sti),
- NULL
+ c_fg(sti, c), c_bg(sti, c),
+ src_x * sti->font_width, src_y * sti->font_height,
+ src_x * sti->font_width, src_y * sti->font_height,
+ width * sti->font_width, height* sti->font_height,
+ 0
};
- struct sti_blkmv_outptr outptr = { 0, NULL };
- s32 ret = 0;
+ struct sti_blkmv_outptr outptr = { 0, };
+ s32 ret;
unsigned long flags;
do {
@@ -158,11 +191,11 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x,
ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
&inptr, &outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
- } while(ret == 1);
+ } while (ret == 1);
}
-static struct sti_blkmv_flags default_blkmv_flags = {
- STI_WAIT, 0, 0, 0, 0, NULL
+static const struct sti_blkmv_flags default_blkmv_flags = {
+ .wait = STI_WAIT,
};
void
@@ -171,13 +204,13 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
{
struct sti_blkmv_inptr inptr = {
0, 0,
- src_x * sti_font_x(sti), src_y * sti_font_y(sti),
- dst_x * sti_font_x(sti), dst_y * sti_font_y(sti),
- width * sti_font_x(sti), height* sti_font_y(sti),
- NULL
+ src_x * sti->font_width, src_y * sti->font_height,
+ dst_x * sti->font_width, dst_y * sti->font_height,
+ width * sti->font_width, height* sti->font_height,
+ 0
};
- struct sti_blkmv_outptr outptr = { 0, NULL };
- s32 ret = 0;
+ struct sti_blkmv_outptr outptr = { 0, };
+ s32 ret;
unsigned long flags;
do {
@@ -185,170 +218,128 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
ret = STI_CALL(sti->block_move, &default_blkmv_flags,
&inptr, &outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
- } while(ret == 1);
+ } while (ret == 1);
}
-static void __init
-sti_rom_copy(unsigned long base, unsigned long offset,
- unsigned long count, void *dest)
+void __init
+sti_rom_copy(unsigned long base, unsigned long count, void *dest)
{
- void *savedest = dest;
- int savecount = count;
+ unsigned long dest_len = count;
+ unsigned long dest_start = (unsigned long) dest;
- while(count >= 4) {
+ /* this still needs to be revisited (see arch/parisc/mm/init.c:246) ! */
+ while (count >= 4) {
count -= 4;
- *(u32 *)dest = gsc_readl(base + offset);
- offset += 4;
+ *(u32 *)dest = __raw_readl(base);
+ base += 4;
dest += 4;
}
- while(count) {
+ while (count) {
count--;
- *(u8 *)dest = gsc_readb(base + offset);
- offset++;
+ *(u8 *)dest = __raw_readb(base);
+ base++;
dest++;
}
- flush_kernel_dcache_range((unsigned long)dest, count);
- flush_icache_range((unsigned long)dest, dest + count);
-}
-
-static void dump_sti_rom(struct sti_rom *rom)
-{
- printk("STI word mode ROM type %d\n", rom->type[3]);
- printk(" supports %d monitors\n", rom->num_mons);
- printk(" conforms to STI ROM spec revision %d.%02x\n",
- rom->revno[0] >> 4, rom->revno[0] & 0x0f);
- printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02x\n",
- rom->graphics_id[0],
- rom->graphics_id[1],
- rom->graphics_id[2],
- rom->graphics_id[3],
- rom->graphics_id[4],
- rom->graphics_id[5],
- rom->graphics_id[6],
- rom->graphics_id[7]);
- printk(" font start %08x\n", rom->font_start);
- printk(" region list %08x\n", rom->region_list);
- printk(" init_graph %08x\n", rom->init_graph);
- printk(" alternate code type %d\n", rom->alt_code_type);
+ sti_flush(dest_start, dest_len); /* XXX */
}
-static void __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
- struct sti_rom *raw_rom)
-{
- struct sti_rom_font *raw_font;
- struct sti_cooked_font *cooked_font;
- struct sti_rom_font *font_start;
-
- cooked_font =
- kmalloc(sizeof *cooked_font, GFP_KERNEL);
- if(!cooked_font)
- return;
- cooked_rom->font_start = cooked_font;
- raw_font = ((void *)raw_rom) + (raw_rom->font_start);
- font_start = raw_font;
- cooked_font->raw = raw_font;
+static char default_sti_path[21];
- while(raw_font->next_font) {
- raw_font = ((void *)font_start) + (raw_font->next_font);
-
- cooked_font->next_font =
- kmalloc(sizeof *cooked_font, GFP_KERNEL);
- if(!cooked_font->next_font)
- return;
+static int __init
+sti_setup(char *str)
+{
+ if (str)
+ strncpy (default_sti_path, str, sizeof (default_sti_path));
+
+ return 0;
+}
- cooked_font = cooked_font->next_font;
+/* Assuming the machine has multiple STI consoles (=graphic cards) which
+ * all get detected by sticon, the user may define with the linux kernel
+ * parameter sti=<x> which of them will be the initial boot-console.
+ * <x> is a number between 0 and MAX_STI_ROMS, with 0 as the default
+ * STI screen.
+ */
+__setup("sti=", sti_setup);
- cooked_font->raw = raw_font;
- }
- cooked_font->next_font = NULL;
-}
-static int font_index, font_height, font_width;
+static char __initdata *font_name[MAX_STI_ROMS] = { "VGA8x16", };
+static int __initdata font_index[MAX_STI_ROMS],
+ font_height[MAX_STI_ROMS],
+ font_width[MAX_STI_ROMS];
static int __init sti_font_setup(char *str)
{
char *x;
+ int i = 0;
- /* we accept sti_font=10x20, sti_font=10*20 or sti_font=7 style
- * command lines. */
-
- if((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {
- font_height = simple_strtoul(str, NULL, 0);
- font_width = simple_strtoul(x+1, NULL, 0);
- } else {
- font_index = simple_strtoul(str, NULL, 0);
- }
-
- return 0;
-}
+ /* we accept sti_font=VGA8x16, sti_font=10x20, sti_font=10*20
+ * or sti_font=7 style command lines. */
+
+ while (i<MAX_STI_ROMS && str && *str) {
+ if (*str>='0' && *str<='9') {
+ if ((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {
+ font_height[i] = simple_strtoul(str, NULL, 0);
+ font_width[i] = simple_strtoul(x+1, NULL, 0);
+ } else {
+ font_index[i] = simple_strtoul(str, NULL, 0);
+ }
+ } else {
+ font_name[i] = str; /* fb font name */
+ }
-__setup("sti_font=", sti_font_setup);
+ if ((x = strchr(str, ',')))
+ *x++ = 0;
+ str = x;
-static int __init sti_search_font(struct sti_cooked_rom *rom,
- int height, int width)
-{
- struct sti_cooked_font *font;
- int i = 0;
-
- for(font = rom->font_start; font; font = font->next_font, i++) {
- if((font->raw->width == width) && (font->raw->height == height))
- return i;
+ i++;
}
return 0;
}
-static struct sti_cooked_font * __init
-sti_select_font(struct sti_cooked_rom *rom)
-{
- struct sti_cooked_font *font;
- int i;
-
- if(font_width && font_height)
- font_index = sti_search_font(rom, font_height, font_width);
+/* The optional linux kernel parameter "sti_font" defines which font
+ * should be used by the sticon driver to draw characters to the screen.
+ * Possible values are:
+ * - sti_font=<fb_fontname>:
+ * <fb_fontname> is the name of one of the linux-kernel built-in
+ * framebuffer font names (e.g. VGA8x16, SUN22x18).
+ * This is only available if the fonts have been statically compiled
+ * in with e.g. the CONFIG_FONT_8x16 or CONFIG_FONT_SUN12x22 options.
+ * - sti_font=<number>
+ * most STI ROMs have built-in HP specific fonts, which can be selected
+ * by giving the desired number to the sticon driver.
+ * NOTE: This number is machine and STI ROM dependend.
+ * - sti_font=<height>x<width> (e.g. sti_font=16x8)
+ * <height> and <width> gives hints to the height and width of the
+ * font which the user wants. The sticon driver will try to use
+ * a font with this height and width, but if no suitable font is
+ * found, sticon will use the default 8x8 font.
+ */
+__setup("sti_font=", sti_font_setup);
- for(font = rom->font_start, i = font_index;
- font && (i > 0);
- font = font->next_font, i--);
- if(font)
- return font;
- else
- return rom->font_start;
-}
-static void __init
-sti_dump_globcfg_ext(struct sti_glob_cfg_ext *cfg)
-{
- printk( "monitor %d\n"
- "in friendly mode: %d\n"
- "power consumption %d watts\n"
- "freq ref %d\n"
- "sti_mem_addr %p\n",
- cfg->curr_mon,
- cfg->friendly_boot,
- cfg->power,
- cfg->freq_ref,
- cfg->sti_mem_addr);
-}
-
void __init
-sti_dump_globcfg(struct sti_glob_cfg *glob_cfg)
+sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request)
{
- printk( "%d text planes\n"
+ struct sti_glob_cfg_ext *cfg;
+
+ DPRINTK((KERN_INFO
+ "%d text planes\n"
"%4d x %4d screen resolution\n"
"%4d x %4d offscreen\n"
"%4d x %4d layout\n"
"regions at %08x %08x %08x %08x\n"
"regions at %08x %08x %08x %08x\n"
"reent_lvl %d\n"
- "save_addr %p\n",
+ "save_addr %08x\n",
glob_cfg->text_planes,
glob_cfg->onscreen_x, glob_cfg->onscreen_y,
glob_cfg->offscreen_x, glob_cfg->offscreen_y,
@@ -358,105 +349,420 @@ sti_dump_globcfg(struct sti_glob_cfg *glob_cfg)
glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
glob_cfg->reent_lvl,
- glob_cfg->save_addr);
- sti_dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr));
+ glob_cfg->save_addr));
+
+ /* dump extended cfg */
+ cfg = PTR_STI(glob_cfg->ext_ptr);
+ DPRINTK(( KERN_INFO
+ "monitor %d\n"
+ "in friendly mode: %d\n"
+ "power consumption %d watts\n"
+ "freq ref %d\n"
+ "sti_mem_addr %08x (size=%d bytes)\n",
+ cfg->curr_mon,
+ cfg->friendly_boot,
+ cfg->power,
+ cfg->freq_ref,
+ cfg->sti_mem_addr, sti_mem_request));
}
-
-static void __init
-sti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa,
- unsigned long rom_address)
+
+void __init
+sti_dump_outptr(struct sti_struct *sti)
+{
+ DPRINTK((KERN_INFO
+ "%d bits per pixel\n"
+ "%d used bits\n"
+ "%d planes\n"
+ "attributes %08x\n",
+ sti->outptr.bits_per_pixel,
+ sti->outptr.bits_used,
+ sti->outptr.planes,
+ sti->outptr.attributes));
+}
+
+int __init
+sti_init_glob_cfg(struct sti_struct *sti,
+ unsigned long rom_address, unsigned long hpa)
{
struct sti_glob_cfg *glob_cfg;
struct sti_glob_cfg_ext *glob_cfg_ext;
void *save_addr;
void *sti_mem_addr;
+ const int save_addr_size = 1024; /* XXX */
+ int i;
+
+ if (!sti->sti_mem_request)
+ sti->sti_mem_request = 256; /* STI default */
- glob_cfg = kmalloc(sizeof *sti->glob_cfg, GFP_KERNEL);
- glob_cfg_ext = kmalloc(sizeof *glob_cfg_ext, GFP_KERNEL);
- save_addr = kmalloc(1024 /*XXX*/, GFP_KERNEL);
- sti_mem_addr = kmalloc(1024, GFP_KERNEL);
+ glob_cfg = kmalloc(sizeof(*sti->glob_cfg), GFP_KERNEL);
+ glob_cfg_ext = kmalloc(sizeof(*glob_cfg_ext), GFP_KERNEL);
+ save_addr = kmalloc(save_addr_size, GFP_KERNEL);
+ sti_mem_addr = kmalloc(sti->sti_mem_request, GFP_KERNEL);
- if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr))
- return;
+ if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr))
+ return -ENOMEM;
- memset(glob_cfg, 0, sizeof *glob_cfg);
- memset(glob_cfg_ext, 0, sizeof *glob_cfg_ext);
- memset(save_addr, 0, 1024);
- memset(sti_mem_addr, 0, 1024);
+ memset(glob_cfg, 0, sizeof(*glob_cfg));
+ memset(glob_cfg_ext, 0, sizeof(*glob_cfg_ext));
+ memset(save_addr, 0, save_addr_size);
+ memset(sti_mem_addr, 0, sti->sti_mem_request);
glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
glob_cfg->save_addr = STI_PTR(save_addr);
- glob_cfg->region_ptrs[0] = ((sti->regions[0]>>18)<<12) + rom_address;
- glob_cfg->region_ptrs[1] = ((sti->regions[1]>>18)<<12) + hpa;
- glob_cfg->region_ptrs[2] = ((sti->regions[2]>>18)<<12) + hpa;
- glob_cfg->region_ptrs[3] = ((sti->regions[3]>>18)<<12) + hpa;
- glob_cfg->region_ptrs[4] = ((sti->regions[4]>>18)<<12) + hpa;
- glob_cfg->region_ptrs[5] = ((sti->regions[5]>>18)<<12) + hpa;
- glob_cfg->region_ptrs[6] = ((sti->regions[6]>>18)<<12) + hpa;
- glob_cfg->region_ptrs[7] = ((sti->regions[7]>>18)<<12) + hpa;
-
+ for (i=0; i<8; i++) {
+ unsigned long newhpa, len;
+
+ if (sti->pd) {
+ unsigned char offs = sti->rm_entry[i];
+
+ if (offs == 0)
+ continue;
+ if (offs != PCI_ROM_ADDRESS &&
+ (offs < PCI_BASE_ADDRESS_0 ||
+ offs > PCI_BASE_ADDRESS_5)) {
+ printk (KERN_WARNING
+ "STI pci region maping for region %d (%02x) can't be mapped\n",
+ i,sti->rm_entry[i]);
+ continue;
+ }
+ newhpa = pci_resource_start (sti->pd, (offs - PCI_BASE_ADDRESS_0) / 4);
+ } else
+ newhpa = (i == 0) ? rom_address : hpa;
+
+ sti->regions_phys[i] =
+ REGION_OFFSET_TO_PHYS(sti->regions[i], newhpa);
+
+ /* remap virtually */
+ /* FIXME: add BTLB support if btlb==1 */
+ len = sti->regions[i].region_desc.length * 4096;
+
+ if (len)
+ glob_cfg->region_ptrs[i] = (unsigned long) (
+ sti->regions[i].region_desc.cache ?
+ ioremap(sti->regions_phys[i], len) :
+ ioremap_nocache(sti->regions_phys[i], len) );
+
+ DPRINTK(("region #%d: phys %08lx, virt %08x, len=%lukB, "
+ "btlb=%d, sysonly=%d, cache=%d, last=%d\n",
+ i, sti->regions_phys[i], glob_cfg->region_ptrs[i],
+ len/1024,
+ sti->regions[i].region_desc.btlb,
+ sti->regions[i].region_desc.sys_only,
+ sti->regions[i].region_desc.cache,
+ sti->regions[i].region_desc.last));
+
+ /* last entry reached ? */
+ if (sti->regions[i].region_desc.last)
+ break;
+ }
+
+ if (++i<8 && sti->regions[i].region)
+ printk(KERN_WARNING "%s: *future ptr (0x%8x) not yet supported !\n",
+ __FILE__, sti->regions[i].region);
+
glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
- sti->glob_cfg = STI_PTR(glob_cfg);
+ sti->glob_cfg = glob_cfg;
+
+ return 0;
}
-/* address is a pointer to a word mode or pci rom */
-static struct sti_struct * __init
-sti_read_rom(unsigned long address)
+#ifdef CONFIG_FB
+struct sti_cooked_font * __init
+sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name )
{
- struct sti_struct *ret = NULL;
- struct sti_cooked_rom *cooked = NULL;
- struct sti_rom *raw = NULL;
- unsigned long size;
+ struct font_desc *fbfont;
+ unsigned int size, bpc;
+ void *dest;
+ struct sti_rom_font *nf;
+ struct sti_cooked_font *cooked_font;
+
+ if (!fbfont_name || !strlen(fbfont_name))
+ return NULL;
+ fbfont = find_font(fbfont_name);
+ if (!fbfont)
+ fbfont = get_default_font(1024,768);
+ if (!fbfont)
+ return NULL;
+
+ DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n",
+ fbfont->width, fbfont->height, fbfont->name));
+
+ bpc = ((fbfont->width+7)/8) * fbfont->height;
+ size = bpc * 256;
+ size += sizeof(struct sti_rom_font);
+
+ nf = kmalloc(size, GFP_KERNEL);
+ if (!nf)
+ return NULL;
+ memset(nf, 0, size);
+
+ nf->first_char = 0;
+ nf->last_char = 255;
+ nf->width = fbfont->width;
+ nf->height = fbfont->height;
+ nf->font_type = STI_FONT_HPROMAN8;
+ nf->bytes_per_char = bpc;
+ nf->next_font = 0;
+ nf->underline_height = 1;
+ nf->underline_pos = fbfont->height - nf->underline_height;
+
+ dest = nf;
+ dest += sizeof(struct sti_rom_font);
+ memcpy(dest, fbfont->data, bpc*256);
+
+ cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+ if (!cooked_font) {
+ kfree(nf);
+ return NULL;
+ }
+
+ cooked_font->raw = nf;
+ cooked_font->next_font = NULL;
- ret = &default_sti;
+ cooked_rom->font_start = cooked_font;
- if(!ret)
- goto out_err;
+ return cooked_font;
+}
+#else
+struct sti_cooked_font * __init
+sti_select_fbfont(struct sti_cooked_rom *cooked_rom, char *fbfont_name)
+{
+ return NULL;
+}
+#endif
- cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
- raw = kmalloc(sizeof *raw, GFP_KERNEL);
+struct sti_cooked_font * __init
+sti_select_font(struct sti_cooked_rom *rom,
+ int (*search_font_fnc) (struct sti_cooked_rom *,int,int) )
+{
+ struct sti_cooked_font *font;
+ int i;
+ int index = num_sti_roms;
+
+ /* check for framebuffer-font first */
+ if ((font = sti_select_fbfont(rom, font_name[index])))
+ return font;
+
+ if (font_width[index] && font_height[index])
+ font_index[index] = search_font_fnc(rom,
+ font_height[index], font_width[index]);
+
+ for (font = rom->font_start, i = font_index[index];
+ font && (i > 0);
+ font = font->next_font, i--);
+
+ if (font)
+ return font;
+ else
+ return rom->font_start;
+}
+
+
+static void __init
+sti_dump_rom(struct sti_rom *rom)
+{
+ printk(KERN_INFO "STI id %04x-%04x, conforms to spec rev. %d.%02x\n",
+ rom->graphics_id[0],
+ rom->graphics_id[1],
+ rom->revno[0] >> 4,
+ rom->revno[0] & 0x0f);
+ DPRINTK((" supports %d monitors\n", rom->num_mons));
+ DPRINTK((" font start %08x\n", rom->font_start));
+ DPRINTK((" region list %08x\n", rom->region_list));
+ DPRINTK((" init_graph %08x\n", rom->init_graph));
+ DPRINTK((" bus support %02x\n", rom->bus_support));
+ DPRINTK((" ext bus support %02x\n", rom->ext_bus_support));
+ DPRINTK((" alternate code type %d\n", rom->alt_code_type));
+}
+
+
+static int __init
+sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
+ struct sti_rom *raw_rom)
+{
+ struct sti_rom_font *raw_font, *font_start;
+ struct sti_cooked_font *cooked_font;
- if(!(raw && cooked))
- goto out_err;
+ cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+ if (!cooked_font)
+ return 0;
- /* reallocate raw */
- sti_rom_copy(address, 0, sizeof *raw, raw);
+ cooked_rom->font_start = cooked_font;
- dump_sti_rom(raw);
+ raw_font = ((void *)raw_rom) + (raw_rom->font_start);
- size = raw->last_addr;
- /* kfree(raw); */
- raw = kmalloc(size, GFP_KERNEL);
- if(!raw)
- goto out_err;
- sti_rom_copy(address, 0, size, raw);
+ font_start = raw_font;
+ cooked_font->raw = raw_font;
- sti_cook_fonts(cooked, raw);
-#if 0
- sti_cook_regions(cooked, raw);
- sti_cook_functions(cooked, raw);
-#endif
+ while (raw_font->next_font) {
+ raw_font = ((void *)font_start) + (raw_font->next_font);
+
+ cooked_font->next_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
+ if (!cooked_font->next_font)
+ return 1;
+
+ cooked_font = cooked_font->next_font;
+
+ cooked_font->raw = raw_font;
+ }
+
+ cooked_font->next_font = NULL;
+ return 1;
+}
+
+
+static int __init
+sti_search_font(struct sti_cooked_rom *rom, int height, int width)
+{
+ struct sti_cooked_font *font;
+ int i = 0;
+
+ for(font = rom->font_start; font; font = font->next_font, i++) {
+ if((font->raw->width == width) && (font->raw->height == height))
+ return i;
+ }
+ return 0;
+}
+
+#define BMODE_RELOCATE(offset) offset = (offset) / 4;
+#define BMODE_LAST_ADDR_OFFS 0x50
+
+static void * __init
+sti_bmode_font_raw(struct sti_cooked_font *f)
+{
+ unsigned char *n, *p, *q;
+ int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font);
+
+ n = kmalloc (4*size, GFP_KERNEL);
+ if (!n)
+ return NULL;
+ memset (n, 0, 4*size);
+ p = n + 3;
+ q = (unsigned char *)f->raw;
+ while (size--) {
+ *p = *q++;
+ p+=4;
+ }
+ return n + 3;
+}
- if(raw->region_list) {
- ret->regions = kmalloc(32, GFP_KERNEL); /* FIXME */
+static void __init
+sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest)
+{
+ unsigned long dest_len = count;
+ unsigned long dest_start = (unsigned long) dest;
- memcpy(ret->regions, ((void *)raw)+raw->region_list, 32);
+ while (count) {
+ count--;
+ *(u8 *)dest = __raw_readl(base);
+ base += 4;
+ dest++;
}
+ sti_flush(dest_start, dest_len); /* XXX */
+}
- address = virt_to_phys(raw);
+struct sti_rom * __init
+sti_get_bmode_rom (unsigned long address)
+{
+ struct sti_rom *raw;
+ u32 size;
+ struct sti_rom_font *raw_font, *font_start;
+
+ sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size);
+
+ size = (size+3) / 4;
+ raw = kmalloc(size, GFP_KERNEL);
+ if (raw) {
+ sti_bmode_rom_copy(address, size, raw);
+ memmove (&raw->res004, &raw->type[0], 0x3c);
+ raw->type[3] = raw->res004;
+
+ BMODE_RELOCATE (raw->region_list);
+ BMODE_RELOCATE (raw->font_start);
+
+ BMODE_RELOCATE (raw->init_graph);
+ BMODE_RELOCATE (raw->state_mgmt);
+ BMODE_RELOCATE (raw->font_unpmv);
+ BMODE_RELOCATE (raw->block_move);
+ BMODE_RELOCATE (raw->inq_conf);
+
+ raw_font = ((void *)raw) + raw->font_start;
+ font_start = raw_font;
+
+ while (raw_font->next_font) {
+ BMODE_RELOCATE (raw_font->next_font);
+ raw_font = ((void *)font_start) + raw_font->next_font;
+ }
+ }
+ return raw;
+}
- ret->font_unpmv = address+(raw->font_unpmv & 0x03ffffff);
- ret->block_move = address+(raw->block_move & 0x03ffffff);
- ret->init_graph = address+(raw->init_graph & 0x03ffffff);
- ret->inq_conf = address+(raw->inq_conf & 0x03ffffff);
+struct sti_rom * __init
+sti_get_wmode_rom (unsigned long address)
+{
+ struct sti_rom *raw;
+ unsigned long size;
+
+ /* read the ROM size directly from the struct in ROM */
+ size = __raw_readl(address + offsetof(struct sti_rom,last_addr));
- ret->rom = cooked;
- ret->rom->raw = raw;
+ raw = kmalloc(size, GFP_KERNEL);
+ if(raw)
+ sti_rom_copy(address, size, raw);
- ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw);
+ return raw;
+}
- return ret;
+int __init
+sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
+{
+ struct sti_cooked_rom *cooked;
+ struct sti_rom *raw = NULL;
+
+ cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
+ if (!cooked)
+ goto out_err;
+
+ if (wordmode)
+ raw = sti_get_wmode_rom (address);
+ else
+ raw = sti_get_bmode_rom (address);
+
+ if (!raw)
+ goto out_err;
+
+ if (!sti_cook_fonts(cooked, raw)) {
+ printk(KERN_ERR "No font found for STI at %08lx\n", address);
+ goto out_err;
+ }
+
+ if (raw->region_list)
+ memcpy(sti->regions, ((void *)raw)+raw->region_list, sizeof(sti->regions));
+
+ address = (unsigned long) STI_PTR(raw);
+
+ sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff);
+ sti->block_move = address + (raw->block_move & 0x03ffffff);
+ sti->init_graph = address + (raw->init_graph & 0x03ffffff);
+ sti->inq_conf = address + (raw->inq_conf & 0x03ffffff);
+
+ sti->rom = cooked;
+ sti->rom->raw = raw;
+
+ sti->font = sti_select_font(sti->rom, sti_search_font);
+ sti->font_width = sti->font->raw->width;
+ sti->font_height = sti->font->raw->height;
+ if (!wordmode)
+ sti->font->raw = sti_bmode_font_raw(sti->font);
+
+ sti->sti_mem_request = raw->sti_mem_req;
+ sti->graphics_id[0] = raw->graphics_id[0];
+ sti->graphics_id[1] = raw->graphics_id[1];
+
+ sti_dump_rom(raw);
+
+ return 1;
out_err:
if(raw)
@@ -464,138 +770,290 @@ out_err:
if(cooked)
kfree(cooked);
- return NULL;
+ return 0;
}
static struct sti_struct * __init
-sti_try_rom(unsigned long address, unsigned long hpa)
+sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd)
{
- struct sti_struct *sti = NULL;
- u16 sig;
+ struct sti_struct *sti;
+ int ok;
+ u32 sig;
+
+ if (num_sti_roms >= MAX_STI_ROMS) {
+ printk(KERN_WARNING "maximum number of STI ROMS reached !\n");
+ return NULL;
+ }
+ sti = kmalloc(sizeof(*sti), GFP_KERNEL);
+ if (!sti) {
+ printk(KERN_ERR "Not enough memory !\n");
+ return NULL;
+ }
+
+ memset(sti, 0, sizeof(*sti));
+ sti->lock = SPIN_LOCK_UNLOCKED;
+
test_rom:
/* if we can't read the ROM, bail out early. Not being able
* to read the hpa is okay, for romless sti */
- if(pdc_add_valid((void*)address))
- return NULL;
-
- printk("found potential STI ROM at %08lx\n", address);
-
- sig = le16_to_cpu(gsc_readw(address));
+ if (pdc_add_valid(address))
+ goto out_err;
- if((sig==0x55aa) || (sig==0xaa55)) {
- address += le32_to_cpu(gsc_readl(address+8));
- printk("sig %04x, PCI STI ROM at %08lx\n",
- sig, address);
+ sig = __raw_readl(address);
+
+ /* check for a PCI ROM structure */
+ if ((le32_to_cpu(sig)==0xaa55)) {
+ unsigned int i, rm_offset;
+ u32 *rm;
+ i = __raw_readl(address+0x04);
+ if (i != 1) {
+ /* The ROM could have multiple architecture
+ * dependent images (e.g. i386, parisc,...) */
+ printk(KERN_WARNING
+ "PCI ROM is not a STI ROM type image (0x%8x)\n", i);
+ goto out_err;
+ }
+
+ sti->pd = pd;
+
+ i = __raw_readl(address+0x0c);
+ DPRINTK(("PCI ROM size (from header) = %d kB\n",
+ le16_to_cpu(i>>16)*512/1024));
+ rm_offset = le16_to_cpu(i & 0xffff);
+ if (rm_offset) {
+ /* read 16 bytes from the pci region mapper array */
+ rm = (u32*) &sti->rm_entry;
+ *rm++ = __raw_readl(address+rm_offset+0x00);
+ *rm++ = __raw_readl(address+rm_offset+0x04);
+ *rm++ = __raw_readl(address+rm_offset+0x08);
+ *rm++ = __raw_readl(address+rm_offset+0x0c);
+ DPRINTK(("PCI region Mapper offset = %08x: ",
+ rm_offset));
+ for (i=0; i<16; i++)
+ DPRINTK(("%02x ", sti->rm_entry[i]));
+ DPRINTK(("\n"));
+ }
+ address += le32_to_cpu(__raw_readl(address+8));
+ DPRINTK(("sig %04x, PCI STI ROM at %08lx\n", sig, address));
goto test_rom;
}
-
- if((sig&0xff) == 0x01) {
- printk("STI byte mode ROM at %08lx, ignored\n",
- address);
-
- sti = NULL;
+
+ ok = 0;
+
+ if ((sig & 0xff) == 0x01) {
+ printk(KERN_INFO "STI byte mode ROM at %08lx, hpa at %08lx\n",
+ address, hpa);
+ ok = sti_read_rom(0, sti, address);
}
- if(sig == 0x0303) {
- printk("STI word mode ROM at %08lx\n",
- address);
-
- sti = sti_read_rom(address);
+ if ((sig & 0xffff) == 0x0303) {
+ printk(KERN_INFO "STI word mode ROM at %08lx, hpa at %08lx\n",
+ address, hpa);
+ ok = sti_read_rom(1, sti, address);
}
- if (!sti)
- return NULL;
+ if (!ok)
+ goto out_err;
- /* this is hacked. We need a better way to find out the HPA for
- * romless STI (eg search for the graphics devices we know about
- * by sversion) */
- if (!pdc_add_valid((void *)0xf5000000)) printk("f4000000 g\n");
- if (!pdc_add_valid((void *)0xf7000000)) printk("f6000000 g\n");
- if (!pdc_add_valid((void *)0xf9000000)) printk("f8000000 g\n");
- if (!pdc_add_valid((void *)0xfb000000)) printk("fa000000 g\n");
- sti_init_glob_cfg(sti, hpa, address);
+ if (sti_init_glob_cfg(sti, address, hpa))
+ goto out_err; /* not enough memory */
+
+ /* disable STI PCI ROM. ROM and card RAM overlap and
+ * leaving it enabled would force HPMCs
+ */
+ if (sti->pd) {
+ unsigned long rom_base;
+ rom_base = pci_resource_start(sti->pd, PCI_ROM_RESOURCE);
+ pci_write_config_dword(sti->pd, PCI_ROM_ADDRESS, rom_base & ~PCI_ROM_ADDRESS_ENABLE);
+ DPRINTK((KERN_DEBUG "STI PCI ROM disabled\n"));
+ }
- sti_init_graph(sti);
+ if (sti_init_graph(sti))
+ goto out_err;
sti_inq_conf(sti);
- sti_dump_globcfg(PTR_STI(sti->glob_cfg));
+ sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request);
+ sti_dump_outptr(sti);
+
+ printk(KERN_INFO "STI device: %s\n", sti->outptr.dev_name );
+ sti_roms[num_sti_roms] = sti;
+ num_sti_roms++;
+
return sti;
+
+out_err:
+ kfree(sti);
+ return NULL;
}
-static unsigned long sti_address;
-static unsigned long sti_hpa;
+static void __init sticore_check_for_default_sti (struct sti_struct *sti, char *path)
+{
+ if (strcmp (path, default_sti_path) == 0)
+ default_sti = sti;
+}
-/* XXX: should build a list of STI ROMs */
-struct sti_struct * __init
-sti_init_roms(void)
+/*
+ * on newer systems PDC gives the address of the ROM
+ * in the additional address field addr[1] while on
+ * older Systems the PDC stores it in page0->proc_sti
+ */
+static int __init sticore_pa_init(struct parisc_device *dev)
{
- struct sti_struct *tmp = NULL, *sti = NULL;
+ unsigned long rom = 0;
+ char pa_path[21];
+ struct sti_struct *sti = NULL;
+
+ if(dev->num_addrs) {
+ rom = dev->addr[0];
+ }
+ if (!rom) {
+ rom = dev->hpa;
+ DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
+ sti = sti_try_rom_generic(rom, dev->hpa, NULL);
+ rom = PAGE0->proc_sti;
+ }
+ if (!sti) {
+ DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
+ sti = sti_try_rom_generic(rom, dev->hpa, NULL);
+ }
+ if (!sti)
+ return 1;
+
+ print_pa_hwpath(dev, pa_path);
+ sticore_check_for_default_sti (sti, pa_path);
+ return 0;
+}
+
- /* handle the command line */
- if (sti_address && sti_hpa) {
- return sti_try_rom(sti_address, sti_hpa);
+static int __devinit sticore_pci_init(struct pci_dev *pd,
+ const struct pci_device_id *ent)
+{
+#ifdef CONFIG_PCI
+ unsigned long fb_base, rom_base;
+ unsigned int fb_len, rom_len;
+ struct sti_struct *sti;
+
+ pci_enable_device(pd);
+
+ fb_base = pci_resource_start(pd, 0);
+ fb_len = pci_resource_len(pd, 0);
+ rom_base = pci_resource_start(pd, PCI_ROM_RESOURCE);
+ rom_len = pci_resource_len(pd, PCI_ROM_RESOURCE);
+ if (rom_base) {
+ pci_write_config_dword(pd, PCI_ROM_ADDRESS, rom_base | PCI_ROM_ADDRESS_ENABLE);
+ DPRINTK((KERN_DEBUG "STI PCI ROM enabled at 0x%08lx\n", rom_base));
}
- /* 712, 715, some other boxes don't have a separate STI ROM,
- * but use part of the regular flash */
- if (PAGE0->proc_sti) {
- printk("STI ROM from PDC at %08x\n", PAGE0->proc_sti);
- if (!pdc_add_valid((void *)0xf9000000))
- sti = sti_try_rom(PAGE0->proc_sti, 0xf8000000);
- else if (!pdc_add_valid((void *)0xf5000000))
- sti = sti_try_rom(PAGE0->proc_sti, 0xf4000000);
- else if (!pdc_add_valid((void *)0xf7000000))
- sti = sti_try_rom(PAGE0->proc_sti, 0xf6000000);
- else if (!pdc_add_valid((void *)0xfb000000))
- sti = sti_try_rom(PAGE0->proc_sti, 0xfa000000);
+ printk(KERN_INFO "STI PCI graphic ROM found at %08lx (%u kB), fb at %08lx (%u MB)\n",
+ rom_base, rom_len/1024, fb_base, fb_len/1024/1024);
+
+ DPRINTK((KERN_DEBUG "Trying PCI STI ROM at %08lx, PCI hpa at %08lx\n",
+ rom_base, fb_base));
+ sti = sti_try_rom_generic(rom_base, fb_base, pd);
+ if (sti) {
+ char pa_path[30];
+ print_pci_hwpath(pd, pa_path);
+ sticore_check_for_default_sti(sti, pa_path);
}
+
+ if (!sti) {
+ printk(KERN_WARNING "Unable to handle STI device '%s'\n",
+ pd->dev.name);
+ return -ENODEV;
+ }
+#endif /* CONFIG_PCI */
+
+ return 0;
+}
- /* standard locations for GSC graphic devices */
- if (!pdc_add_valid((void *)0xf4000000))
- tmp = sti_try_rom(0xf4000000, 0xf4000000);
- sti = tmp ? tmp : sti;
- if (!pdc_add_valid((void *)0xf6000000))
- tmp = sti_try_rom(0xf6000000, 0xf6000000);
- sti = tmp ? tmp : sti;
- if (!pdc_add_valid((void *)0xf8000000))
- tmp = sti_try_rom(0xf8000000, 0xf8000000);
- sti = tmp ? tmp : sti;
- if (!pdc_add_valid((void *)0xfa000000))
- tmp = sti_try_rom(0xfa000000, 0xfa000000);
- sti = tmp ? tmp : sti;
- return sti;
+static void __devexit sticore_pci_remove(struct pci_dev *pd)
+{
+ BUG();
}
-static int __init
-sti_setup(char *str)
+
+#define PCI_DEVICE_ID_VISUALIZE_EG 0x1005
+#define PCI_DEVICE_ID_VISUALIZE_FX 0x1008
+#define PCI_DEVICE_ID_VISUALIZE_FX_NEW 0x108b
+
+static struct pci_device_id sti_pci_tbl[] __devinitdata = {
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_VISUALIZE_EG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_VISUALIZE_FX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_VISUALIZE_FX_NEW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0, } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, sti_pci_tbl);
+
+static struct pci_driver pci_sti_driver = {
+ .name = "sti (pci)",
+ .id_table = sti_pci_tbl,
+ .probe = sticore_pci_init,
+ .remove = sticore_pci_remove,
+};
+
+static struct parisc_device_id sti_pa_tbl[] = {
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00077 },
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00085 },
+ { 0, }
+};
+
+struct parisc_driver pa_sti_driver = {
+ .name = "sti (native)",
+ .id_table = sti_pa_tbl,
+ .probe = sticore_pa_init,
+};
+
+struct sti_struct * __init sti_init_roms(void)
{
- char *end;
+ static int initialized;
- if(strcmp(str, "pdc") == 0) {
- sti_address = PAGE0->proc_sti;
+ if (initialized)
+ goto out;
- return 1;
- } else {
- sti_address = simple_strtoul(str, &end, 16);
+ printk(KERN_INFO "STI GSC/PCI graphics driver version %s\n",
+ STI_DRIVERVERSION);
- if((end == str) || (sti_address < 0xf0000000)) {
- sti_address = 0;
- return 0;
- }
+ /* Register drivers for native & PCI cards */
+ register_parisc_driver(&pa_sti_driver);
+ pci_module_init (&pci_sti_driver);
- sti_hpa = sti_address;
+ /* if we didn't find the given default sti, take the first one */
+ if (!default_sti)
+ default_sti = sti_roms[0];
- return 1;
+out:
+ /* return default STI if available */
+ if (num_sti_roms && default_sti && default_sti->init_graph) {
+ initialized = 1;
+ return default_sti;
}
-
- return 0;
+ return NULL;
}
-__setup("sti=", sti_setup);
-
-MODULE_LICENSE("GPL");
+/*
+ * index = 0 gives default sti
+ * index > 0 gives other stis in detection order
+ */
+struct sti_struct * __init sti_get_rom(int index)
+{
+ int i;
+
+ if (index == 0)
+ return default_sti;
+
+ i = -1;
+ while (index > 0) {
+ i++;
+ if (i > num_sti_roms)
+ return NULL;
+ if (sti_roms[i] == default_sti)
+ continue;
+ index--;
+ }
+ return sti_roms[i];
+}
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 19031e2573f6..69bb72d5777a 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -22,6 +22,10 @@
* control.c: Console support for PowerMac "control" display adaptor.
* Copyright (C) 1996 Paul Mackerras
*
+ * Updated to 2.5 framebuffer API by Ben Herrenschmidt
+ * <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>,
+ * and James Simmons <jsimmons@infradead.org>.
+ *
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
@@ -50,12 +54,7 @@
#include <asm/pgtable.h>
#include <asm/btext.h>
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb32.h>
-#include <video/macmodes.h>
-
+#include "macmodes.h"
#include "controlfb.h"
struct fb_par_control {
@@ -97,7 +96,6 @@ static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninf
struct fb_info_control {
struct fb_info info;
- struct display display; /* Will disappear */
struct fb_par_control par;
u32 pseudo_palette[17];
@@ -119,14 +117,14 @@ struct fb_info_control {
};
/* control register access macro */
-#define CNTRL_REG(INFO,REG) (&(((INFO)->control_regs-> ## REG).r))
+#define CNTRL_REG(INFO,REG) (&(((INFO)->control_regs->REG).r))
/******************** Prototypes for exported functions ********************/
/*
* struct fb_ops
*/
-static int controlfb_pan_display(struct fb_var_screeninfo *var, int con,
+static int controlfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info);
static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
@@ -171,11 +169,8 @@ static int default_cmode __initdata = CMODE_NVRAM;
static struct fb_ops controlfb_ops = {
.owner = THIS_MODULE,
- .fb_set_var = gen_set_var,
.fb_check_var = controlfb_check_var,
.fb_set_par = controlfb_set_par,
- .fb_get_cmap = gen_get_cmap,
- .fb_set_cmap = gen_set_cmap,
.fb_setcolreg = controlfb_setcolreg,
.fb_pan_display = controlfb_pan_display,
.fb_blank = controlfb_blank,
@@ -265,8 +260,8 @@ static inline void set_screen_start(int xoffset, int yoffset,
}
-static int controlfb_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
+static int controlfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
unsigned int xoffset, hstep;
struct fb_info_control *p = (struct fb_info_control *)info;
@@ -483,7 +478,7 @@ try_again:
/* Apply default var */
p->info.var = var;
var.activate = FB_ACTIVATE_NOW;
- rc = gen_set_var(&var, -1, &p->info);
+ rc = fb_set_var(&var, &p->info);
if (rc && (vmode != VMODE_640_480_60 || cmode != CMODE_8))
goto try_again;
@@ -491,7 +486,7 @@ try_again:
if (register_framebuffer(&p->info) < 0)
return -ENXIO;
- printk(KERN_INFO "fb%d: control display adapter\n", GET_FB_IDX(p->info.node));
+ printk(KERN_INFO "fb%d: control display adapter\n", minor(p->info.node));
return 0;
}
@@ -1015,22 +1010,12 @@ static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeni
static void __init control_init_info(struct fb_info *info, struct fb_info_control *p)
{
/* Fill fb_info */
- strcpy(info->modename, "control");
- info->currcon = -1;
info->par = &p->par;
info->node = NODEV;
info->fbops = &controlfb_ops;
- info->disp = &p->display;
info->pseudo_palette = p->pseudo_palette;
info->flags = FBINFO_FLAG_DEFAULT;
- strncpy (info->fontname, fontname, sizeof (info->fontname));
- info->fontname[sizeof (info->fontname) - 1] = 0;
- info->changevar = NULL;
- info->display_fg = NULL;
info->screen_base = (char *) p->frame_buffer + CTRLFB_OFF;
- info->changevar = NULL;
- info->switch_con = gen_switch;
- info->updatevar = gen_update_var;
fb_alloc_cmap(&info->cmap, 256, 0);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 27dc6417cddd..4d677aacb0e4 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -41,6 +41,9 @@
#include <asm/pgtable.h>
#include <linux/fb.h>
+#define INCLUDE_LINUX_LOGO_DATA
+#include <asm/linux_logo.h>
+
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
#include "console/fbcon.h"
#endif
@@ -141,6 +144,8 @@ extern int pvr2fb_init(void);
extern int pvr2fb_setup(char*);
extern int sstfb_init(void);
extern int sstfb_setup(char*);
+extern int i810fb_init(void);
+extern int i810fb_setup(char*);
static struct {
const char *name;
@@ -155,11 +160,9 @@ static struct {
*/
{ "sbus", sbusfb_init, sbusfb_setup },
#endif
-
/*
* Chipset specific drivers that use resource management
*/
-
#ifdef CONFIG_FB_RETINAZ3
{ "retz3", retz3fb_init, retz3fb_setup },
#endif
@@ -235,6 +238,12 @@ static struct {
#ifdef CONFIG_FB_TRIDENT
{ "trident", tridentfb_init, tridentfb_setup },
#endif
+#ifdef CONFIG_FB_I810
+ { "i810fb", i810fb_init, i810fb_setup },
+#endif
+#ifdef CONFIG_FB_STI
+ { "stifb", stifb_init, stifb_setup },
+#endif
/*
* Generic drivers that are used as fallbacks
@@ -328,9 +337,6 @@ static struct {
#ifdef CONFIG_FB_VGA16
{ "vga16", vga16fb_init, vga16fb_setup },
#endif
-#ifdef CONFIG_FB_STI
- { "stifb", stifb_init, stifb_setup },
-#endif
#ifdef CONFIG_GSP_RESOLVER
/* Not a real frame buffer device... */
@@ -352,15 +358,264 @@ extern const char *global_mode_option;
static initcall_t pref_init_funcs[FB_MAX];
static int num_pref_init_funcs __initdata = 0;
-
-
struct fb_info *registered_fb[FB_MAX];
int num_registered_fb;
+static int nologo;
#ifdef CONFIG_FB_OF
static int ofonly __initdata = 0;
#endif
+#define LOGO_H 80
+#define LOGO_W 80
+
+static inline unsigned safe_shift(unsigned d, int n)
+{
+ return n < 0 ? d >> -n : d << n;
+}
+
+static void __init fb_set_logocmap(struct fb_info *info)
+{
+ struct fb_cmap palette_cmap;
+ u16 palette_green[16];
+ u16 palette_blue[16];
+ u16 palette_red[16];
+ int i, j, n;
+
+ palette_cmap.start = 0;
+ palette_cmap.len = 16;
+ palette_cmap.red = palette_red;
+ palette_cmap.green = palette_green;
+ palette_cmap.blue = palette_blue;
+
+ for (i = 0; i < LINUX_LOGO_COLORS; i += n) {
+ n = LINUX_LOGO_COLORS - i;
+ /* palette_cmap provides space for only 16 colors at once */
+ if (n > 16)
+ n = 16;
+ palette_cmap.start = 32 + i;
+ palette_cmap.len = n;
+ for (j = 0; j < n; ++j) {
+ palette_cmap.red[j] =
+ (linux_logo_red[i + j] << 8) |
+ linux_logo_red[i + j];
+ palette_cmap.green[j] =
+ (linux_logo_green[i + j] << 8) |
+ linux_logo_green[i + j];
+ palette_cmap.blue[j] =
+ (linux_logo_blue[i + j] << 8) |
+ linux_logo_blue[i + j];
+ }
+ fb_set_cmap(&palette_cmap, 1, info);
+ }
+}
+
+static void __init fb_set_logo_truepalette(struct fb_info *info, u32 *palette)
+{
+ unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
+ unsigned char redmask, greenmask, bluemask;
+ int redshift, greenshift, blueshift;
+ int i;
+
+ /*
+ * We have to create a temporary palette since console palette is only
+ * 16 colors long.
+ */
+ /* Bug: Doesn't obey msb_right ... (who needs that?) */
+ redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8];
+ greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
+ bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8];
+ redshift = info->var.red.offset - (8 - info->var.red.length);
+ greenshift = info->var.green.offset - (8 - info->var.green.length);
+ blueshift = info->var.blue.offset - (8 - info->var.blue.length);
+
+ for ( i = 0; i < LINUX_LOGO_COLORS; i++) {
+ palette[i+32] = (safe_shift((linux_logo_red[i] & redmask), redshift) |
+ safe_shift((linux_logo_green[i] & greenmask), greenshift) |
+ safe_shift((linux_logo_blue[i] & bluemask), blueshift));
+ }
+}
+
+static void __init fb_set_logo_directpalette(struct fb_info *info, u32 *palette)
+{
+ int redshift, greenshift, blueshift;
+ int i;
+
+ redshift = info->var.red.offset;
+ greenshift = info->var.green.offset;
+ blueshift = info->var.blue.offset;
+
+ for (i = 32; i < LINUX_LOGO_COLORS; i++)
+ palette[i] = i << redshift | i << greenshift | i << blueshift;
+}
+
+static void __init fb_set_logo(struct fb_info *info, u8 *logo, int needs_logo)
+{
+ int i, j;
+
+ switch (needs_logo) {
+ case 4:
+ for (i = 0; i < (LOGO_W * LOGO_H)/2; i++) {
+ logo[i*2] = linux_logo16[i] >> 4;
+ logo[(i*2)+1] = linux_logo16[i] & 0xf;
+ }
+ break;
+ case 1:
+ case ~1:
+ default:
+ for (i = 0; i < (LOGO_W * LOGO_H)/8; i++)
+ for (j = 0; j < 8; j++)
+ logo[i*8 + j] = (linux_logo_bw[i] & (7 - j)) ?
+ ((needs_logo == 1) ? 1 : 0) :
+ ((needs_logo == 1) ? 0 : 1);
+ break;
+ }
+}
+
+/*
+ * Three (3) kinds of logo maps exist. linux_logo (>16 colors), linux_logo_16
+ * (16 colors) and linux_logo_bw (2 colors). Depending on the visual format and
+ * color depth of the framebuffer, the DAC, the pseudo_palette, and the logo data
+ * will be adjusted accordingly.
+ *
+ * Case 1 - linux_logo:
+ * Color exceeds the number of console colors (16), thus we set the hardware DAC
+ * using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set.
+ *
+ * For visuals that require color info from the pseudo_palette, we also construct
+ * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
+ * will be set.
+ *
+ * Case 2 - linux_logo_16:
+ * The number of colors just matches the console colors, thus there is no need
+ * to set the DAC or the pseudo_palette. However, the bitmap is packed, ie,
+ * each byte contains color information for two pixels (upper and lower nibble).
+ * To be consistent with fb_imageblit() usage, we therefore separate the two
+ * nibbles into separate bytes. The "needs_logo" flag will be set to 4.
+ *
+ * Case 3 - linux_logo_bw:
+ * This is similar with Case 2. Each byte contains information for 8 pixels.
+ * We isolate each bit and expand each into a byte. The "needs_logo" flag will
+ * be set to 1.
+ */
+int fb_show_logo(struct fb_info *info)
+{
+ unsigned char *fb = info->screen_base, *logo_new = NULL;
+ u32 *palette = NULL, *saved_palette = NULL;
+ int needs_directpalette = 0;
+ int needs_truepalette = 0;
+ int needs_cmapreset = 0;
+ struct fb_image image;
+ int needs_logo = 0;
+ int done = 0, x;
+
+ /* Return if the frame buffer is not mapped */
+ if (!fb || !info->fbops->fb_imageblit)
+ return 0;
+
+ image.depth = info->var.bits_per_pixel;
+
+ /* reasonable default */
+ if (image.depth >= 8)
+ image.data = linux_logo;
+ else if (image.depth >= 4)
+ image.data = linux_logo16;
+ else
+ image.data = linux_logo_bw;
+
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ needs_truepalette = 1;
+ if (image.depth >= 4 && image.depth <= 8)
+ needs_logo = 4;
+ else if (image.depth < 4)
+ needs_logo = 1;
+ break;
+ case FB_VISUAL_DIRECTCOLOR:
+ if (image.depth >= 24) {
+ needs_directpalette = 1;
+ needs_cmapreset = 1;
+ }
+ /* 16 colors */
+ else if (image.depth >= 16)
+ needs_logo = 4;
+ /* 2 colors */
+ else
+ needs_logo = 1;
+ break;
+ case FB_VISUAL_MONO01:
+ /* reversed 0 = fg, 1 = bg */
+ needs_logo = ~1;
+ break;
+ case FB_VISUAL_MONO10:
+ needs_logo = 1;
+ break;
+ case FB_VISUAL_PSEUDOCOLOR:
+ default:
+ if (image.depth >= 8)
+ needs_cmapreset = 1;
+ /* fall through */
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ /* 16 colors */
+ if (image.depth >= 4 && image.depth < 8)
+ needs_logo = 4;
+ /* 2 colors */
+ else if (image.depth < 4)
+ needs_logo = 1;
+ break;
+ }
+
+ if (needs_cmapreset)
+ fb_set_logocmap(info);
+
+ if (needs_truepalette || needs_directpalette) {
+ palette = kmalloc(256 * 4, GFP_KERNEL);
+ if (palette == NULL)
+ return 1;
+
+ if (needs_truepalette)
+ fb_set_logo_truepalette(info, palette);
+ else
+ fb_set_logo_directpalette(info, palette);
+
+ saved_palette = info->pseudo_palette;
+ info->pseudo_palette = palette;
+ }
+
+ if (needs_logo) {
+ logo_new = kmalloc(LOGO_W * LOGO_H, GFP_KERNEL);
+ if (logo_new == NULL) {
+ if (palette)
+ kfree(palette);
+ if (saved_palette)
+ info->pseudo_palette = saved_palette;
+ return 1;
+ }
+
+ image.data = logo_new;
+ fb_set_logo(info, logo_new, needs_logo);
+ }
+
+ image.width = LOGO_W;
+ image.height = LOGO_H;
+ image.dy = 0;
+
+ for (x = 0; x < num_online_cpus() * (LOGO_W + 8) &&
+ x < info->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
+ image.dx = x;
+ info->fbops->fb_imageblit(info, &image);
+ done = 1;
+ }
+
+ if (palette != NULL)
+ kfree(palette);
+ if (saved_palette != NULL)
+ info->pseudo_palette = saved_palette;
+ if (logo_new != NULL)
+ kfree(logo_new);
+ return 0;
+}
+
static int fbmem_read_proc(char *buf, char **start, off_t offset,
int len, int *eof, void *private)
{
@@ -460,22 +715,19 @@ static void try_to_load(int fb)
}
#endif /* CONFIG_KMOD */
-int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+int
+fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
int xoffset = var->xoffset;
int yoffset = var->yoffset;
int err;
- if (xoffset < 0 || yoffset < 0 ||
+ if (xoffset < 0 || yoffset < 0 || !info->fbops->fb_pan_display ||
xoffset + info->var.xres > info->var.xres_virtual ||
yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
- if (info->fbops->fb_pan_display) {
- if ((err = info->fbops->fb_pan_display(var, info)))
- return err;
- else
- return -EINVAL;
- }
+ if ((err = info->fbops->fb_pan_display(var, info)))
+ return err;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
@@ -485,7 +737,8 @@ int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
return 0;
}
-int fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info)
+int
+fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
int err;
@@ -571,6 +824,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
return -EFAULT;
fb_copy_cmap(&info->cmap, &cmap, 0);
+ return 0;
case FBIOPAN_DISPLAY:
if (copy_from_user(&var, (void *) arg, sizeof(var)))
return -EFAULT;
@@ -704,6 +958,8 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
#elif defined(__sh__)
pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
+#elif defined(__hppa__)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
#elif defined(__ia64__)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
#else
@@ -737,6 +993,8 @@ fb_open(struct inode *inode, struct file *file)
if (res)
module_put(info->fbops->owner);
}
+ if (!nologo)
+ fb_show_logo(info);
return res;
}
@@ -878,46 +1136,49 @@ fbmem_init(void)
int __init video_setup(char *options)
{
- int i, j;
+ int i, j;
- if (!options || !*options)
- return 0;
+ if (!options || !*options)
+ return 0;
#ifdef CONFIG_FB_OF
- if (!strcmp(options, "ofonly")) {
- ofonly = 1;
- return 0;
- }
+ if (!strcmp(options, "ofonly")) {
+ ofonly = 1;
+ return 0;
+ }
#endif
- if (num_pref_init_funcs == FB_MAX)
- return 0;
+ if (!strcmp(options, "nologo"))
+ nologo = 1;
- for (i = 0; i < NUM_FB_DRIVERS; i++) {
- j = strlen(fb_drivers[i].name);
- if (!strncmp(options, fb_drivers[i].name, j) &&
- options[j] == ':') {
- if (!strcmp(options+j+1, "off"))
- fb_drivers[i].init = NULL;
- else {
- if (fb_drivers[i].init) {
- pref_init_funcs[num_pref_init_funcs++] =
- fb_drivers[i].init;
- fb_drivers[i].init = NULL;
- }
- if (fb_drivers[i].setup)
- fb_drivers[i].setup(options+j+1);
- }
- return 0;
- }
- }
+ if (num_pref_init_funcs == FB_MAX)
+ return 0;
- /*
- * If we get here no fb was specified.
- * We consider the argument to be a global video mode option.
- */
- global_mode_option = options;
- return 0;
+ for (i = 0; i < NUM_FB_DRIVERS; i++) {
+ j = strlen(fb_drivers[i].name);
+ if (!strncmp(options, fb_drivers[i].name, j) &&
+ options[j] == ':') {
+ if (!strcmp(options+j+1, "off"))
+ fb_drivers[i].init = NULL;
+ else {
+ if (fb_drivers[i].init) {
+ pref_init_funcs[num_pref_init_funcs++] =
+ fb_drivers[i].init;
+ fb_drivers[i].init = NULL;
+ }
+ if (fb_drivers[i].setup)
+ fb_drivers[i].setup(options+j+1);
+ }
+ return 0;
+ }
+ }
+
+ /*
+ * If we get here no fb was specified.
+ * We consider the argument to be a global video mode option.
+ */
+ global_mode_option = options;
+ return 0;
}
__setup("video=", video_setup);
@@ -928,7 +1189,10 @@ __setup("video=", video_setup);
EXPORT_SYMBOL(register_framebuffer);
EXPORT_SYMBOL(unregister_framebuffer);
-EXPORT_SYMBOL(registered_fb);
EXPORT_SYMBOL(num_registered_fb);
+EXPORT_SYMBOL(registered_fb);
+EXPORT_SYMBOL(fb_show_logo);
+EXPORT_SYMBOL(fb_set_var);
+EXPORT_SYMBOL(fb_blank);
MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 77a796109a99..c7b2077180c4 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -1,77 +1,295 @@
/*
* linux/drivers/video/fbmon.c
*
- * Copyright (C) 1999 James Simmons
+ * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*
- * Notes:
- * This code handles the different types of monitors that are out their.
- * Most video cards for example can support a mode like 800x600 but fix
- * frequency monitors can't. So the code here checks if the monitor can
- * support the mode as well as the card can. Fbmonospecs takes on
- * different meaning with different types of monitors. For multifrequency
- * monitors fbmonospecs represents the range of frequencies the monitor
- * can support. Only one fbmonospec needs to be allocated. The fbmonospecs
- * pointer in fb_info points to this one. If you specific a mode that has
- * timing greater than the allowed range then setting the video mode will
- * fail. With multifrequency monitors you can set any mode you like as long
- * as you have a programmable clock on the video card.
- * With fixed frequency monitors you have only a SET of very narrow
- * allowed frequency ranges. So for a fixed fequency monitor you have a
- * array of fbmonospecs. The fbmonospecs in fb_info represents the
- * monitor frequency for the CURRENT mode. If you change the mode and ask
- * for fbmonospecs you will NOT get the same values as before. Note this
- * is not true for multifrequency monitors where you do get the same
- * fbmonospecs each time. Also the values in each fbmonospecs represent the
- * very narrow frequency band for range. Well you can't have exactly the
- * same frequencies from fixed monitor. So some tolerance is excepted.
- * By DEFAULT all monitors are assumed fixed frequency since they are so
- * easy to fry or screw up a mode with. Just try setting a 800x600 mode on
- * one. After you boot you can run a simple program the tells what kind of
- * monitor you have. If you have a multifrequency monitor then you can set
- * any mode size you like as long as your video card has a programmable clock.
- * By default also besides assuming you have a fixed frequency monitor it
- * assumes the monitor only supports lower modes. This way for example you
- * can't set a 1280x1024 mode on a fixed frequency monitor that can only
- * support up to 1024x768.
- *
*/
#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/module.h>
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+
+/*
+ * EDID parser
+ *
+ * portions of this file were based on the EDID parser by
+ * John Fremlin <vii@users.sourceforge.net> and Ani Joshi <ajoshi@unixbox.com>
+ */
+
+#define EDID_LENGTH 0x80
+#define EDID_HEADER 0x00
+#define EDID_HEADER_END 0x07
+
+#define ID_MANUFACTURER_NAME 0x08
+#define ID_MANUFACTURER_NAME_END 0x09
+#define ID_MODEL 0x0a
+
+#define ID_SERIAL_NUMBER 0x0c
+
+#define MANUFACTURE_WEEK 0x10
+#define MANUFACTURE_YEAR 0x11
+
+#define EDID_STRUCT_VERSION 0x12
+#define EDID_STRUCT_REVISION 0x13
+
+#define DPMS_FLAGS 0x18
+#define ESTABLISHED_TIMING_1 0x23
+#define ESTABLISHED_TIMING_2 0x24
+#define MANUFACTURERS_TIMINGS 0x25
+
+#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
+#define DETAILED_TIMING_DESCRIPTION_SIZE 18
+#define NO_DETAILED_TIMING_DESCRIPTIONS 4
+
+#define DETAILED_TIMING_DESCRIPTION_1 0x36
+#define DETAILED_TIMING_DESCRIPTION_2 0x48
+#define DETAILED_TIMING_DESCRIPTION_3 0x5a
+#define DETAILED_TIMING_DESCRIPTION_4 0x6c
+
+#define DESCRIPTOR_DATA 5
+
+#define UPPER_NIBBLE( x ) \
+ (((128|64|32|16) & (x)) >> 4)
+
+#define LOWER_NIBBLE( x ) \
+ ((1|2|4|8) & (x))
+
+#define COMBINE_HI_8LO( hi, lo ) \
+ ( (((unsigned)hi) << 8) | (unsigned)lo )
+
+#define COMBINE_HI_4LO( hi, lo ) \
+ ( (((unsigned)hi) << 4) | (unsigned)lo )
+
+#define PIXEL_CLOCK_LO (unsigned)block[ 0 ]
+#define PIXEL_CLOCK_HI (unsigned)block[ 1 ]
+#define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*1000)
+#define H_ACTIVE_LO (unsigned)block[ 2 ]
+#define H_BLANKING_LO (unsigned)block[ 3 ]
+#define H_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_ACTIVE COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
+#define H_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_BLANKING COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
-int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
- const struct fb_info *fb_info)
+#define V_ACTIVE_LO (unsigned)block[ 5 ]
+#define V_BLANKING_LO (unsigned)block[ 6 ]
+#define V_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_ACTIVE COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
+#define V_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_BLANKING COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
+
+#define H_SYNC_OFFSET_LO (unsigned)block[ 8 ]
+#define H_SYNC_WIDTH_LO (unsigned)block[ 9 ]
+
+#define V_SYNC_OFFSET_LO UPPER_NIBBLE( (unsigned)block[ 10 ] )
+#define V_SYNC_WIDTH_LO LOWER_NIBBLE( (unsigned)block[ 10 ] )
+
+#define V_SYNC_WIDTH_HI ((unsigned)block[ 11 ] & (1|2))
+#define V_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (4|8)) >> 2)
+
+#define H_SYNC_WIDTH_HI (((unsigned)block[ 11 ] & (16|32)) >> 4)
+#define H_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (64|128)) >> 6)
+
+#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
+#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
+
+#define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
+#define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
+
+#define H_SIZE_LO (unsigned)block[ 12 ]
+#define V_SIZE_LO (unsigned)block[ 13 ]
+
+#define H_SIZE_HI UPPER_NIBBLE( (unsigned)block[ 14 ] )
+#define V_SIZE_HI LOWER_NIBBLE( (unsigned)block[ 14 ] )
+
+#define H_SIZE COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
+#define V_SIZE COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
+
+#define H_BORDER (unsigned)block[ 15 ]
+#define V_BORDER (unsigned)block[ 16 ]
+
+#define FLAGS (unsigned)block[ 17 ]
+
+#define INTERLACED (FLAGS&128)
+#define SYNC_TYPE (FLAGS&3<<3) /* bits 4,3 */
+#define SYNC_SEPARATE (3<<3)
+#define HSYNC_POSITIVE (FLAGS & 4)
+#define VSYNC_POSITIVE (FLAGS & 2)
+
+const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00
+};
+const unsigned char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
+
+static int edid_checksum(unsigned char *edid)
{
-#if 0
- /*
- * long long divisions .... $#%%#$
- */
- unsigned long long hpicos, vpicos;
- const unsigned long long _1e12 = 1000000000000ULL;
- const struct fb_monspecs *monspecs = &fb_info->monspecs;
-
- hpicos = (unsigned long long)htotal*(unsigned long long)pixclock;
- vpicos = (unsigned long long)vtotal*(unsigned long long)hpicos;
- if (!vpicos)
- return 0;
-
- if (monspecs->hfmin == 0)
- return 1;
-
- if (hpicos*monspecs->hfmin > _1e12 || hpicos*monspecs->hfmax < _1e12 ||
- vpicos*monspecs->vfmin > _1e12 || vpicos*monspecs->vfmax < _1e12)
- return 0;
-#endif
- return 1;
+ unsigned char i, csum = 0;
+
+ for (i = 0; i < EDID_LENGTH; i++)
+ csum += edid[i];
+
+ if (csum == 0x00) {
+ /* checksum passed, everything's good */
+ return 1;
+ } else {
+ printk("EDID checksum failed, aborting\n");
+ return 0;
+ }
}
-int fbmon_dpms(const struct fb_info *fb_info)
+static int edid_check_header(unsigned char *edid)
{
- return fb_info->monspecs.dpms;
+ if ((edid[0] != 0x00) || (edid[1] != 0xff) || (edid[2] != 0xff) ||
+ (edid[3] != 0xff) || (edid[4] != 0xff) || (edid[5] != 0xff) ||
+ (edid[6] != 0xff)) {
+ printk
+ ("EDID header doesn't match EDID v1 header, aborting\n");
+ return 0;
+ }
+ return 1;
}
-EXPORT_SYMBOL(fbmon_valid_timings);
+
+static char *edid_get_vendor(unsigned char *block)
+{
+ static char sign[4];
+ unsigned short h;
+
+ h = COMBINE_HI_8LO(block[0], block[1]);
+ sign[0] = ((h >> 10) & 0x1f) + 'A' - 1;
+ sign[1] = ((h >> 5) & 0x1f) + 'A' - 1;
+ sign[2] = (h & 0x1f) + 'A' - 1;
+ sign[3] = 0;
+
+ return sign;
+}
+
+static char *edid_get_monitor(unsigned char *block)
+{
+ static char name[13];
+ unsigned i;
+ const unsigned char *ptr = block + DESCRIPTOR_DATA;
+
+ for (i = 0; i < 13; i++, ptr++) {
+ if (*ptr == 0xa) {
+ name[i] = 0x00;
+ return name;
+ }
+ name[i] = *ptr;
+ }
+ return name;
+}
+
+static int edid_is_timing_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00))
+ return 0;
+ else
+ return 1;
+}
+
+static int edid_is_monitor_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) && (block[3] == 0xfc))
+ return 1;
+ else
+ return 0;
+}
+
+static void parse_timing_block(unsigned char *block,
+ struct fb_var_screeninfo *var)
+{
+ var->xres = var->xres_virtual = H_ACTIVE;
+ var->yres = var->yres_virtual = V_ACTIVE;
+ var->height = var->width = -1;
+ var->right_margin = H_SYNC_OFFSET;
+ var->left_margin = (H_ACTIVE + H_BLANKING) -
+ (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+ var->upper_margin = V_BLANKING - V_SYNC_OFFSET - V_SYNC_WIDTH;
+ var->lower_margin = V_SYNC_OFFSET;
+ var->hsync_len = H_SYNC_WIDTH;
+ var->vsync_len = V_SYNC_WIDTH;
+ var->pixclock = PIXEL_CLOCK;
+ var->pixclock /= 1000;
+ var->pixclock = KHZ2PICOS(var->pixclock);
+
+ if (HSYNC_POSITIVE)
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (VSYNC_POSITIVE)
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+}
+
+int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
+{
+ unsigned char *block, *vendor, *monitor = NULL;
+ int i;
+
+ if (!(edid_checksum(edid)))
+ return 0;
+
+ if (!(edid_check_header(edid)))
+ return 0;
+
+ printk("EDID ver %d rev %d\n", (int) edid[EDID_STRUCT_VERSION],
+ (int) edid[EDID_STRUCT_REVISION]);
+
+ vendor = edid_get_vendor(edid + ID_MANUFACTURER_NAME);
+
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+
+ for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+ if (edid_is_monitor_block(block)) {
+ monitor = edid_get_monitor(block);
+ }
+ }
+
+ printk("EDID: detected %s %s\n", vendor, monitor);
+
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+
+ for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+ if (edid_is_timing_block(block)) {
+ parse_timing_block(block, var);
+ }
+ }
+ return 1;
+}
+
+#ifdef CONFIG_PCI
+char *get_EDID(struct pci_dev *pdev)
+{
+#ifdef CONFIG_ALL_PPC
+ static char *propnames[] =
+ { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL };
+ unsigned char *pedid = NULL;
+ struct device_node *dp;
+ int i;
+
+ dp = pci_device_to_OF_node(pdev);
+ while (dp != NULL) {
+ for (i = 0; propnames[i] != NULL; ++i) {
+ pedid =
+ (unsigned char *) get_property(dp,
+ propnames[i],
+ NULL);
+ if (pedid != NULL)
+ return pedid;
+ }
+ dp = dp->child;
+ }
+ return pedid;
+#else
+ return NULL;
+#endif
+}
+#endif
+
+EXPORT_SYMBOL(parse_edid);
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(get_EDID);
+#endif
diff --git a/drivers/video/i810/Makefile b/drivers/video/i810/Makefile
new file mode 100644
index 000000000000..2cdcc59b3cff
--- /dev/null
+++ b/drivers/video/i810/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the Intel 810/815 framebuffer driver
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+
+obj-$(CONFIG_FB_I810) += i810fb.o
+
+
+i810fb-objs := i810_main.o i810_accel.o
+
+ifdef CONFIG_FB_I810_GTF
+i810fb-objs += i810_gtf.o
+else
+i810fb-objs += i810_dvt.o
+endif
+
+include $(TOPDIR)/Rules.make
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
new file mode 100644
index 000000000000..3a548d4fa5c6
--- /dev/null
+++ b/drivers/video/i810/i810.h
@@ -0,0 +1,300 @@
+/*-*- linux-c -*-
+ * linux/drivers/video/i810.h -- Intel 810 General Definitions/Declarations
+ *
+ * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef __I810_H__
+#define __I810_H__
+
+#include <linux/list.h>
+#include <linux/agp_backend.h>
+#include <linux/fb.h>
+#include <video/vga.h>
+
+/* Fence */
+#define TILEWALK_X (0 << 12)
+#define TILEWALK_Y (1 << 12)
+
+/* Raster ops */
+#define COLOR_COPY_ROP 0xF0
+#define PAT_COPY_ROP 0xCC
+#define CLEAR_ROP 0x00
+#define WHITE_ROP 0xFF
+#define INVERT_ROP 0x55
+#define XOR_ROP 0x5A
+
+/* 2D Engine definitions */
+#define SOLIDPATTERN 0x80000000
+#define NONSOLID 0x00000000
+#define BPP8 (0 << 24)
+#define BPP16 (1 << 24)
+#define BPP24 (2 << 24)
+
+#define PIXCONF8 (2 << 16)
+#define PIXCONF15 (4 << 16)
+#define PIXCONF16 (5 << 16)
+#define PIXCONF24 (6 << 16)
+#define PIXCONF32 (7 << 16)
+
+#define DYN_COLOR_EN (1 << 26)
+#define DYN_COLOR_DIS (0 << 26)
+#define INCREMENT 0x00000000
+#define DECREMENT (0x01 << 30)
+#define ARB_ON 0x00000001
+#define ARB_OFF 0x00000000
+#define SYNC_FLIP 0x00000000
+#define ASYNC_FLIP 0x00000040
+#define OPTYPE_MASK 0xE0000000
+#define PARSER_MASK 0x001F8000
+#define D2_MASK 0x001FC000 /* 2D mask */
+
+/* Instruction type */
+/* There are more but pertains to 3D */
+#define PARSER 0x00000000
+#define BLIT (0x02 << 29)
+#define RENDER (0x03 << 29)
+
+/* Parser */
+#define NOP 0x00 /* No operation, padding */
+#define BP_INT (0x01 << 23) /* Breakpoint interrupt */
+#define USR_INT (0x02 << 23) /* User interrupt */
+#define WAIT_FOR_EVNT (0x03 << 23) /* Wait for event */
+#define FLUSH (0x04 << 23)
+#define CONTEXT_SEL (0x05 << 23)
+#define REPORT_HEAD (0x07 << 23)
+#define ARB_ON_OFF (0x08 << 23)
+#define OVERLAY_FLIP (0x11 << 23)
+#define LOAD_SCAN_INC (0x12 << 23)
+#define LOAD_SCAN_EX (0x13 << 23)
+#define FRONT_BUFFER (0x14 << 23)
+#define DEST_BUFFER (0x15 << 23)
+#define Z_BUFFER (0x16 << 23)
+
+#define STORE_DWORD_IMM (0x20 << 23)
+#define STORE_DWORD_IDX (0x21 << 23)
+#define BATCH_BUFFER (0x30 << 23)
+
+/* Blit */
+#define SETUP_BLIT 0x00
+#define SETUP_MONO_PATTERN_SL_BLT (0x10 << 22)
+#define PIXEL_BLT (0x20 << 22)
+#define SCANLINE_BLT (0x21 << 22)
+#define TEXT_BLT (0x22 << 22)
+#define TEXT_IMM_BLT (0x30 << 22)
+#define COLOR_BLT (0x40 << 22)
+#define MONO_PAT_BLIT (0x42 << 22)
+#define SOURCE_COPY_BLIT (0x43 << 22)
+#define MONO_SOURCE_COPY_BLIT (0x44 << 22)
+#define SOURCE_COPY_IMMEDIATE (0x60 << 22)
+#define MONO_SOURCE_COPY_IMMEDIATE (0x61 << 22)
+
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 9
+#define VERSION_TEENIE 0
+#define BRANCH_VERSION ""
+
+
+/* mvo: intel i815 */
+#ifndef PCI_DEVICE_ID_INTEL_82815_100
+ #define PCI_DEVICE_ID_INTEL_82815_100 0x1102
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_82815_NOAGP
+ #define PCI_DEVICE_ID_INTEL_82815_NOAGP 0x1112
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_82815_FULL_CTRL
+ #define PCI_DEVICE_ID_INTEL_82815_FULL_CTRL 0x1130
+#endif
+
+/* General Defines */
+#define I810_PAGESIZE 4096
+#define MAX_DMA_SIZE (1024 * 4096)
+#define SAREA_SIZE 4096
+#define PCI_I810_MISCC 0x72
+#define MMIO_SIZE (512*1024)
+#define GTT_SIZE (16*1024)
+#define RINGBUFFER_SIZE (64*1024)
+#define PIXMAP_SIZE (4 * 4096)
+#define CURSOR_SIZE 4096
+#define OFF 0
+#define ON 1
+#define MAX_KEY 256
+#define WAIT_COUNT 10000000
+#define IRING_PAD 8
+#define FONTDATAMAX 8192
+/* Masks (AND ops) and OR's */
+#define FB_START_MASK (0x3f << (32 - 6))
+#define MMIO_ADDR_MASK (0x1FFF << (32 - 13))
+#define FREQ_MASK 0x1EF
+#define SCR_OFF 0x20
+#define DRAM_ON 0x08
+#define DRAM_OFF 0xE7
+#define PG_ENABLE_MASK 0x01
+#define RING_SIZE_MASK (RINGBUFFER_SIZE - 1);
+
+/* defines for restoring registers partially */
+#define ADDR_MAP_MASK (0x07 << 5)
+#define DISP_CTRL ~0
+#define PIXCONF_0 (0x64 << 8)
+#define PIXCONF_2 (0xF3 << 24)
+#define PIXCONF_1 (0xF0 << 16)
+#define MN_MASK 0x3FF03FF
+#define P_OR (0x7 << 4)
+#define DAC_BIT (1 << 16)
+#define INTERLACE_BIT (1 << 7)
+#define IER_MASK (3 << 13)
+#define IMR_MASK (3 << 13)
+
+/* Power Management */
+#define DPMS_MASK 0xF0000
+#define POWERON 0x00000
+#define STANDBY 0x20000
+#define SUSPEND 0x80000
+#define POWERDOWN 0xA0000
+#define EMR_MASK ~0x3F
+#define FW_BLC_MASK ~(0x3F|(7 << 8)|(0x3F << 12)|(7 << 20))
+
+/* Ringbuffer */
+#define RBUFFER_START_MASK 0xFFFFF000
+#define RBUFFER_SIZE_MASK 0x001FF000
+#define RBUFFER_HEAD_MASK 0x001FFFFC
+#define RBUFFER_TAIL_MASK 0x001FFFF8
+
+/* Video Timings */
+#define REF_FREQ 24000000
+#define TARGET_N_MAX 30
+
+#define FLYBACK 550
+#define V_FRONTPORCH 1
+#define H_OFFSET 40
+#define H_SCALEFACTOR 20
+#define H_BLANKSCALE 128
+#define H_GRADIENT 600
+
+#define MAX_PIXELCLOCK 230000000
+#define MIN_PIXELCLOCK 15000000
+#define VFMAX 60
+#define VFMIN 60
+#define HFMAX 30000
+#define HFMIN 29000
+
+/* Cursor */
+#define CURSOR_ENABLE_MASK 0x1000
+#define CURSOR_MODE_64_TRANS 4
+#define CURSOR_MODE_64_XOR 5
+#define CURSOR_MODE_64_3C 6
+#define COORD_INACTIVE 0
+#define COORD_ACTIVE (1 << 4)
+#define EXTENDED_PALETTE 1
+
+/* AGP Memory Types*/
+#define AGP_NORMAL_MEMORY 0
+#define AGP_DCACHE_MEMORY 1
+#define AGP_PHYSICAL_MEMORY 2
+
+/* Allocated resource Flags */
+#define FRAMEBUFFER_REQ 1
+#define MMIO_REQ 2
+#define PCI_DEVICE_ENABLED 4
+#define HAS_FONTCACHE 8
+
+/* driver flags */
+#define HAS_MTRR 1
+#define HAS_ACCELERATION 2
+#define ALWAYS_SYNC 4
+#define LOCKUP 8
+
+struct gtt_data {
+ agp_memory *i810_fb_memory;
+ agp_memory *i810_iring_memory;
+ agp_memory *i810_cursor_memory;
+ agp_memory *i810_pixmap_memory;
+};
+
+struct mode_registers {
+ u32 pixclock, M, N, P;
+ u8 cr00, cr01, cr02, cr03;
+ u8 cr04, cr05, cr06, cr07;
+ u8 cr09, cr10, cr11, cr12;
+ u8 cr13, cr15, cr16, cr30;
+ u8 cr31, cr32, cr33, cr35, cr39;
+ u32 bpp8_100, bpp16_100;
+ u32 bpp24_100, bpp8_133;
+ u32 bpp16_133, bpp24_133;
+ u8 msr;
+};
+
+struct heap_data {
+ unsigned long physical;
+ __u8 *virtual;
+ u32 offset;
+ u32 size;
+};
+
+struct state_registers {
+ u32 dclk_1d, dclk_2d, dclk_0ds;
+ u32 pixconf, fw_blc, pgtbl_ctl;
+ u32 fence0, hws_pga, dplystas;
+ u16 bltcntl, hwstam, ier, iir, imr;
+ u8 cr00, cr01, cr02, cr03, cr04;
+ u8 cr05, cr06, cr07, cr08, cr09;
+ u8 cr10, cr11, cr12, cr13, cr14;
+ u8 cr15, cr16, cr17, cr80, gr10;
+ u8 cr30, cr31, cr32, cr33, cr35;
+ u8 cr39, cr41, cr70, sr01, msr;
+};
+
+struct i810fb_par {
+ struct mode_registers regs;
+ struct state_registers hw_state;
+ struct gtt_data i810_gtt;
+ struct fb_ops i810fb_ops;
+ struct pci_dev *dev;
+ struct heap_data aperture;
+ struct heap_data fb;
+ struct heap_data iring;
+ struct heap_data cursor_heap;
+ struct heap_data pixmap;
+ struct vgastate state;
+ drm_agp_t *drm_agp;
+ atomic_t use_count;
+ u32 pseudo_palette[17];
+ unsigned long mmio_start_phys;
+ u8 *mmio_start_virtual;
+ u32 cursor_reset;
+ u8 red[64];
+ u8 green[64];
+ u8 blue[64];
+ u32 pixmap_offset;
+ u32 pitch;
+ u32 pixconf;
+ u32 watermark;
+ u32 mem_freq;
+ u32 res_flags;
+ u32 dev_flags;
+ u32 cur_tail;
+ u32 depth;
+ u32 blit_bpp;
+ u32 ovract;
+ int mtrr_reg;
+ u16 bltcntl;
+ u8 interlace;
+};
+
+/*
+ * Register I/O
+ */
+#define i810_readb(where, mmio) readb(mmio + where)
+#define i810_readw(where, mmio) readw(mmio + where)
+#define i810_readl(where, mmio) readl(mmio + where)
+#define i810_writeb(where, mmio, val) writeb(val, mmio + where)
+#define i810_writew(where, mmio, val) writew(val, mmio + where)
+#define i810_writel(where, mmio, val) writel(val, mmio + where)
+
+#endif /* __I810_H__ */
diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c
new file mode 100644
index 000000000000..95fb0600b9e1
--- /dev/null
+++ b/drivers/video/i810/i810_accel.c
@@ -0,0 +1,513 @@
+/*-*- linux-c -*-
+ * linux/drivers/video/i810_accel.c -- Hardware Acceleration
+ *
+ * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+#include <linux/kernel.h>
+#include <linux/fb.h>
+
+#include "i810_regs.h"
+#include "i810.h"
+
+static u32 i810fb_rop[] = {
+ COLOR_COPY_ROP, /* ROP_COPY */
+ XOR_ROP /* ROP_XOR */
+};
+
+/* Macros */
+#define PUT_RING(n) { \
+ i810_writel(par->cur_tail, par->iring.virtual, n); \
+ par->cur_tail += 4; \
+ par->cur_tail &= RING_SIZE_MASK; \
+}
+
+extern inline void flush_cache(void);
+extern int reinit_agp(struct fb_info *info);
+
+/************************************************************/
+
+/* BLT Engine Routines */
+static inline void i810_report_error(u8 *mmio)
+{
+ printk("IIR : 0x%04x\n"
+ "EIR : 0x%04x\n"
+ "PGTBL_ER: 0x%04x\n"
+ "IPEIR : 0x%04x\n"
+ "IPEHR : 0x%04x\n",
+ i810_readw(IIR, mmio),
+ i810_readb(EIR, mmio),
+ i810_readl(PGTBL_ER, mmio),
+ i810_readl(IPEIR, mmio),
+ i810_readl(IPEHR, mmio));
+}
+
+/**
+ * wait_for_space - check ring buffer free space
+ * @space: amount of ringbuffer space needed in bytes
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * The function waits until a free space from the ringbuffer
+ * is available
+ */
+static inline int wait_for_space(struct i810fb_par *par, u32 space)
+{
+ u32 head, count = WAIT_COUNT, tail;
+ u8 *mmio = par->mmio_start_virtual;
+
+ tail = par->cur_tail;
+ while (count--) {
+ head = i810_readl(IRING + 4, mmio) & RBUFFER_HEAD_MASK;
+ if ((tail == head) ||
+ (tail > head &&
+ (par->iring.size - tail + head) >= space) ||
+ (tail < head && (head - tail) >= space)) {
+ return 0;
+ }
+ }
+ printk("ringbuffer lockup!!!\n");
+ i810_report_error(mmio);
+ par->dev_flags |= LOCKUP;
+ return 1;
+}
+
+
+
+/**
+ * wait_for_engine_idle - waits for all hardware engines to finish
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * This waits for lring(0), iring(1), and batch(3), etc to finish and
+ * waits until ringbuffer is empty.
+ */
+static inline int wait_for_engine_idle(struct i810fb_par *par)
+{
+ u8 *mmio = par->mmio_start_virtual;
+ int count = WAIT_COUNT;
+
+ while((i810_readw(INSTDONE, mmio) & 0x7B) != 0x7B && --count);
+ if (count) return 0;
+
+ printk("accel engine lockup!!!\n");
+ printk("INSTDONE: 0x%04x\n", i810_readl(INSTDONE, mmio));
+ i810_report_error(mmio);
+ par->dev_flags |= LOCKUP;
+ return 1;
+}
+
+/* begin_iring - prepares the ringbuffer
+ * @space: length of sequence in dwords
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Checks/waits for sufficent space in ringbuffer of size
+ * space. Returns the tail of the buffer
+ */
+static inline u32 begin_iring(struct i810fb_par *par, u32 space)
+{
+ if (par->dev_flags & ALWAYS_SYNC)
+ wait_for_engine_idle(par);
+ return wait_for_space(par, space);
+}
+
+/**
+ * end_iring - advances the buffer
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * This advances the tail of the ringbuffer, effectively
+ * beginning the execution of the graphics instruction sequence.
+ */
+static inline void end_iring(struct i810fb_par *par)
+{
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writel(IRING, mmio, par->cur_tail);
+}
+
+/**
+ * source_copy_blit - BLIT transfer operation
+ * @dwidth: width of rectangular graphics data
+ * @dheight: height of rectangular graphics data
+ * @dpitch: bytes per line of destination buffer
+ * @xdir: direction of copy (left to right or right to left)
+ * @src: address of first pixel to read from
+ * @dest: address of first pixel to write to
+ * @from: source address
+ * @where: destination address
+ * @rop: raster operation
+ * @blit_bpp: pixel format which can be different from the
+ * framebuffer's pixelformat
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * This is a BLIT operation typically used when doing
+ * a 'Copy and Paste'
+ */
+static inline void source_copy_blit(int dwidth, int dheight, int dpitch,
+ int xdir, int src, int dest, int rop,
+ int blit_bpp, struct i810fb_par *par)
+{
+ if (begin_iring(par, 24 + IRING_PAD)) return;
+ PUT_RING(BLIT | SOURCE_COPY_BLIT | 4);
+ PUT_RING(xdir | rop << 16 | dpitch | DYN_COLOR_EN | blit_bpp);
+ PUT_RING(dheight << 16 | dwidth);
+ PUT_RING(dest);
+ PUT_RING(dpitch);
+ PUT_RING(src);
+ end_iring(par);
+}
+
+/**
+ * color_blit - solid color BLIT operation
+ * @width: width of destination
+ * @height: height of destination
+ * @pitch: pixels per line of the buffer
+ * @dest: address of first pixel to write to
+ * @where: destination
+ * @rop: raster operation
+ * @what: color to transfer
+ * @blit_bpp: pixel format which can be different from the
+ * framebuffer's pixelformat
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * A BLIT operation which can be used for color fill/rectangular fill
+ */
+static inline void color_blit(int width, int height, int pitch, int dest,
+ int rop, int what, int blit_bpp,
+ struct i810fb_par *par)
+{
+ if (begin_iring(par, 24 + IRING_PAD)) return;
+ PUT_RING(BLIT | COLOR_BLT | 3);
+ PUT_RING(rop << 16 | pitch | SOLIDPATTERN | DYN_COLOR_EN | blit_bpp);
+ PUT_RING(height << 16 | width);
+ PUT_RING(dest);
+ PUT_RING(what);
+ PUT_RING(NOP);
+ end_iring(par);
+}
+
+/**
+ * mono_src_copy_imm_blit - color expand from system memory to framebuffer
+ * @dwidth: width of destination
+ * @dheight: height of destination
+ * @dpitch: pixels per line of the buffer
+ * @dsize: size of bitmap in double words
+ * @dest: address of first byte of pixel;
+ * @rop: raster operation
+ * @blit_bpp: pixelformat to use which can be different from the
+ * framebuffer's pixelformat
+ * @src: address of image data
+ * @bg: backgound color
+ * @fg: forground color
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * A color expand operation where the source data is placed in the
+ * ringbuffer itself. Useful for drawing text.
+ *
+ * REQUIREMENT:
+ * The end of a scanline must be padded to the next word.
+ */
+static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
+ int dsize, int blit_bpp, int rop,
+ int dest, const u32 *src, int bg,
+ int fg, struct i810fb_par *par)
+{
+ u32 i, *s = (u32 *) src;
+
+ if (begin_iring(par, 24 + (dsize << 2) + IRING_PAD)) return;
+ PUT_RING(BLIT | MONO_SOURCE_COPY_IMMEDIATE | (4 + dsize));
+ PUT_RING(DYN_COLOR_EN | blit_bpp | rop << 16 | dpitch);
+ PUT_RING(dheight << 16 | dwidth);
+ PUT_RING(dest);
+ PUT_RING(bg);
+ PUT_RING(fg);
+ for (i = dsize; i--; )
+ PUT_RING(*s++);
+
+ end_iring(par);
+}
+
+/**
+ * mono_src_copy_blit - color expand from video memory to framebuffer
+ * @dwidth: width of destination
+ * @dheight: height of destination
+ * @dpitch: pixels per line of the buffer
+ * @qsize: size of bitmap in quad words
+ * @dest: address of first byte of pixel;
+ * @rop: raster operation
+ * @blit_bpp: pixelformat to use which can be different from the
+ * framebuffer's pixelformat
+ * @src: address of image data
+ * @bg: backgound color
+ * @fg: forground color
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * A color expand operation where the source data is in video memory.
+ * Useful for drawing text.
+ *
+ * REQUIREMENT:
+ * The end of a scanline must be padded to the next word.
+ */
+static inline void mono_src_copy_blit(int dwidth, int dheight, int dpitch,
+ int qsize, int blit_bpp, int rop,
+ int dest, int src, int bg,
+ int fg, struct i810fb_par *par)
+{
+ if (begin_iring(par, 32 + IRING_PAD)) return;
+
+ PUT_RING(BLIT | MONO_SOURCE_COPY_BLIT | 6);
+ PUT_RING(DYN_COLOR_EN | blit_bpp | rop << 16 | dpitch | 1 << 27);
+ PUT_RING(dheight << 16 | dwidth);
+ PUT_RING(dest);
+ PUT_RING(qsize - 1);
+ PUT_RING(src);
+ PUT_RING(bg);
+ PUT_RING(fg);
+
+ end_iring(par);
+}
+
+static u32 get_buffer_offset(u32 size, struct i810fb_par *par)
+{
+ u32 offset;
+
+ if (par->pixmap_offset + size > par->pixmap.size) {
+ wait_for_engine_idle(par);
+ par->pixmap_offset = 0;
+ }
+
+ offset = par->pixmap_offset;
+ par->pixmap_offset += size;
+
+ return offset;
+}
+
+/**
+ * i810fb_iring_enable - enables/disables the ringbuffer
+ * @mode: enable or disable
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Enables or disables the ringbuffer, effectively enabling or
+ * disabling the instruction/acceleration engine.
+ */
+static inline void i810fb_iring_enable(struct i810fb_par *par, u32 mode)
+{
+ u32 tmp;
+ u8 *mmio = par->mmio_start_virtual;
+
+ tmp = i810_readl(IRING + 12, mmio);
+ if (mode == OFF)
+ tmp &= ~1;
+ else
+ tmp |= 1;
+ flush_cache();
+ i810_writel(IRING + 12, mmio, tmp);
+}
+
+void i810fb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
+{
+ struct i810fb_par *par = (struct i810fb_par *) p->par;
+ u32 dx, dy, width, height, dest, rop = 0, color = 0;
+
+ if (!p->var.accel_flags || par->dev_flags & LOCKUP) {
+ cfb_fillrect(p, rect);
+ return;
+ }
+
+ if (par->depth == 4) {
+ wait_for_engine_idle(par);
+ cfb_fillrect(p, rect);
+ return;
+ }
+
+ if (par->depth == 1)
+ color = rect->color;
+ else
+ color = ((u32 *) (p->pseudo_palette))[rect->color];
+
+ rop = i810fb_rop[rect->rop];
+
+ dx = rect->dx * par->depth;
+ width = rect->width * par->depth;
+ dy = rect->dy;
+ height = rect->height;
+
+ dest = p->fix.smem_start + (dy * p->fix.line_length) + dx;
+ color_blit(width, height, p->fix.line_length, dest, rop, color,
+ par->blit_bpp, par);
+}
+
+void i810fb_copyarea(struct fb_info *p, struct fb_copyarea *region)
+{
+ struct i810fb_par *par = (struct i810fb_par *) p->par;
+ u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir;
+
+ if (!p->var.accel_flags || par->dev_flags & LOCKUP) {
+ cfb_copyarea(p, region);
+ return;
+ }
+
+ if (par->depth == 4) {
+ wait_for_engine_idle(par);
+ cfb_copyarea(p, region);
+ return;
+ }
+
+ dx = region->dx * par->depth;
+ sx = region->sx * par->depth;
+ width = region->width * par->depth;
+ sy = region->sy;
+ dy = region->dy;
+ height = region->height;
+
+ if (dx <= sx) {
+ xdir = INCREMENT;
+ }
+ else {
+ xdir = DECREMENT;
+ sx += width - 1;
+ dx += width - 1;
+ }
+ if (dy <= sy) {
+ pitch = p->fix.line_length;
+ }
+ else {
+ pitch = (-(p->fix.line_length)) & 0xFFFF;
+ sy += height - 1;
+ dy += height - 1;
+ }
+ src = p->fix.smem_start + (sy * p->fix.line_length) + sx;
+ dest = p->fix.smem_start + (dy * p->fix.line_length) + dx;
+
+ source_copy_blit(width, height, pitch, xdir, src, dest,
+ PAT_COPY_ROP, par->blit_bpp, par);
+}
+
+/*
+ * Blitting is done at 8x8 pixel-array at a time. If map is not
+ * monochrome or not a multiple of 8x8 pixels, cfb_imageblit will
+ * be called instead.
+ */
+void i810fb_imageblit(struct fb_info *p, struct fb_image *image)
+{
+ struct i810fb_par *par = (struct i810fb_par *) p->par;
+ u32 fg = 0, bg = 0, s_pitch, d_pitch, size, offset, dst, i, j;
+ u8 *s_addr, *d_addr;
+
+ if (!p->var.accel_flags || par->dev_flags & LOCKUP) {
+ cfb_imageblit(p, image);
+ return;
+ }
+
+ if (par->depth == 4 || image->depth != 1) {
+ wait_for_engine_idle(par);
+ cfb_imageblit(p, image);
+ return;
+ }
+
+ switch (p->var.bits_per_pixel) {
+ case 8:
+ fg = image->fg_color;
+ bg = image->bg_color;
+ break;
+ case 16:
+ fg = ((u32 *)(p->pseudo_palette))[image->fg_color];
+ bg = ((u32 *)(p->pseudo_palette))[image->bg_color];
+ break;
+ case 24:
+ fg = ((u32 *)(p->pseudo_palette))[image->fg_color];
+ bg = ((u32 *)(p->pseudo_palette))[image->bg_color];
+ break;
+ }
+
+ dst = p->fix.smem_start + (image->dy * p->fix.line_length) +
+ (image->dx * par->depth);
+
+ s_pitch = image->width/8;
+ d_pitch = (s_pitch + 1) & ~1;
+
+ size = d_pitch * image->height;
+
+ if (image->width & 15) {
+ offset = get_buffer_offset(size, par);
+
+ d_addr = par->pixmap.virtual + offset;
+ s_addr = image->data;
+
+ for (i = image->height; i--; ) {
+ for (j = 0; j < s_pitch; j++)
+ i810_writeb(j, d_addr, s_addr[j]);
+ s_addr += s_pitch;
+ d_addr += d_pitch;
+ }
+
+ mono_src_copy_blit(image->width * par->depth, image->height,
+ p->fix.line_length, size/8, par->blit_bpp,
+ PAT_COPY_ROP, dst,
+ par->pixmap.physical + offset,
+ bg, fg, par);
+ }
+ /*
+ * immediate blit if width is a multiple of 16 (hardware requirement)
+ */
+ else {
+ mono_src_copy_imm_blit(image->width * par->depth,
+ image->height, p->fix.line_length,
+ size/4, par->blit_bpp,
+ PAT_COPY_ROP, dst, (u32 *) image->data,
+ bg, fg, par);
+ }
+}
+
+int i810fb_sync(struct fb_info *p)
+{
+ struct i810fb_par *par = (struct i810fb_par *) p->par;
+
+ if (!p->var.accel_flags)
+ return 0;
+
+ return wait_for_engine_idle(par);
+}
+
+
+/**
+ * i810fb_init_ringbuffer - initialize the ringbuffer
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Initializes the ringbuffer by telling the device the
+ * size and location of the ringbuffer. It also sets
+ * the head and tail pointers = 0
+ */
+void i810fb_init_ringbuffer(struct i810fb_par *par)
+{
+ u32 tmp1, tmp2;
+ u8 *mmio = par->mmio_start_virtual;
+
+ wait_for_engine_idle(par);
+ i810fb_iring_enable(par, OFF);
+ i810_writel(IRING, mmio, 0);
+ i810_writel(IRING + 4, mmio, 0);
+ par->cur_tail = 0;
+
+ tmp2 = i810_readl(IRING + 8, mmio) & ~RBUFFER_START_MASK;
+ tmp1 = par->iring.physical;
+ i810_writel(IRING + 8, mmio, tmp2 | tmp1);
+
+ tmp1 = i810_readl(IRING + 12, mmio);
+ tmp1 &= ~RBUFFER_SIZE_MASK;
+ tmp2 = (par->iring.size - I810_PAGESIZE) & RBUFFER_SIZE_MASK;
+ i810_writel(IRING + 12, mmio, tmp1 | tmp2);
+ i810fb_iring_enable(par, ON);
+}
diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/i810/i810_dvt.c
new file mode 100644
index 000000000000..ad417bb698e8
--- /dev/null
+++ b/drivers/video/i810/i810_dvt.c
@@ -0,0 +1,308 @@
+/*-*- linux-c -*-
+ * linux/drivers/video/i810_dvt.c -- Intel 810 Discrete Video Timings (Intel)
+ *
+ * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/kernel.h>
+
+#include "i810_regs.h"
+#include "i810.h"
+
+struct mode_registers std_modes[] = {
+ /* 640x480 @ 60Hz */
+ { 25000, 0x0013, 0x0003, 0x40, 0x5F, 0x4F, 0x50, 0x82, 0x51, 0x9D,
+ 0x0B, 0x10, 0x40, 0xE9, 0x0B, 0xDF, 0x50, 0xE7, 0x04, 0x02,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x22002000, 0x22004000, 0x22006000,
+ 0x22002000, 0x22004000, 0x22006000, 0xC0 },
+
+ /* 640x480 @ 70Hz */
+ { 28000, 0x0053, 0x0010, 0x40, 0x61, 0x4F, 0x4F, 0x85, 0x52, 0x9A,
+ 0xF2, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xF3, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x22002000, 0x22004000, 0x22005000,
+ 0x22002000, 0x22004000, 0x22005000, 0xC0 },
+
+ /* 640x480 @ 72Hz */
+ { 31000, 0x0013, 0x0002, 0x40, 0x63, 0x4F, 0x4F, 0x87, 0x52, 0x97,
+ 0x06, 0x0F, 0x40, 0xE8, 0x0B, 0xDF, 0x50, 0xDF, 0x07, 0x02,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22007000,
+ 0x22003000, 0x22005000, 0x22007000, 0xC0 },
+
+ /* 640x480 @ 75Hz */
+ { 31000, 0x0013, 0x0002, 0x40, 0x64, 0x4F, 0x4F, 0x88, 0x51, 0x99,
+ 0xF2, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xF3, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22007000,
+ 0x22003000, 0x22005000, 0x22007000, 0xC0 },
+
+ /* 640x480 @ 85Hz */
+ { 36000, 0x0010, 0x0001, 0x40, 0x63, 0x4F, 0x4F, 0x87, 0x56, 0x9D,
+ 0xFB, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xFC, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22107000,
+ 0x22003000, 0x22005000, 0x22107000, 0xC0 },
+
+ /* 800x600 @ 56Hz */
+ { 36000, 0x0010, 0x0001, 0x40, 0x7B, 0x63, 0x63, 0x9F, 0x66, 0x8F,
+ 0x6F, 0x10, 0x40, 0x58, 0x0A, 0x57, 0xC8, 0x57, 0x70, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x22003000, 0x22005000, 0x22107000,
+ 0x22003000, 0x22005000, 0x22107000, 0x00 },
+
+ /* 800x600 @ 60Hz */
+ { 40000, 0x0008, 0x0001, 0x30, 0x7F, 0x63, 0x63, 0x83, 0x68, 0x18,
+ 0x72, 0x10, 0x40, 0x58, 0x0C, 0x57, 0xC8, 0x57, 0x73, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x22003000, 0x22006000, 0x22108000,
+ 0x22003000, 0x22006000, 0x22108000, 0x00 },
+
+ /* 800x600 @ 70Hz */
+ { 45000, 0x0054, 0x0015, 0x30, 0x7D, 0x63, 0x63, 0x81, 0x68, 0x12,
+ 0x6f, 0x10, 0x40, 0x58, 0x0b, 0x57, 0x64, 0x57, 0x70, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210A000,
+ 0x22004000, 0x22007000, 0x2210A000, 0x00 },
+
+ /* 800x600 @ 72Hz */
+ { 50000, 0x0017, 0x0004, 0x30, 0x7D, 0x63, 0x63, 0x81, 0x6A, 0x19,
+ 0x98, 0x10, 0x40, 0x7C, 0x02, 0x57, 0xC8, 0x57, 0x99, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210A000,
+ 0x22004000, 0x22007000, 0x2210A000, 0x00 },
+
+ /* 800x600 @ 75Hz */
+ { 49000, 0x001F, 0x0006, 0x30, 0x7F, 0x63, 0x63, 0x83, 0x65, 0x0F,
+ 0x6F, 0x10, 0x40, 0x58, 0x0B, 0x57, 0xC8, 0x57, 0x70, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210B000,
+ 0x22004000, 0x22007000, 0x2210B000, 0x00 },
+
+ /* 800x600 @ 85Hz */
+ { 56000, 0x0049, 0x000E, 0x30, 0x7E, 0x63, 0x63, 0x82, 0x67, 0x0F,
+ 0x75, 0x10, 0x40, 0x58, 0x0B, 0x57, 0xC8, 0x57, 0x76, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22108000, 0x2210b000,
+ 0x22004000, 0x22108000, 0x2210b000, 0x00 },
+
+ /* 1024x768 @ 60Hz */
+ { 65000, 0x003F, 0x000A, 0x30, 0xA3, 0x7F, 0x7F, 0x87, 0x83, 0x94,
+ 0x24, 0x10, 0x40, 0x02, 0x08, 0xFF, 0x80, 0xFF, 0x25, 0x03,
+ 0x02, 0x03, 0x02, 0x00, 0x00, 0x22005000, 0x22109000, 0x2220D000,
+ 0x22005000, 0x22109000, 0x2220D000, 0xC0 },
+
+ /* 1024x768 @ 70Hz */
+ { 75000, 0x0017, 0x0002, 0x30, 0xA1, 0x7F, 0x7F, 0x85, 0x82, 0x93,
+ 0x24, 0x10, 0x40, 0x02, 0x08, 0xFF, 0x80, 0xFF, 0x25, 0x03,
+ 0x02, 0x03, 0x02, 0x00, 0x00, 0x22005000, 0x2210A000, 0x2220F000,
+ 0x22005000, 0x2210A000, 0x2220F000, 0xC0 },
+
+ /* 1024x768 @ 75Hz */
+ { 78000, 0x0050, 0x0017, 0x20, 0x9F, 0x7F, 0x7F, 0x83, 0x81, 0x8D,
+ 0x1E, 0x10, 0x40, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0x1F, 0x03,
+ 0x02, 0x03, 0x02, 0x00, 0x00, 0x22006000, 0x2210B000, 0x22210000,
+ 0x22006000, 0x2210B000, 0x22210000, 0x00 },
+
+ /* 1024x768 @ 85Hz */
+ { 94000, 0x003D, 0x000E, 0x20, 0xA7, 0x7F, 0x7F, 0x8B, 0x85, 0x91,
+ 0x26, 0x10, 0x40, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0x27, 0x03,
+ 0x02, 0x03, 0x02, 0x00, 0x00, 0x22007000, 0x2220E000, 0x22212000,
+ 0x22007000, 0x2220E000, 0x22212000, 0x00 },
+
+ /* 1152x864 @ 60Hz */
+ { 80000, 0x0008, 0x0001, 0x20, 0xB3, 0x8F, 0x8F, 0x97, 0x93, 0x9f,
+ 0x87, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5f, 0x88, 0x03,
+ 0x03, 0x03, 0x03, 0x00, 0x00, 0x2220C000, 0x22210000, 0x22415000,
+ 0x2220C000, 0x22210000, 0x22415000, 0x00 },
+
+ /* 1152x864 @ 70Hz */
+ { 96000, 0x000a, 0x0001, 0x20, 0xbb, 0x8F, 0x8F, 0x9f, 0x98, 0x87,
+ 0x82, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x83, 0x03,
+ 0x03, 0x03, 0x03, 0x00, 0x00, 0x22107000, 0x22210000, 0x22415000,
+ 0x22107000, 0x22210000, 0x22415000, 0x00 },
+
+ /* 1152x864 @ 72Hz */
+ { 99000, 0x001f, 0x0006, 0x20, 0xbb, 0x8F, 0x8F, 0x9f, 0x98, 0x87,
+ 0x83, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x84, 0x03,
+ 0x03, 0x03, 0x03, 0x00, 0x00, 0x22107000, 0x22210000, 0x22415000,
+ 0x22107000, 0x22210000, 0x22415000, 0x00 },
+
+ /* 1152x864 @ 75Hz */
+ { 108000, 0x0010, 0x0002, 0x20, 0xC3, 0x8F, 0x8F, 0x87, 0x97, 0x07,
+ 0x82, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x83, 0x03,
+ 0x03, 0x03, 0x03, 0x00, 0x01, 0x22107000, 0x22210000, 0x22415000,
+ 0x22107000, 0x22210000, 0x22415000, 0x00 },
+
+ /* 1152x864 @ 85Hz */
+ { 121000, 0x006D, 0x0014, 0x20, 0xc0, 0x8F, 0x8F, 0x84, 0x97, 0x07,
+ 0x93, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x94, 0x03,
+ 0x03, 0x03, 0x03, 0x00, 0x01, 0x2220C000, 0x22210000, 0x22415000,
+ 0x2220C000, 0x22210000, 0x22415000, 0x0 },
+
+ /* 1280x960 @ 60Hz */
+ { 108000, 0x0010, 0x0002, 0x20, 0xDC, 0x9F, 0x9F, 0x80, 0xAB, 0x99,
+ 0xE6, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xE7, 0x03,
+ 0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22210000, 0x22415000,
+ 0x2210A000, 0x22210000, 0x22415000, 0x00 },
+
+ /* 1280x960 @ 75Hz */
+ { 129000, 0x0029, 0x0006, 0x20, 0xD3, 0x9F, 0x9F, 0x97, 0xaa, 0x1b,
+ 0xE8, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xE9, 0x03,
+ 0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22210000, 0x2241B000,
+ 0x2210A000, 0x22210000, 0x2241B000, 0x00 },
+
+ /* 1280x960 @ 85Hz */
+ { 148000, 0x0042, 0x0009, 0x20, 0xD3, 0x9F, 0x9F, 0x97, 0xA7, 0x1B,
+ 0xF1, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xF2, 0x03,
+ 0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22220000, 0x2241D000,
+ 0x2210A000, 0x22220000, 0x2241D000, 0x00 },
+
+ /* 1600x1200 @ 60Hz */
+ { 162000, 0x0019, 0x0006, 0x10, 0x09, 0xC7, 0xC7, 0x8D, 0xcf, 0x07,
+ 0xE0, 0x10, 0x40, 0xB0, 0x03, 0xAF, 0xC8, 0xAF, 0xE1, 0x04,
+ 0x04, 0x04, 0x04, 0x01, 0x00, 0x2210b000, 0x22416000, 0x44419000,
+ 0x2210b000, 0x22416000, 0x44419000, 0x00 },
+
+ /* 1600x1200 @ 65 Hz */
+ { 175000, 0x005d, 0x0018, 0x10, 0x09, 0xC7, 0xC7, 0x8D, 0xcf, 0x07,
+ 0xE0, 0x10, 0x40, 0xB0, 0x03, 0xAF, 0xC8, 0xAF, 0xE1, 0x04,
+ 0x04, 0x04, 0x04, 0x01, 0x00, 0x2210c000, 0x22416000, 0x44419000,
+ 0x2210c000, 0x22416000, 0x44419000, 0x00 },
+
+ /* 1600x1200 @ 70 Hz */
+ { 189000, 0x003D, 0x000e, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
+ 0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04,
+ 0x04, 0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
+ 0x2220e000, 0x22416000, 0x44419000, 0x00 },
+
+ /* 1600x1200 @ 72 Hz */
+ { 195000, 0x003f, 0x000e, 0x10, 0x0b, 0xC7, 0xC7, 0x8f, 0xd5, 0x0b,
+ 0xE1, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xe2, 0x04, 0x04,
+ 0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
+ 0x2220e000, 0x22416000, 0x44419000, 0x00 },
+
+ /* 1600x1200 @ 75 Hz */
+ { 202000, 0x0024, 0x0007, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
+ 0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 0x04,
+ 0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
+ 0x2220e000, 0x22416000, 0x44419000, 0x00 },
+
+ /* 1600x1200 @ 85 Hz */
+ { 229000, 0x0029, 0x0007, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
+ 0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 0x04,
+ 0x04, 0x04, 0x01, 0x00, 0x22210000, 0x22416000, 0x0,
+ 0x22210000, 0x22416000, 0x0, 0x00 },
+};
+
+void round_off_xres(u32 *xres)
+{
+ if (*xres < 800)
+ *xres = 640;
+ if (*xres < 1024 && *xres >= 800)
+ *xres = 800;
+ if (*xres < 1152 && *xres >= 1024)
+ *xres = 1024;
+ if (*xres < 1280 && *xres >= 1152)
+ *xres = 1152;
+ if (*xres < 1600 && *xres >= 1280)
+ *xres = 1280;
+ if (*xres >= 1600)
+ *xres = 1600;
+}
+
+inline void round_off_yres(u32 *xres, u32 *yres)
+{
+ *yres = (*xres * 3) >> 2;
+}
+
+void i810fb_encode_registers(const struct fb_var_screeninfo *var,
+ struct i810fb_par *par, u32 xres, u32 yres)
+{
+ u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0;
+ u8 hfl;
+
+ hfl = (u8) ((xres >> 3) - 1);
+ for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
+ if (std_modes[i].cr01 == hfl) {
+ if (std_modes[i].pixclock <= par->regs.pixclock)
+ diff = par->regs.pixclock -
+ std_modes[i].pixclock;
+ if (diff < diff_best) {
+ i_best = i;
+ diff_best = diff;
+ }
+ }
+ }
+ par->regs = std_modes[i_best];
+
+ /* overlay */
+ par->ovract = ((xres + var->right_margin + var->hsync_len +
+ var->left_margin - 32) | ((xres - 32) << 16));
+}
+
+void i810fb_fill_var_timings(struct fb_var_screeninfo *var)
+{
+ struct i810fb_par par;
+ u32 total, xres, yres;
+
+ xres = var->xres;
+ yres = var->yres;
+
+ par.regs.pixclock = 1000000000/var->pixclock;
+ i810fb_encode_registers(var, &par, xres, yres);
+
+ total = ((par.regs.cr00 | (par.regs.cr35 & 1) << 8) + 3) << 3;
+
+ var->pixclock = 1000000000/par.regs.pixclock;
+ var->right_margin = (par.regs.cr04 << 3) - xres;
+ var->hsync_len = ((par.regs.cr05 & 0x1F) -
+ (par.regs.cr04 & 0x1F)) << 3;
+ var->left_margin = (total - (xres + var->right_margin +
+ var->hsync_len));
+ var->sync = FB_SYNC_ON_GREEN;
+ if (~(par.regs.msr & (1 << 6)))
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (~(par.regs.msr & (1 << 7)))
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+
+ total = ((par.regs.cr06 | (par.regs.cr30 & 0x0F) << 8)) + 2;
+ var->lower_margin = (par.regs.cr10 |
+ (par.regs.cr32 & 0x0F) << 8) - yres;
+ var->vsync_len = (par.regs.cr11 & 0x0F) - (var->lower_margin & 0x0F);
+ var->upper_margin = total - (yres + var->lower_margin +
+ var->vsync_len);
+}
+
+u32 i810_get_watermark(struct fb_var_screeninfo *var,
+ struct i810fb_par *par)
+{
+ struct mode_registers *params = &par->regs;
+ u32 wmark = 0;
+
+ if (par->mem_freq == 100) {
+ switch (var->bits_per_pixel) {
+ case 8:
+ wmark = params->bpp8_100;
+ break;
+ case 16:
+ wmark = params->bpp16_100;
+ break;
+ case 24:
+ case 32:
+ wmark = params->bpp24_100;
+ }
+ }
+ else {
+ switch (var->bits_per_pixel) {
+ case 8:
+ wmark = params->bpp8_133;
+ break;
+ case 16:
+ wmark = params->bpp16_133;
+ break;
+ case 24:
+ case 32:
+ wmark = params->bpp24_133;
+ }
+ }
+ return wmark;
+}
+
diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/i810/i810_gtf.c
new file mode 100644
index 000000000000..d5edb52d1afe
--- /dev/null
+++ b/drivers/video/i810/i810_gtf.c
@@ -0,0 +1,275 @@
+/*-*- linux-c -*-
+ * linux/drivers/video/i810_main.h -- Intel 810 Nondiscrete Video Timings
+ * (VESA GTF)
+ *
+ * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+#include <linux/kernel.h>
+
+#include "i810_regs.h"
+#include "i810.h"
+
+/*
+ * FIFO and Watermark tables - based almost wholly on i810_wmark.c in
+ * XFree86 v4.03 by Precision Insight. Slightly modified for integer
+ * operation, instead of float
+ */
+
+struct wm_info {
+ u32 freq;
+ u32 wm;
+};
+
+struct wm_info i810_wm_8_100[] = {
+ { 15, 0x0070c000 }, { 19, 0x0070c000 }, { 25, 0x22003000 },
+ { 28, 0x22003000 }, { 31, 0x22003000 }, { 36, 0x22007000 },
+ { 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22008000 },
+ { 50, 0x22008000 }, { 56, 0x22008000 }, { 65, 0x22008000 },
+ { 75, 0x22008000 }, { 78, 0x22008000 }, { 80, 0x22008000 },
+ { 94, 0x22008000 }, { 96, 0x22107000 }, { 99, 0x22107000 },
+ { 108, 0x22107000 }, { 121, 0x22107000 }, { 128, 0x22107000 },
+ { 132, 0x22109000 }, { 135, 0x22109000 }, { 157, 0x2210b000 },
+ { 162, 0x2210b000 }, { 175, 0x2210b000 }, { 189, 0x2220e000 },
+ { 195, 0x2220e000 }, { 202, 0x2220e000 }, { 204, 0x2220e000 },
+ { 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 },
+};
+
+struct wm_info i810_wm_16_100[] = {
+ { 15, 0x0070c000 }, { 19, 0x0020c000 }, { 25, 0x22006000 },
+ { 28, 0x22006000 }, { 31, 0x22007000 }, { 36, 0x22007000 },
+ { 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22009000 },
+ { 50, 0x22009000 }, { 56, 0x22108000 }, { 65, 0x2210e000 },
+ { 75, 0x2210e000 }, { 78, 0x2210e000 }, { 80, 0x22210000 },
+ { 94, 0x22210000 }, { 96, 0x22210000 }, { 99, 0x22210000 },
+ { 108, 0x22210000 }, { 121, 0x22210000 }, { 128, 0x22210000 },
+ { 132, 0x22314000 }, { 135, 0x22314000 }, { 157, 0x22415000 },
+ { 162, 0x22416000 }, { 175, 0x22416000 }, { 189, 0x22416000 },
+ { 195, 0x22416000 }, { 202, 0x22416000 }, { 204, 0x22416000 },
+ { 218, 0x22416000 }, { 229, 0x22416000 },
+};
+
+struct wm_info i810_wm_24_100[] = {
+ { 15, 0x0020c000 }, { 19, 0x0040c000 }, { 25, 0x22009000 },
+ { 28, 0x22009000 }, { 31, 0x2200a000 }, { 36, 0x2210c000 },
+ { 40, 0x2210c000 }, { 45, 0x2210c000 }, { 49, 0x22111000 },
+ { 50, 0x22111000 }, { 56, 0x22111000 }, { 65, 0x22214000 },
+ { 75, 0x22214000 }, { 78, 0x22215000 }, { 80, 0x22216000 },
+ { 94, 0x22218000 }, { 96, 0x22418000 }, { 99, 0x22418000 },
+ { 108, 0x22418000 }, { 121, 0x22418000 }, { 128, 0x22419000 },
+ { 132, 0x22519000 }, { 135, 0x4441d000 }, { 157, 0x44419000 },
+ { 162, 0x44419000 }, { 175, 0x44419000 }, { 189, 0x44419000 },
+ { 195, 0x44419000 }, { 202, 0x44419000 }, { 204, 0x44419000 },
+};
+
+struct wm_info i810_wm_8_133[] = {
+ { 15, 0x0070c000 }, { 19, 0x0070c000 }, { 25, 0x22003000 },
+ { 28, 0x22003000 }, { 31, 0x22003000 }, { 36, 0x22007000 },
+ { 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22008000 },
+ { 50, 0x22008000 }, { 56, 0x22008000 }, { 65, 0x22008000 },
+ { 75, 0x22008000 }, { 78, 0x22008000 }, { 80, 0x22008000 },
+ { 94, 0x22008000 }, { 96, 0x22107000 }, { 99, 0x22107000 },
+ { 108, 0x22107000 }, { 121, 0x22107000 }, { 128, 0x22107000 },
+ { 132, 0x22109000 }, { 135, 0x22109000 }, { 157, 0x2210b000 },
+ { 162, 0x2210b000 }, { 175, 0x2210b000 }, { 189, 0x2220e000 },
+ { 195, 0x2220e000 }, { 202, 0x2220e000 }, { 204, 0x2220e000 },
+ { 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 },
+};
+
+struct wm_info i810_wm_16_133[] = {
+ { 15, 0x0020c000 }, { 19, 0x0020c000 }, { 25, 0x22006000 },
+ { 28, 0x22006000 }, { 31, 0x22007000 }, { 36, 0x22007000 },
+ { 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22009000 },
+ { 50, 0x22009000 }, { 56, 0x22108000 }, { 65, 0x2210e000 },
+ { 75, 0x2210e000 }, { 78, 0x2210e000 }, { 80, 0x22210000 },
+ { 94, 0x22210000 }, { 96, 0x22210000 }, { 99, 0x22210000 },
+ { 108, 0x22210000 }, { 121, 0x22210000 }, { 128, 0x22210000 },
+ { 132, 0x22314000 }, { 135, 0x22314000 }, { 157, 0x22415000 },
+ { 162, 0x22416000 }, { 175, 0x22416000 }, { 189, 0x22416000 },
+ { 195, 0x22416000 }, { 202, 0x22416000 }, { 204, 0x22416000 },
+ { 218, 0x22416000 }, { 229, 0x22416000 },
+};
+
+struct wm_info i810_wm_24_133[] = {
+ { 15, 0x0020c000 }, { 19, 0x00408000 }, { 25, 0x22009000 },
+ { 28, 0x22009000 }, { 31, 0x2200a000 }, { 36, 0x2210c000 },
+ { 40, 0x2210c000 }, { 45, 0x2210c000 }, { 49, 0x22111000 },
+ { 50, 0x22111000 }, { 56, 0x22111000 }, { 65, 0x22214000 },
+ { 75, 0x22214000 }, { 78, 0x22215000 }, { 80, 0x22216000 },
+ { 94, 0x22218000 }, { 96, 0x22418000 }, { 99, 0x22418000 },
+ { 108, 0x22418000 }, { 121, 0x22418000 }, { 128, 0x22419000 },
+ { 132, 0x22519000 }, { 135, 0x4441d000 }, { 157, 0x44419000 },
+ { 162, 0x44419000 }, { 175, 0x44419000 }, { 189, 0x44419000 },
+ { 195, 0x44419000 }, { 202, 0x44419000 }, { 204, 0x44419000 },
+};
+
+void round_off_xres(u32 *xres) { }
+void round_off_yres(u32 *xres, u32 *yres) { }
+
+/**
+ * i810fb_encode_registers - encode @var to hardware register values
+ * @var: pointer to var structure
+ * @par: pointer to hardware par structure
+ *
+ * DESCRIPTION:
+ * Timing values in @var will be converted to appropriate
+ * register values of @par.
+ */
+void i810fb_encode_registers(const struct fb_var_screeninfo *var,
+ struct i810fb_par *par, u32 xres, u32 yres)
+{
+ int n, blank_s, blank_e;
+ u8 *mmio = par->mmio_start_virtual, msr = 0;
+
+ /* Horizontal */
+ /* htotal */
+ n = ((xres + var->right_margin + var->hsync_len +
+ var->left_margin) >> 3) - 5;
+ par->regs.cr00 = (u8) n;
+ par->regs.cr35 = (u8) ((n >> 8) & 1);
+
+ /* xres */
+ par->regs.cr01 = (u8) ((xres >> 3) - 1);
+
+ /* hblank */
+ blank_e = (xres + var->right_margin + var->hsync_len +
+ var->left_margin) >> 3;
+ blank_e--;
+ blank_s = blank_e - 127;
+ if (blank_s < (xres >> 3))
+ blank_s = xres >> 3;
+ par->regs.cr02 = (u8) blank_s;
+ par->regs.cr03 = (u8) (blank_e & 0x1F);
+ par->regs.cr05 = (u8) ((blank_e & (1 << 5)) << 2);
+ par->regs.cr39 = (u8) ((blank_e >> 6) & 1);
+
+ /* hsync */
+ par->regs.cr04 = (u8) ((xres + var->right_margin) >> 3);
+ par->regs.cr05 |= (u8) (((xres + var->right_margin +
+ var->hsync_len) >> 3) & 0x1F);
+
+ /* Vertical */
+ /* vtotal */
+ n = yres + var->lower_margin + var->vsync_len + var->upper_margin - 2;
+ par->regs.cr06 = (u8) (n & 0xFF);
+ par->regs.cr30 = (u8) ((n >> 8) & 0x0F);
+
+ /* vsync */
+ n = yres + var->lower_margin;
+ par->regs.cr10 = (u8) (n & 0xFF);
+ par->regs.cr32 = (u8) ((n >> 8) & 0x0F);
+ par->regs.cr11 = i810_readb(CR11, mmio) & ~0x0F;
+ par->regs.cr11 |= (u8) ((yres + var->lower_margin +
+ var->vsync_len) & 0x0F);
+
+ /* yres */
+ n = yres - 1;
+ par->regs.cr12 = (u8) (n & 0xFF);
+ par->regs.cr31 = (u8) ((n >> 8) & 0x0F);
+
+ /* vblank */
+ blank_e = yres + var->lower_margin + var->vsync_len +
+ var->upper_margin;
+ blank_e--;
+ blank_s = blank_e - 127;
+ if (blank_s < yres)
+ blank_s = yres;
+ par->regs.cr15 = (u8) (blank_s & 0xFF);
+ par->regs.cr33 = (u8) ((blank_s >> 8) & 0x0F);
+ par->regs.cr16 = (u8) (blank_e & 0xFF);
+ par->regs.cr09 = 0;
+
+ /* sync polarity */
+ if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+ msr |= 1 << 6;
+ if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+ msr |= 1 << 7;
+ par->regs.msr = msr;
+
+ /* interlace */
+ if (var->vmode & FB_VMODE_INTERLACED)
+ par->interlace = (1 << 7) | ((u8) (var->yres >> 4));
+ else
+ par->interlace = 0;
+
+ if (var->vmode & FB_VMODE_DOUBLE)
+ par->regs.cr09 |= 1 << 7;
+
+ /* overlay */
+ par->ovract = ((var->xres + var->right_margin + var->hsync_len +
+ var->left_margin - 32) | ((var->xres - 32) << 16));
+}
+
+void i810fb_fill_var_timings(struct fb_var_screeninfo *var) { }
+
+/**
+ * i810_get_watermark - gets watermark
+ * @var: pointer to fb_var_screeninfo
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Get's the required watermark based on
+ * pixelclock and RAMBUS frequency.
+ *
+ * RETURNS:
+ * watermark
+ */
+u32 i810_get_watermark(const struct fb_var_screeninfo *var,
+ struct i810fb_par *par)
+{
+ struct wm_info *wmark = 0;
+ u32 i, size = 0, pixclock, wm_best = 0, min, diff;
+
+ if (par->mem_freq == 100) {
+ switch (var->bits_per_pixel) {
+ case 8:
+ wmark = i810_wm_8_100;
+ size = ARRAY_SIZE(i810_wm_8_100);
+ break;
+ case 16:
+ wmark = i810_wm_16_100;
+ size = ARRAY_SIZE(i810_wm_16_100);
+ break;
+ case 24:
+ case 32:
+ wmark = i810_wm_24_100;
+ size = ARRAY_SIZE(i810_wm_24_100);
+ }
+ }
+ else {
+ switch(var->bits_per_pixel) {
+ case 8:
+ wmark = i810_wm_8_133;
+ size = ARRAY_SIZE(i810_wm_8_133);
+ break;
+ case 16:
+ wmark = i810_wm_16_133;
+ size = ARRAY_SIZE(i810_wm_16_133);
+ break;
+ case 24:
+ case 32:
+ wmark = i810_wm_24_133;
+ size = ARRAY_SIZE(i810_wm_24_133);
+ }
+ }
+
+ pixclock = 1000000/var->pixclock;
+ min = ~0;
+ for (i = 0; i < size; i++) {
+ if (pixclock <= wmark[i].freq)
+ diff = wmark[i].freq - pixclock;
+ else
+ diff = pixclock - wmark[i].freq;
+ if (diff < min) {
+ wm_best = wmark[i].wm;
+ min = diff;
+ }
+ }
+ return wm_best;
+}
+
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
new file mode 100644
index 000000000000..a13b75cefae4
--- /dev/null
+++ b/drivers/video/i810/i810_main.c
@@ -0,0 +1,2245 @@
+ /*-*- linux-c -*-
+ * linux/drivers/video/i810_main.c -- Intel 810 frame buffer device
+ *
+ * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ * Contributors:
+ * Michael Vogt <mvogt@acm.org> - added support for Intel 815 chipsets
+ * and enabling the power-on state of
+ * external VGA connectors for
+ * secondary displays
+ *
+ * Fredrik Andersson <krueger@shell.linux.se> - alpha testing of
+ * the VESA GTF
+ *
+ * Brad Corrion <bcorrion@web-co.com> - alpha testing of customized
+ * timings support
+ *
+ * The code framework is a modification of vfb.c by Geert Uytterhoeven.
+ * DotClock and PLL calculations are partly based on i810_driver.c
+ * in xfree86 v4.0.3 by Precision Insight.
+ * Watermark calculation and tables are based on i810_wmark.c
+ * in xfre86 v4.0.3 by Precision Insight. Slight modifications
+ * only to allow for integer operations instead of floating point.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/config.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/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/resource.h>
+#include <linux/unistd.h>
+
+#include <asm/io.h>
+#include <asm/div64.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <asm/page.h>
+
+#include "i810_regs.h"
+#include "i810.h"
+#include "i810_main.h"
+
+/*------------------------------------------------------------*/
+
+/**************************************************************
+ * Hardware Low Level Routines *
+ **************************************************************/
+
+/**
+ * i810_screen_off - turns off/on display
+ * @mmio: address of register space
+ * @mode: on or off
+ *
+ * DESCRIPTION:
+ * Blanks/unblanks the display
+ */
+static void i810_screen_off(u8 *mmio, u8 mode)
+{
+ u32 count = WAIT_COUNT;
+ u8 val;
+
+ i810_writeb(SR_INDEX, mmio, SR01);
+ val = i810_readb(SR_DATA, mmio);
+ val = (mode == OFF) ? val | SCR_OFF :
+ val & ~SCR_OFF;
+
+ while((i810_readw(DISP_SL, mmio) & 0xFFF) && count--);
+ i810_writeb(SR_INDEX, mmio, SR01);
+ i810_writeb(SR_DATA, mmio, val);
+}
+
+/**
+ * i810_dram_off - turns off/on dram refresh
+ * @mmio: address of register space
+ * @mode: on or off
+ *
+ * DESCRIPTION:
+ * Turns off DRAM refresh. Must be off for only 2 vsyncs
+ * before data becomes corrupt
+ */
+static void i810_dram_off(u8 *mmio, u8 mode)
+{
+ u8 val;
+
+ val = i810_readb(DRAMCH, mmio);
+ val &= DRAM_OFF;
+ val = (mode == OFF) ? val : val | DRAM_ON;
+ i810_writeb(DRAMCH, mmio, val);
+}
+
+/**
+ * i810_protect_regs - allows rw/ro mode of certain VGA registers
+ * @mmio: address of register space
+ * @mode: protect/unprotect
+ *
+ * DESCRIPTION:
+ * The IBM VGA standard allows protection of certain VGA registers.
+ * This will protect or unprotect them.
+ */
+static void i810_protect_regs(u8 *mmio, int mode)
+{
+ u8 reg;
+
+ i810_writeb(CR_INDEX_CGA, mmio, CR11);
+ reg = i810_readb(CR_DATA_CGA, mmio);
+ reg = (mode == OFF) ? reg & ~0x80 :
+ reg | 0x80;
+
+ i810_writeb(CR_INDEX_CGA, mmio, CR11);
+ i810_writeb(CR_DATA_CGA, mmio, reg);
+}
+
+/**
+ * i810_load_pll - loads values for the hardware PLL clock
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Loads the P, M, and N registers.
+ */
+static void i810_load_pll(struct i810fb_par *par)
+{
+ u32 tmp1, tmp2;
+ u8 *mmio = par->mmio_start_virtual;
+
+ tmp1 = par->regs.M | par->regs.N << 16;
+ tmp2 = i810_readl(DCLK_2D, mmio);
+ tmp2 &= ~MN_MASK;
+ i810_writel(DCLK_2D, mmio, tmp1 | tmp2);
+
+ tmp1 = par->regs.P;
+ tmp2 = i810_readl(DCLK_0DS, mmio);
+ tmp2 &= ~(P_OR << 16);
+ i810_writel(DCLK_0DS, mmio, (tmp1 << 16) | tmp2);
+
+ i810_writeb(MSR_WRITE, mmio, par->regs.msr | 0xC8 | 1);
+
+}
+
+/**
+ * i810_load_vga - load standard VGA registers
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Load values to VGA registers
+ */
+static void i810_load_vga(struct i810fb_par *par)
+{
+ u8 *mmio = par->mmio_start_virtual;
+
+ /* interlace */
+ i810_writeb(CR_INDEX_CGA, mmio, CR70);
+ i810_writeb(CR_DATA_CGA, mmio, par->interlace);
+
+ i810_writeb(CR_INDEX_CGA, mmio, CR00);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr00);
+ i810_writeb(CR_INDEX_CGA, mmio, CR01);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr01);
+ i810_writeb(CR_INDEX_CGA, mmio, CR02);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr02);
+ i810_writeb(CR_INDEX_CGA, mmio, CR03);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr03);
+ i810_writeb(CR_INDEX_CGA, mmio, CR04);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr04);
+ i810_writeb(CR_INDEX_CGA, mmio, CR05);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr05);
+ i810_writeb(CR_INDEX_CGA, mmio, CR06);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr06);
+ i810_writeb(CR_INDEX_CGA, mmio, CR09);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr09);
+ i810_writeb(CR_INDEX_CGA, mmio, CR10);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr10);
+ i810_writeb(CR_INDEX_CGA, mmio, CR11);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr11);
+ i810_writeb(CR_INDEX_CGA, mmio, CR12);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr12);
+ i810_writeb(CR_INDEX_CGA, mmio, CR15);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr15);
+ i810_writeb(CR_INDEX_CGA, mmio, CR16);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr16);
+}
+
+/**
+ * i810_load_vgax - load extended VGA registers
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Load values to extended VGA registers
+ */
+static void i810_load_vgax(struct i810fb_par *par)
+{
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_writeb(CR_INDEX_CGA, mmio, CR30);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr30);
+ i810_writeb(CR_INDEX_CGA, mmio, CR31);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr31);
+ i810_writeb(CR_INDEX_CGA, mmio, CR32);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr32);
+ i810_writeb(CR_INDEX_CGA, mmio, CR33);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr33);
+ i810_writeb(CR_INDEX_CGA, mmio, CR35);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr35);
+ i810_writeb(CR_INDEX_CGA, mmio, CR39);
+ i810_writeb(CR_DATA_CGA, mmio, par->regs.cr39);
+}
+
+/**
+ * i810_load_2d - load grahics registers
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Load values to graphics registers
+ */
+static void i810_load_2d(struct i810fb_par *par)
+{
+ u32 tmp;
+ u8 tmp8, *mmio = par->mmio_start_virtual;;
+
+ i810_writel(FW_BLC, mmio, par->watermark);
+ tmp = i810_readl(PIXCONF, mmio);
+ tmp |= 1 | 1 << 20;
+ i810_writel(PIXCONF, mmio, tmp);
+
+ i810_writel(OVRACT, mmio, par->ovract);
+
+ i810_writeb(GR_INDEX, mmio, GR10);
+ tmp8 = i810_readb(GR_DATA, mmio);
+ tmp8 |= 2;
+ i810_writeb(GR_INDEX, mmio, GR10);
+ i810_writeb(GR_DATA, mmio, tmp8);
+}
+
+/**
+ * i810_hires - enables high resolution mode
+ * @mmio: address of register space
+ */
+static void i810_hires(u8 *mmio)
+{
+ u8 val;
+
+ i810_writeb(CR_INDEX_CGA, mmio, CR80);
+ val = i810_readb(CR_DATA_CGA, mmio);
+ i810_writeb(CR_INDEX_CGA, mmio, CR80);
+ i810_writeb(CR_DATA_CGA, mmio, val | 1);
+}
+
+/**
+ * i810_load_pitch - loads the characters per line of the display
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Loads the characters per line
+ */
+static void i810_load_pitch(struct i810fb_par *par)
+{
+ u32 tmp, pitch;
+ u8 val, *mmio = par->mmio_start_virtual;
+
+ pitch = par->pitch >> 3;
+ i810_writeb(SR_INDEX, mmio, SR01);
+ val = i810_readb(SR_DATA, mmio);
+ val &= 0xE0;
+ val |= 1 | 1 << 2;
+ i810_writeb(SR_INDEX, mmio, SR01);
+ i810_writeb(SR_DATA, mmio, val);
+
+ tmp = pitch & 0xFF;
+ i810_writeb(CR_INDEX_CGA, mmio, CR13);
+ i810_writeb(CR_DATA_CGA, mmio, (u8) tmp);
+
+ tmp = pitch >> 8;
+ i810_writeb(CR_INDEX_CGA, mmio, CR41);
+ val = i810_readb(CR_DATA_CGA, mmio) & ~0x0F;
+ i810_writeb(CR_INDEX_CGA, mmio, CR41);
+ i810_writeb(CR_DATA_CGA, mmio, (u8) tmp | val);
+}
+
+/**
+ * i810_load_color - loads the color depth of the display
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Loads the color depth of the display and the graphics engine
+ */
+static void i810_load_color(struct i810fb_par *par)
+{
+ u8 *mmio = par->mmio_start_virtual;
+ u32 reg1;
+ u16 reg2;
+ reg1 = i810_readl(PIXCONF, mmio) & ~(0xF0000 | 1 << 27);
+ reg2 = i810_readw(BLTCNTL, mmio) & ~0x30;
+
+ reg1 |= 0x8000 | par->pixconf;
+ reg2 |= par->bltcntl;
+ i810_writel(PIXCONF, mmio, reg1);
+ i810_writew(BLTCNTL, mmio, reg2);
+}
+
+/**
+ * i810_load_regs - loads all registers for the mode
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Loads registers
+ */
+static void i810_load_regs(struct i810fb_par *par)
+{
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_screen_off(mmio, OFF);
+ i810_protect_regs(mmio, OFF);
+ i810_dram_off(mmio, OFF);
+ i810_load_pll(par);
+ i810_load_vga(par);
+ i810_load_vgax(par);
+ i810_dram_off(mmio, ON);
+ i810_load_2d(par);
+ i810_hires(mmio);
+ i810_screen_off(mmio, ON);
+ i810_protect_regs(mmio, ON);
+ i810_load_color(par);
+ i810_load_pitch(par);
+}
+
+static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue,
+ u8 *mmio)
+{
+ i810_writeb(CLUT_INDEX_WRITE, mmio, regno);
+ i810_writeb(CLUT_DATA, mmio, red);
+ i810_writeb(CLUT_DATA, mmio, green);
+ i810_writeb(CLUT_DATA, mmio, blue);
+}
+
+static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue,
+ u8 *mmio)
+{
+ i810_writeb(CLUT_INDEX_READ, mmio, regno);
+ *red = i810_readb(CLUT_DATA, mmio);
+ *green = i810_readb(CLUT_DATA, mmio);
+ *blue = i810_readb(CLUT_DATA, mmio);
+}
+
+/************************************************************
+ * VGA State Restore *
+ ************************************************************/
+static void i810_restore_pll(struct i810fb_par *par)
+{
+ u32 tmp1, tmp2;
+ u8 *mmio = par->mmio_start_virtual;
+
+ tmp1 = par->hw_state.dclk_2d;
+ tmp2 = i810_readl(DCLK_2D, mmio);
+ tmp1 &= ~MN_MASK;
+ tmp2 &= MN_MASK;
+ i810_writel(DCLK_2D, mmio, tmp1 | tmp2);
+
+ tmp1 = par->hw_state.dclk_1d;
+ tmp2 = i810_readl(DCLK_1D, mmio);
+ tmp1 &= ~MN_MASK;
+ tmp2 &= MN_MASK;
+ i810_writel(DCLK_1D, mmio, tmp1 | tmp2);
+
+ i810_writel(DCLK_0DS, mmio, par->hw_state.dclk_0ds);
+}
+
+static void i810_restore_dac(struct i810fb_par *par)
+{
+ u32 tmp1, tmp2;
+ u8 *mmio = par->mmio_start_virtual;
+
+ tmp1 = par->hw_state.pixconf;
+ tmp2 = i810_readl(PIXCONF, mmio);
+ tmp1 &= DAC_BIT;
+ tmp2 &= ~DAC_BIT;
+ i810_writel(PIXCONF, mmio, tmp1 | tmp2);
+}
+
+static void i810_restore_vgax(struct i810fb_par *par)
+{
+ u8 i, j, *mmio = par->mmio_start_virtual;
+
+ for (i = 0; i < 4; i++) {
+ i810_writeb(CR_INDEX_CGA, mmio, CR30+i);
+ i810_writeb(CR_DATA_CGA, mmio, *(&(par->hw_state.cr30) + i));
+ }
+ i810_writeb(CR_INDEX_CGA, mmio, CR35);
+ i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr35);
+ i810_writeb(CR_INDEX_CGA, mmio, CR39);
+ i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39);
+ i810_writeb(CR_INDEX_CGA, mmio, CR41);
+ i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39);
+
+ /*restore interlace*/
+ i810_writeb(CR_INDEX_CGA, mmio, CR70);
+ i = par->hw_state.cr70;
+ i &= INTERLACE_BIT;
+ j = i810_readb(CR_DATA_CGA, mmio);
+ i810_writeb(CR_INDEX_CGA, mmio, CR70);
+ i810_writeb(CR_DATA_CGA, mmio, j | i);
+
+ i810_writeb(CR_INDEX_CGA, mmio, CR80);
+ i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr80);
+ i810_writeb(MSR_WRITE, mmio, par->hw_state.msr);
+ i810_writeb(SR_INDEX, mmio, SR01);
+ i = (par->hw_state.sr01) & ~0xE0 ;
+ j = i810_readb(SR_DATA, mmio) & 0xE0;
+ i810_writeb(SR_INDEX, mmio, SR01);
+ i810_writeb(SR_DATA, mmio, i | j);
+}
+
+static void i810_restore_vga(struct i810fb_par *par)
+{
+ u8 i, *mmio = par->mmio_start_virtual;
+
+ for (i = 0; i < 10; i++) {
+ i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
+ i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr00) + i));
+ }
+ for (i = 0; i < 8; i++) {
+ i810_writeb(CR_INDEX_CGA, mmio, CR10 + i);
+ i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr10) + i));
+ }
+}
+
+static void i810_restore_addr_map(struct i810fb_par *par)
+{
+ u8 tmp, *mmio = par->mmio_start_virtual;
+
+ i810_writeb(GR_INDEX, mmio, GR10);
+ tmp = i810_readb(GR_DATA, mmio);
+ tmp &= ADDR_MAP_MASK;
+ tmp |= par->hw_state.gr10;
+ i810_writeb(GR_INDEX, mmio, GR10);
+ i810_writeb(GR_DATA, mmio, tmp);
+}
+
+static void i810_restore_2d(struct i810fb_par *par)
+{
+ u32 tmp_long;
+ u16 tmp_word;
+ u8 *mmio = par->mmio_start_virtual;
+
+ tmp_word = i810_readw(BLTCNTL, mmio);
+ tmp_word &= ~(3 << 4);
+ tmp_word |= par->hw_state.bltcntl;
+ i810_writew(BLTCNTL, mmio, tmp_word);
+
+ i810_dram_off(mmio, OFF);
+ i810_writel(PIXCONF, mmio, par->hw_state.pixconf);
+ i810_dram_off(mmio, ON);
+
+ tmp_word = i810_readw(HWSTAM, mmio);
+ tmp_word &= 3 << 13;
+ tmp_word |= par->hw_state.hwstam;
+ i810_writew(HWSTAM, mmio, tmp_word);
+
+ tmp_long = i810_readl(FW_BLC, mmio);
+ tmp_long &= FW_BLC_MASK;
+ tmp_long |= par->hw_state.fw_blc;
+ i810_writel(FW_BLC, mmio, tmp_long);
+
+ i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga);
+ i810_writew(IER, mmio, par->hw_state.ier);
+ i810_writew(IMR, mmio, par->hw_state.imr);
+ i810_writel(DPLYSTAS, mmio, par->hw_state.dplystas);
+}
+
+static void i810_restore_vga_state(struct i810fb_par *par)
+{
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_screen_off(mmio, OFF);
+ i810_protect_regs(mmio, OFF);
+ i810_dram_off(mmio, OFF);
+ i810_restore_pll(par);
+ i810_restore_dac(par);
+ i810_restore_vga(par);
+ i810_restore_vgax(par);
+ i810_restore_addr_map(par);
+ i810_dram_off(mmio, ON);
+ i810_restore_2d(par);
+ i810_screen_off(mmio, ON);
+ i810_protect_regs(mmio, ON);
+}
+
+/***********************************************************************
+ * VGA State Save *
+ ***********************************************************************/
+
+static void i810_save_vgax(struct i810fb_par *par)
+{
+ u8 i, *mmio = par->mmio_start_virtual;
+
+ for (i = 0; i < 4; i++) {
+ i810_writeb(CR_INDEX_CGA, mmio, CR30 + i);
+ *(&(par->hw_state.cr30) + i) = i810_readb(CR_DATA_CGA, mmio);
+ }
+ i810_writeb(CR_INDEX_CGA, mmio, CR35);
+ par->hw_state.cr35 = i810_readb(CR_DATA_CGA, mmio);
+ i810_writeb(CR_INDEX_CGA, mmio, CR39);
+ par->hw_state.cr39 = i810_readb(CR_DATA_CGA, mmio);
+ i810_writeb(CR_INDEX_CGA, mmio, CR41);
+ par->hw_state.cr41 = i810_readb(CR_DATA_CGA, mmio);
+ i810_writeb(CR_INDEX_CGA, mmio, CR70);
+ par->hw_state.cr70 = i810_readb(CR_DATA_CGA, mmio);
+ par->hw_state.msr = i810_readb(MSR_READ, mmio);
+ i810_writeb(CR_INDEX_CGA, mmio, CR80);
+ par->hw_state.cr80 = i810_readb(CR_DATA_CGA, mmio);
+ i810_writeb(SR_INDEX, mmio, SR01);
+ par->hw_state.sr01 = i810_readb(SR_DATA, mmio);
+}
+
+static void i810_save_vga(struct i810fb_par *par)
+{
+ u8 i, *mmio = par->mmio_start_virtual;
+
+ for (i = 0; i < 10; i++) {
+ i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
+ *((&par->hw_state.cr00) + i) = i810_readb(CR_DATA_CGA, mmio);
+ }
+ for (i = 0; i < 8; i++) {
+ i810_writeb(CR_INDEX_CGA, mmio, CR10 + i);
+ *((&par->hw_state.cr10) + i) = i810_readb(CR_DATA_CGA, mmio);
+ }
+}
+
+static void i810_save_2d(struct i810fb_par *par)
+{
+ u8 *mmio = par->mmio_start_virtual;
+
+ par->hw_state.dclk_2d = i810_readl(DCLK_2D, mmio);
+ par->hw_state.dclk_1d = i810_readl(DCLK_1D, mmio);
+ par->hw_state.dclk_0ds = i810_readl(DCLK_0DS, mmio);
+ par->hw_state.pixconf = i810_readl(PIXCONF, mmio);
+ par->hw_state.fw_blc = i810_readl(FW_BLC, mmio);
+ par->hw_state.bltcntl = i810_readw(BLTCNTL, mmio);
+ par->hw_state.hwstam = i810_readw(HWSTAM, mmio);
+ par->hw_state.hws_pga = i810_readl(HWS_PGA, mmio);
+ par->hw_state.ier = i810_readw(IER, mmio);
+ par->hw_state.imr = i810_readw(IMR, mmio);
+ par->hw_state.dplystas = i810_readl(DPLYSTAS, mmio);
+}
+
+static void i810_save_vga_state(struct i810fb_par *par)
+{
+ i810_save_vga(par);
+ i810_save_vgax(par);
+ i810_save_2d(par);
+}
+
+/************************************************************
+ * Helpers *
+ ************************************************************/
+/**
+ * get_line_length - calculates buffer pitch in bytes
+ * @par: pointer to i810fb_par structure
+ * @xres_virtual: virtual resolution of the frame
+ * @bpp: bits per pixel
+ *
+ * DESCRIPTION:
+ * Calculates buffer pitch in bytes.
+ */
+u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp)
+{
+ u32 length;
+
+ length = xres_virtual*bpp;
+ length = (length+31)&-32;
+ length >>= 3;
+ return length;
+}
+
+/**
+ * i810_calc_dclk - calculates the P, M, and N values of a pixelclock value
+ * @freq: target pixelclock in picoseconds
+ * @m: where to write M register
+ * @n: where to write N register
+ * @p: where to write P register
+ *
+ * DESCRIPTION:
+ * Based on the formula Freq_actual = (4*M*Freq_ref)/(N^P)
+ * Repeatedly computes the Freq until the actual Freq is equal to
+ * the target Freq or until the loop count is zero. In the latter
+ * case, the actual frequency nearest the target will be used.
+ */
+static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p)
+{
+ u32 m_reg, n_reg, p_divisor, n_target_max;
+ u32 m_target, n_target, p_target, n_best, m_best, mod;
+ u32 f_out, target_freq, diff = 0, mod_min, diff_min;
+
+ diff_min = mod_min = 0xFFFFFFFF;
+ n_best = m_best = m_target = f_out = 0;
+
+ target_freq = freq;
+ n_target_max = 30;
+
+ /*
+ * find P such that target freq is 16x reference freq (Hz).
+ */
+ p_divisor = 1;
+ p_target = 0;
+ while(!((1000000 * p_divisor)/(16 * 24 * target_freq)) &&
+ p_divisor <= 32) {
+ p_divisor <<= 1;
+ p_target++;
+ }
+
+ n_reg = m_reg = n_target = 3;
+ while ((diff_min || mod_min) && (n_target < n_target_max)) {
+ f_out = (p_divisor * n_reg * 1000000)/(4 * 24 * m_reg);
+ mod = (p_divisor * n_reg * 1000000) % (4 * 24 * m_reg);
+ m_target = m_reg;
+ n_target = n_reg;
+ if (f_out <= target_freq) {
+ n_reg++;
+ diff = target_freq - f_out;
+ }
+ else {
+ m_reg++;
+ diff = f_out - target_freq;
+ }
+
+ if (diff_min > diff) {
+ diff_min = diff;
+ n_best = n_target;
+ m_best = m_target;
+ }
+
+ if (!diff && mod_min > mod) {
+ mod_min = mod;
+ n_best = n_target;
+ m_best = m_target;
+ }
+ }
+ if (m) *m = (m_best - 2) & 0x3FF;
+ if (n) *n = (n_best - 2) & 0x3FF;
+ if (p) *p = (p_target << 4);
+}
+
+/**
+ * i810_get_vblank - get vertical blank time
+ * @hfreq: horizontal freq
+ *
+ * DESCRIPTION:
+ * vblank = right_margin + vsync_len + left_margin
+ * given: right_margin = 1 (V_FRONTPORCH)
+ * vsync_len = 3
+ * flyback = 550
+ *
+ * flyback * hfreq
+ * left_margin = --------------- - vsync_len
+ * 1000000
+ * and flyback is set to 550
+ */
+static u32 i810_get_vblank(u32 hfreq)
+{
+ u32 vblank;
+
+ vblank = (hfreq * FLYBACK)/1000;
+ vblank = (vblank + 500)/1000;
+ return (vblank + V_FRONTPORCH);
+}
+
+/**
+ * i810_get_hblank - get horizontal blank time
+ * @hfreq: horizontal freq
+ * @xres: horizontal resolution in pixels
+ *
+ * DESCRIPTION:
+ * duty cycle is the percent of htotal assigned to inactive display
+ * duty cycle = C - (M/Hfreq)
+ * where: C = ((offset - scale factor) * blank_scale)
+ * -------------------------------------- + scale factor
+ * 256
+ * M = blank_scale * gradient
+ *
+ * xres * duty_cycle
+ * hblank = ------------------
+ * 100 - duty_cycle
+ */
+static u32 i810_get_hblank(u32 hfreq, u32 xres)
+{
+ u32 c_val, m_val, duty_cycle, hblank;
+
+ c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
+ H_SCALEFACTOR) * 1000;
+ m_val = (H_BLANKSCALE * H_GRADIENT)/256;
+ m_val = (m_val * 1000000)/hfreq;
+ duty_cycle = c_val - m_val;
+ hblank = (xres * duty_cycle)/(100000 - duty_cycle);
+ hblank = (hblank + 4) & ~7;
+ return (hblank);
+}
+
+/**
+ * i810_estimate_hfreq - estimate hsync
+ * @vfreq: vertical refresh rate
+ * @yres: vertical resolution
+ *
+ * DESCRIPTION:
+ * Based on:
+ *
+ * (yres + front_port) * vfreq * 1000000
+ * hfreq = -------------------------------------
+ * (1000000 - (vfreq * FLYBACK)
+ *
+ */
+
+static u32 i810_estimate_hfreq(u32 vfreq, u32 yres)
+{
+ u64 hfreq;
+ u32 divisor;
+
+ divisor = 1000000 - (vfreq * FLYBACK);
+
+ hfreq = (u64) (yres + V_FRONTPORCH) *
+ (u64) (vfreq) * 1000000;
+ do_div(hfreq, divisor);
+
+ return ((u32) hfreq);
+}
+
+/**
+ * i810_calculate_timings - calculate video timings
+ * @info: pointer to fb_info structure
+ * @var: pointer to current var
+ *
+ * DESCRIPTION:
+ * htotal: calculated using GTF
+ * vtotal: calculated using GTF
+ * hsync pulse: 8% of htotal
+ * vsync pulse: 3
+ * left margin : (htotal - xres)/2 - hsync
+ * right margin: sync + left margin
+ * upper margin: 1
+ * lower margin: vtotal - (yres + vsync + upper margin)
+ *
+ * Calculates necessary timing information based on
+ * monitor specifications. This will use the
+ * VESA generalized timing formula. New values are
+ * written to @var.
+ */
+static int i810_calculate_timings(struct fb_info *info,
+ struct fb_var_screeninfo *var,
+ u32 xres, u32 yres)
+{
+ u64 num = 1000000000000;
+ u32 htotal = 0, vtotal, hfreq, vfreq, hblank, vblank;
+ u32 dclk, interlace = 0, dscan = 0;
+ u32 max_pixclock = 0;
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ max_pixclock = 234000000;
+ break;
+ case 16:
+ max_pixclock = 229000000;
+ break;
+ case 24:
+ case 32:
+ max_pixclock = 204000000;
+ break;
+ default:
+ max_pixclock = 0;
+ }
+
+ if (var->vmode & FB_VMODE_INTERLACED) {
+ yres >>= 1;
+ interlace = 1;
+ }
+ if (var->vmode & FB_VMODE_DOUBLE) {
+ yres <<= 1;
+ dscan = 1;
+ }
+
+ hfreq = info->monspecs.hfmax;
+ vblank = i810_get_vblank(hfreq);
+ vtotal = yres + vblank;
+ vfreq = hfreq/vtotal;
+ if (vfreq > info->monspecs.vfmax) {
+ vfreq = info->monspecs.vfmax;
+ hfreq = i810_estimate_hfreq(vfreq, yres);
+ vblank = i810_get_vblank(hfreq);
+ vtotal = yres + vblank;
+ }
+ hblank = i810_get_hblank(hfreq, xres);
+ htotal = xres + hblank;
+ dclk = htotal * hfreq;
+ while(dclk > max_pixclock &&
+ hfreq > info->monspecs.hfmin &&
+ vfreq > info->monspecs.vfmin) {
+ hfreq -= 1000;
+ vblank = i810_get_vblank(hfreq);
+ vtotal = yres + vblank;
+ vfreq = hfreq/vtotal;
+ hblank = i810_get_hblank(hfreq, xres);
+ htotal = xres + hblank;
+ dclk = hfreq * htotal;
+ }
+ if (vfreq < info->monspecs.vfmin) {
+ printk("i810fb: required vertical refresh, %dHz, "
+ "for %dx%d is out of range\n",
+ vfreq, xres, yres);
+ return -1;
+ }
+ if (hfreq < info->monspecs.hfmin) {
+ printk("i810fb: required horizontal sync frequency, %dKHz, "
+ "for %dx%d is out of range\n", hfreq/1000, xres, yres);
+ return -1;
+ }
+ if (dclk < MIN_PIXELCLOCK) {
+ printk("i810fb: required pixelclock, %dMHz, for %dx%d"
+ " is out of range\n", dclk/1000000, xres, yres);
+ return -1;
+ }
+
+ do_div(num, dclk);
+ var->pixclock = (u32) num;
+ var->hsync_len = ((htotal * 8)/100 + 4) & ~7;
+ var->right_margin = ((hblank >> 1) - var->hsync_len + 4) & ~7;
+ var->left_margin = (hblank-var->right_margin-var->hsync_len + 4) & ~7;
+
+ var->vsync_len = (3 << interlace) >> dscan;
+ var->lower_margin = (1 << interlace) >> dscan;
+ var->upper_margin = ((vblank << interlace) >> dscan) -
+ (var->vsync_len + var->lower_margin);
+
+ if (yres > 480 || (yres == 200 && vfreq == 60 && hfreq/100 == 157))
+ var->sync |= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT;
+ else {
+ if (yres == 400 && vfreq == 70 && hfreq/100 == 315)
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+ if (yres == 350 && vfreq == 60 && hfreq/100 == 218)
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ }
+ return 0;
+}
+
+/**
+ * i810_check_custom_timings - validates user entered timings
+ * @info: pointer to fb_info
+ * @var: pointer to current fb_var_screeninfo
+ *
+ * DESCRIPTION:
+ * Validates user entered timings in @var.
+ */
+static int i810_check_custom_timings(struct fb_info *info,
+ struct fb_var_screeninfo *var,
+ u32 xres, u32 yres)
+{
+ u64 num = 1000000000000;
+ u32 hfreq, vfreq, htotal, vtotal, pixclock;
+ u32 max_pixclock = 0;
+
+ if (!var->pixclock)
+ return -EINVAL;
+ do_div(num, var->pixclock);
+ pixclock = (u32) num;
+
+ htotal = xres + var->right_margin + var->hsync_len + var->left_margin;
+ vtotal = yres + var->lower_margin + var->vsync_len + var->upper_margin;
+
+ if (var->vmode & FB_VMODE_INTERLACED)
+ vtotal >>= 1;
+
+ if (var->vmode & FB_VMODE_DOUBLE)
+ vtotal <<= 1;
+
+ hfreq = pixclock/htotal;
+ vfreq = hfreq/vtotal;
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ max_pixclock = 234000000;
+ break;
+ case 16:
+ max_pixclock = 229000000;
+ break;
+ case 24:
+ case 32:
+ max_pixclock = 204000000;
+ break;
+ default:
+ max_pixclock = 0;
+ }
+
+ if (pixclock < MIN_PIXELCLOCK || pixclock > max_pixclock ||
+ hfreq < info->monspecs.hfmin || hfreq > info->monspecs.hfmax ||
+ vfreq < info->monspecs.vfmin || vfreq > info->monspecs.vfmax)
+ return -EINVAL;
+
+ return 0;
+}
+
+/*************************************************************
+ * Hardware Cursor Routines *
+ *************************************************************/
+
+/**
+ * i810_enable_cursor - show or hide the hardware cursor
+ * @mmio: address of register space
+ * @mode: show (1) or hide (0)
+ *
+ * Description:
+ * Shows or hides the hardware cursor
+ */
+void i810_enable_cursor(u8 *mmio, int mode)
+{
+ u32 temp;
+
+ temp = i810_readl(PIXCONF, mmio);
+ temp = (mode == ON) ? temp | CURSOR_ENABLE_MASK :
+ temp & ~CURSOR_ENABLE_MASK;
+
+ i810_writel(PIXCONF, mmio, temp);
+}
+
+static void i810_reset_cursor_image(struct i810fb_par *par)
+{
+ u8 *addr = par->cursor_heap.virtual;
+ int i, j;
+
+ for (i = 64; i--; ) {
+ for (j = 0; j < 8; j++) {
+ i810_writeb(j, addr, 0xff);
+ i810_writeb(j+8, addr, 0x00);
+ }
+ addr +=16;
+ }
+}
+
+static void i810_load_cursor_image(int width, int height, u8 *data,
+ struct i810fb_par *par)
+{
+ u8 *addr = par->cursor_heap.virtual;
+ int i, j, w = (width + 7)/8;
+
+ for (i = height; i--; ) {
+ for (j = 0; j < w; j++) {
+ i810_writeb(j+0, addr, 0x00);
+ i810_writeb(j+8, addr, *data++);
+ }
+ addr += 16;
+ }
+}
+
+static void i810_load_cursor_colors(int fg, int bg,
+ struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ u8 *mmio = par->mmio_start_virtual, temp;
+ u8 red, green, blue, trans;
+
+ i810fb_getcolreg(bg, &red, &green, &blue, &trans, info);
+
+ temp = i810_readb(PIXCONF1, mmio);
+ i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE);
+
+ i810_write_dac(4, red, green, blue, mmio);
+
+ i810_writeb(PIXCONF1, mmio, temp);
+
+ i810fb_getcolreg(fg, &red, &green, &blue, &trans, info);
+ temp = i810_readb(PIXCONF1, mmio);
+ i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE);
+
+ i810_write_dac(5, red, green, blue, mmio);
+
+ i810_writeb(PIXCONF1, mmio, temp);
+}
+
+/**
+ * i810_init_cursor - initializes the cursor
+ * @par: pointer to i810fb_par structure
+ *
+ * DESCRIPTION:
+ * Initializes the cursor registers
+ */
+static void i810_init_cursor(struct i810fb_par *par)
+{
+ u8 *mmio = par->mmio_start_virtual;
+
+ i810_enable_cursor(mmio, OFF);
+ i810_writel(CURBASE, mmio, par->cursor_heap.physical);
+ i810_writew(CURCNTR, mmio, COORD_ACTIVE | CURSOR_MODE_64_XOR);
+}
+
+/*********************************************************************
+ * Framebuffer hook helpers *
+ *********************************************************************/
+/**
+ * i810_round_off - Round off values to capability of hardware
+ * @var: pointer to fb_var_screeninfo structure
+ *
+ * DESCRIPTION:
+ * @var contains user-defined information for the mode to be set.
+ * This will try modify those values to ones nearest the
+ * capability of the hardware
+ */
+static void i810_round_off(struct fb_var_screeninfo *var)
+{
+ u32 xres, yres, vxres, vyres;
+
+ /*
+ * Presently supports only these configurations
+ */
+
+ xres = var->xres;
+ yres = var->yres;
+ vxres = var->xres_virtual;
+ vyres = var->yres_virtual;
+
+ var->bits_per_pixel += 7;
+ var->bits_per_pixel &= ~7;
+
+ if (var->bits_per_pixel < 8)
+ var->bits_per_pixel = 8;
+ if (var->bits_per_pixel > 32)
+ var->bits_per_pixel = 32;
+
+ round_off_xres(&xres);
+ if (xres < 40)
+ xres = 40;
+ if (xres > 2048)
+ xres = 2048;
+ xres = (xres + 7) & ~7;
+
+ if (vxres < xres)
+ vxres = xres;
+
+ round_off_yres(&xres, &yres);
+ if (yres < 1)
+ yres = 1;
+ if (yres >= 2048)
+ yres = 2048;
+
+ if (vyres < yres)
+ vyres = yres;
+
+ if (var->bits_per_pixel == 32)
+ var->accel_flags = 0;
+
+ /* round of horizontal timings to nearest 8 pixels */
+ var->left_margin = (var->left_margin + 4) & ~7;
+ var->right_margin = (var->right_margin + 4) & ~7;
+ var->hsync_len = (var->hsync_len + 4) & ~7;
+
+ if (var->vmode & FB_VMODE_INTERLACED) {
+ if (!((yres + var->upper_margin + var->vsync_len +
+ var->lower_margin) & 1))
+ var->upper_margin++;
+ }
+
+ var->xres = xres;
+ var->yres = yres;
+ var->xres_virtual = vxres;
+ var->yres_virtual = vyres;
+}
+
+/**
+ * set_color_bitfields - sets rgba fields
+ * @var: pointer to fb_var_screeninfo
+ *
+ * DESCRIPTION:
+ * The length, offset and ordering for each color field
+ * (red, green, blue) will be set as specified
+ * by the hardware
+ */
+static void set_color_bitfields(struct fb_var_screeninfo *var)
+{
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 16:
+ if (var->green.length == 5) {
+ /* RGB 555 */
+ var->red.offset = 10;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 5;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 15;
+ var->transp.length = 1;
+ }
+ else {
+ /* RGB 565 */
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ }
+ break;
+ case 24: /* RGB 888 */
+ case 32: /* RGBA 8888 */
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ if (var->bits_per_pixel == 24) {
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ }
+ else {
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ break;
+ }
+ }
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+}
+
+/**
+ * i810_check_params - check if contents in var are valid
+ * @var: pointer to fb_var_screeninfo
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * This will check if the framebuffer size is sufficient
+ * for the current mode and if the user's monitor has the
+ * required specifications to display the current mode.
+ */
+static int i810_check_params(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ int line_length, vidmem;
+ u32 xres, yres, vxres, vyres;
+
+ xres = var->xres;
+ yres = var->yres;
+ vxres = var->xres_virtual;
+ vyres = var->yres_virtual;
+
+ /*
+ * Memory limit
+ */
+ line_length = get_line_length(par, vxres,
+ var->bits_per_pixel);
+
+ vidmem = line_length*vyres;
+ if (vidmem > par->fb.size) {
+ vyres = par->fb.size/line_length;
+ if (vyres < yres) {
+ vyres = yres;
+ vxres = par->fb.size/vyres;
+ vxres /= var->bits_per_pixel >> 3;
+ line_length = get_line_length(par, vxres,
+ var->bits_per_pixel);
+ vidmem = line_length * yres;
+ if (vxres < xres) {
+ printk("i810fb: required video memory, "
+ "%d bytes, for %dx%d-%d (virtual) "
+ "is out of range\n",
+ vidmem, vxres, vyres,
+ var->bits_per_pixel);
+ return -ENOMEM;
+ }
+ }
+ }
+ /*
+ * Monitor limit
+ */
+ if (i810_check_custom_timings(info, var, xres, yres)) {
+ if (i810_calculate_timings(info, var, xres, yres)) {
+ return -EINVAL;
+ }
+ }
+ var->xres = xres;
+ var->yres = yres;
+ var->xres_virtual = vxres;
+ var->yres_virtual = vyres;
+ return 0;
+}
+
+/**
+ * encode_fix - fill up fb_fix_screeninfo structure
+ * @fix: pointer to fb_fix_screeninfo
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * This will set up parameters that are unmodifiable by the user.
+ */
+static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+ strcpy(fix->id, i810fb_name);
+ fix->smem_start = par->fb.physical;
+ fix->smem_len = par->fb.size;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+ fix->xpanstep = 8;
+ fix->ypanstep = 1;
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ case 16:
+ case 24:
+ case 32:
+ if (info->var.nonstd)
+ fix->visual = FB_VISUAL_DIRECTCOLOR;
+ else
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ break;
+ default:
+ return -EINVAL;
+ }
+ fix->ywrapstep = 0;
+ fix->line_length = get_line_length(par, info->var.xres_virtual,
+ info->var.bits_per_pixel);
+ fix->mmio_start = par->mmio_start_phys;
+ fix->mmio_len = MMIO_SIZE;
+ fix->accel = FB_ACCEL_I810;
+
+ return 0;
+}
+
+/**
+ * decode_var - modify par according to contents of var
+ * @var: pointer to fb_var_screeninfo
+ * @par: pointer to i810fb_par
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * Based on the contents of @var, @par will be dynamically filled up.
+ * @par contains all information necessary to modify the hardware.
+*/
+static void decode_var(const struct fb_var_screeninfo *var,
+ struct i810fb_par *par, struct fb_info *info)
+{
+ u32 xres, yres, vxres, vyres;
+
+ xres = var->xres;
+ yres = var->yres;
+ vxres = var->xres_virtual;
+ vyres = var->yres_virtual;
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ par->pixconf = PIXCONF8;
+ par->bltcntl = 0;
+ par->depth = 1;
+ par->blit_bpp = BPP8;
+ break;
+ case 16:
+ if (var->green.length == 5)
+ par->pixconf = PIXCONF15;
+ else
+ par->pixconf = PIXCONF16;
+ par->bltcntl = 16;
+ par->depth = 2;
+ par->blit_bpp = BPP16;
+ break;
+ case 24:
+ par->pixconf = PIXCONF24;
+ par->bltcntl = 32;
+ par->depth = 3;
+ par->blit_bpp = BPP24;
+ break;
+ case 32:
+ par->pixconf = PIXCONF32;
+ par->bltcntl = 0;
+ par->depth = 4;
+ par->blit_bpp = 3 << 24;
+ break;
+ }
+ if (var->nonstd && var->bits_per_pixel != 8)
+ par->pixconf |= 1 << 27;
+
+ i810_calc_dclk(var->pixclock, &par->regs.M,
+ &par->regs.N, &par->regs.P);
+ i810fb_encode_registers(var, par, xres, yres);
+
+ par->watermark = i810_get_watermark(var, par);
+ par->pitch = get_line_length(par, vxres, var->bits_per_pixel);
+}
+
+/**
+ * i810fb_getcolreg - gets red, green and blue values of the hardware DAC
+ * @regno: DAC index
+ * @red: red
+ * @green: green
+ * @blue: blue
+ * @transp: transparency (alpha)
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * Gets the red, green and blue values of the hardware DAC as pointed by @regno
+ * and writes them to @red, @green and @blue respectively
+ */
+static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
+ u8 *transp, struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ u8 *mmio = par->mmio_start_virtual, temp;
+
+ if (regno > 255) return 1;
+
+ if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ if ((info->var.green.length == 5 && regno > 31) ||
+ (info->var.green.length == 6 && regno > 63))
+ return 1;
+ }
+
+ temp = i810_readb(PIXCONF1, mmio);
+ i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
+
+ if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
+ info->var.green.length == 5)
+ i810_read_dac(regno * 8, red, green, blue, mmio);
+
+ else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
+ info->var.green.length == 6) {
+ u8 tmp;
+
+ i810_read_dac(regno * 8, red, &tmp, blue, mmio);
+ i810_read_dac(regno * 4, &tmp, green, &tmp, mmio);
+ }
+ else
+ i810_read_dac(regno, red, green, blue, mmio);
+
+ *transp = 0;
+ i810_writeb(PIXCONF1, mmio, temp);
+
+ return 0;
+}
+
+/******************************************************************
+ * Framebuffer device-specific hooks *
+ ******************************************************************/
+
+static int i810fb_open(struct fb_info *info, int user)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ u32 count = atomic_read(&par->use_count);
+
+ if (count == 0) {
+ memset(&par->state, 0, sizeof(struct vgastate));
+ par->state.flags = VGA_SAVE_CMAP;
+ par->state.vgabase = (caddr_t) par->mmio_start_virtual;
+ save_vga(&par->state);
+
+ i810_save_vga_state(par);
+ }
+
+ atomic_inc(&par->use_count);
+
+ return 0;
+}
+
+static int i810fb_release(struct fb_info *info, int user)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ u32 count;
+
+ count = atomic_read(&par->use_count);
+ if (count == 0)
+ return -EINVAL;
+
+ if (count == 1) {
+ i810_restore_vga_state(par);
+ restore_vga(&par->state);
+ }
+
+ atomic_dec(&par->use_count);
+
+ return 0;
+}
+
+
+static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ u8 *mmio = par->mmio_start_virtual, temp;
+ int i;
+
+ if (regno > 255) return 1;
+
+ if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ if ((info->var.green.length == 5 && regno > 31) ||
+ (info->var.green.length == 6 && regno > 63))
+ return 1;
+ }
+
+ if (info->var.grayscale)
+ red = green = blue = (19595 * red + 38470 * green +
+ 7471 * blue) >> 16;
+
+ temp = i810_readb(PIXCONF1, mmio);
+ i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
+
+ if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
+ info->var.green.length == 5) {
+ for (i = 0; i < 8; i++)
+ i810_write_dac((u8) (regno * 8) + i, (u8) red,
+ (u8) green, (u8) blue, mmio);
+ }
+
+ else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
+ info->var.green.length == 6) {
+ if (!regno) {
+ memset(par->red, 0, 64);
+ memset(par->green, 0, 64);
+ memset(par->blue, 0, 64);
+ }
+
+ par->red[regno] = (u8) red;
+ par->green[regno] = (u8) green;
+ par->blue[regno] = (u8) blue;
+
+ if (regno < 32) {
+ for (i = 0; i < 8; i++)
+ i810_write_dac((u8) (regno * 8) + i,
+ (u8) red, par->green[regno*2],
+ (u8) blue, mmio);
+ }
+ for (i = 0; i < 4; i++)
+ i810_write_dac((u8) (regno*4) + i, par->red[regno/2],
+ (u8) green, par->blue[regno/2], mmio);
+ }
+ else {
+ i810_write_dac((u8) regno, (u8) red, (u8) green,
+ (u8) blue, mmio);
+ }
+
+ i810_writeb(PIXCONF1, mmio, temp);
+
+ if (regno < 16) {
+ switch (info->var.bits_per_pixel) {
+ case 16:
+ if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ if (info->var.green.length == 5)
+ ((u32 *)info->pseudo_palette)[regno] =
+ (regno << 10) | (regno << 5) |
+ regno;
+ else
+ ((u32 *)info->pseudo_palette)[regno] =
+ (regno << 11) | (regno << 5) |
+ regno;
+ }
+ else {
+ if (info->var.green.length == 5) {
+ /* RGB 555 */
+ ((u32 *)info->pseudo_palette)[regno] =
+ ((red & 0xf800) >> 1) |
+ ((green & 0xf800) >> 6) |
+ ((blue & 0xf800) >> 11);
+ }
+ else {
+ /* RGB 565 */
+ ((u32 *)info->pseudo_palette)[regno] =
+ (red & 0xf800) |
+ ((green & 0xf800) >> 5) |
+ ((blue & 0xf800) >> 11);
+ }
+ }
+ break;
+ case 24: /* RGB 888 */
+ case 32: /* RGBA 8888 */
+ if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+ ((u32 *)info->pseudo_palette)[regno] =
+ (regno << 16) | (regno << 8) |
+ regno;
+ else
+ ((u32 *)info->pseudo_palette)[regno] =
+ ((red & 0xff00) << 8) |
+ (green & 0xff00) |
+ ((blue & 0xff00) >> 8);
+ break;
+ }
+ }
+ return 0;
+}
+
+static int i810fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ u32 total;
+ u8 *mmio = par->mmio_start_virtual;
+ int xoffset = var->xoffset, yoffset = var->yoffset;
+
+ if (xoffset < 0 ||
+ xoffset+var->xres > var->xres_virtual ||
+ yoffset < 0 ||
+ yoffset+var->yres > var->yres_virtual)
+ return -EINVAL;
+
+ total = xoffset * par->depth + yoffset * info->fix.line_length;
+ i810_writel(DPLYBASE, mmio, par->fb.physical + total);
+
+ return 0;
+}
+
+static int i810fb_blank (int blank_mode, struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ u8 *mmio = par->mmio_start_virtual;
+ int mode = 0, pwr, scr_off = 0;
+
+ pwr = i810_readl(PWR_CLKC, mmio);
+
+ switch(blank_mode) {
+ case VESA_NO_BLANKING:
+ mode = POWERON;
+ pwr |= 1;
+ scr_off = ON;
+ break;
+ case VESA_VSYNC_SUSPEND:
+ mode = STANDBY;
+ pwr |= 1;
+ scr_off = OFF;
+ break;
+ case VESA_HSYNC_SUSPEND:
+ mode = SUSPEND;
+ pwr |= 1;
+ scr_off = OFF;
+ break;
+ case VESA_POWERDOWN:
+ mode = POWERDOWN;
+ pwr &= ~1;
+ scr_off = OFF;
+ break;
+ default:
+ return -EINVAL;
+ }
+ i810_screen_off(mmio, scr_off);
+ i810_writel(HVSYNC, mmio, mode);
+ i810_writel(PWR_CLKC, mmio, pwr);
+ return 0;
+}
+
+static int i810fb_set_par(struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+
+ i810_load_regs(par);
+ i810_init_cursor(par);
+ par->cursor_reset = 1;
+ encode_fix(&info->fix, info);
+
+ return 0;
+}
+
+static int i810fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ int err;
+
+ if (IS_DVT) {
+ var->vmode &= ~FB_VMODE_MASK;
+ var->vmode |= FB_VMODE_NONINTERLACED;
+ }
+ if (var->vmode & FB_VMODE_DOUBLE) {
+ var->vmode &= ~FB_VMODE_MASK;
+ var->vmode |= FB_VMODE_NONINTERLACED;
+ }
+
+ i810_round_off(var);
+ if ((err = i810_check_params(var, info)))
+ return err;
+
+ i810fb_fill_var_timings(var);
+ set_color_bitfields(var);
+ decode_var(&info->var, par, info);
+ return 0;
+}
+
+static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ static u8 data[64 * 8];
+ struct i810fb_par *par = (struct i810fb_par *)info->par;
+ u8 *mmio = par->mmio_start_virtual;
+ u16 flags = cursor->set;
+
+ if (!info->var.accel_flags || par->dev_flags & LOCKUP) {
+ return soft_cursor(info, cursor);
+ }
+
+ if (cursor->image.width > 64 || cursor->image.height > 64 ||
+ (cursor->dest == NULL && cursor->rop == ROP_XOR))
+ return 1;
+
+ if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) {
+ i810_init_cursor(par);
+ par->cursor_reset = 1;
+ }
+
+ if (par->cursor_reset) {
+ flags = FB_CUR_SETALL;
+ par->cursor_reset = 0;
+ }
+
+ i810_enable_cursor(mmio, OFF);
+
+ if (flags & FB_CUR_SETPOS) {
+ u32 tmp;
+
+ tmp = cursor->image.dx - info->var.xoffset;
+ tmp |= (cursor->image.dy - info->var.yoffset) << 16;
+
+ i810_writel(CURPOS, mmio, tmp);
+ }
+
+ if (flags & FB_CUR_SETSIZE) {
+ i810_reset_cursor_image(par);
+ }
+
+ if (flags & FB_CUR_SETCMAP) {
+ i810_load_cursor_colors(cursor->image.fg_color,
+ cursor->image.bg_color,
+ info);
+ }
+
+ if (flags & (FB_CUR_SETDEST | FB_CUR_SETSHAPE)) {
+ int size = ((cursor->image.width + 7)/8) *
+ cursor->image.height;
+ int i;
+
+ switch (cursor->rop) {
+ case ROP_XOR:
+ for (i = 0; i < size; i++) {
+ data[i] = (cursor->image.data[i] &
+ cursor->mask[i]) ^
+ cursor->dest[i];
+ }
+ break;
+ case ROP_COPY:
+ default:
+ for (i = 0; i < size; i++) {
+ data[i] = cursor->image.data[i] &
+ cursor->mask[i];
+ }
+ break;
+ }
+ i810_load_cursor_image(cursor->image.width,
+ cursor->image.height, data,
+ par);
+ }
+
+ if (cursor->enable)
+ i810_enable_cursor(mmio, ON);
+
+ return 0;
+}
+
+static struct fb_ops i810fb_ops __initdata = {
+ .owner = THIS_MODULE,
+ .fb_open = i810fb_open,
+ .fb_release = i810fb_release,
+ .fb_check_var = i810fb_check_var,
+ .fb_set_par = i810fb_set_par,
+ .fb_setcolreg = i810fb_setcolreg,
+ .fb_blank = i810fb_blank,
+ .fb_pan_display = i810fb_pan_display,
+ .fb_fillrect = i810fb_fillrect,
+ .fb_copyarea = i810fb_copyarea,
+ .fb_imageblit = i810fb_imageblit,
+ .fb_cursor = i810fb_cursor,
+};
+
+/***********************************************************************
+ * AGP resource allocation *
+ ***********************************************************************/
+
+static void __devinit i810_fix_pointers(struct i810fb_par *par)
+{
+ par->fb.physical = par->aperture.physical+(par->fb.offset << 12);
+ par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12);
+ par->iring.physical = par->aperture.physical +
+ (par->iring.offset << 12);
+ par->iring.virtual = par->aperture.virtual +
+ (par->iring.offset << 12);
+ par->cursor_heap.virtual = par->aperture.virtual+
+ (par->cursor_heap.offset << 12);
+ par->pixmap.virtual = par->aperture.virtual +
+ (par->pixmap.offset << 12);
+ par->pixmap.physical = par->aperture.physical +
+ (par->pixmap.offset << 12);
+}
+
+static void __devinit i810_fix_offsets(struct i810fb_par *par)
+{
+ if (vram + 1 > par->aperture.size >> 20)
+ vram = (par->aperture.size >> 20) - 1;
+ if (v_offset_default > (par->aperture.size >> 20))
+ v_offset_default = (par->aperture.size >> 20);
+ if (vram + v_offset_default + 1 > par->aperture.size >> 20)
+ v_offset_default = (par->aperture.size >> 20) - (vram + 1);
+
+ par->fb.size = vram << 20;
+ par->fb.offset = v_offset_default << 20;
+ par->fb.offset >>= 12;
+
+ par->iring.offset = par->fb.offset + (par->fb.size >> 12);
+ par->iring.size = RINGBUFFER_SIZE;
+
+ par->pixmap.offset = par->iring.offset + (RINGBUFFER_SIZE >> 12);
+ par->pixmap.size = PIXMAP_SIZE;
+
+ par->cursor_heap.offset = par->pixmap.offset + (PIXMAP_SIZE >> 12);
+ par->cursor_heap.size = 4096;
+}
+
+static int __devinit i810_alloc_agp_mem(struct fb_info *info)
+{
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+ int size;
+
+ i810_fix_offsets(par);
+ size = par->fb.size + par->iring.size + par->pixmap.size;
+
+ par->drm_agp = (drm_agp_t *) inter_module_get("drm_agp");
+ if (!par->drm_agp) {
+ printk("i810fb: cannot acquire agp\n");
+ return -ENODEV;
+ }
+ par->drm_agp->acquire();
+
+ if (!(par->i810_gtt.i810_fb_memory =
+ par->drm_agp->allocate_memory(size >> 12, AGP_NORMAL_MEMORY))) {
+ printk("i810fb_alloc_fbmem: can't allocate framebuffer "
+ "memory\n");
+ par->drm_agp->release();
+ return -ENOMEM;
+ }
+ if (par->drm_agp->bind_memory(par->i810_gtt.i810_fb_memory,
+ par->fb.offset)) {
+ printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
+ par->drm_agp->release();
+ return -EBUSY;
+ }
+
+ if (!(par->i810_gtt.i810_cursor_memory =
+ par->drm_agp->allocate_memory(par->cursor_heap.size >> 12,
+ AGP_PHYSICAL_MEMORY))) {
+ printk("i810fb_alloc_cursormem: can't allocate"
+ "cursor memory\n");
+ par->drm_agp->release();
+ return -ENOMEM;
+ }
+ if (par->drm_agp->bind_memory(par->i810_gtt.i810_cursor_memory,
+ par->cursor_heap.offset)) {
+ printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
+ par->drm_agp->release();
+ return -EBUSY;
+ }
+
+ par->cursor_heap.physical = par->i810_gtt.i810_cursor_memory->physical;
+
+ i810_fix_pointers(par);
+
+ par->drm_agp->release();
+
+ return 0;
+}
+
+/***************************************************************
+ * Initialization *
+ ***************************************************************/
+
+/**
+ * i810_init_monspecs
+ * @info: pointer to device specific info structure
+ *
+ * DESCRIPTION:
+ * Sets the the user monitor's horizontal and vertical
+ * frequency limits
+ */
+static void __devinit i810_init_monspecs(struct fb_info *info)
+{
+ if (!hsync1)
+ hsync1 = HFMIN;
+ if (!hsync2)
+ hsync2 = HFMAX;
+ info->monspecs.hfmax = hsync2;
+ info->monspecs.hfmin = hsync1;
+ if (hsync2 < hsync1)
+ info->monspecs.hfmin = hsync2;
+
+ if (!vsync1)
+ vsync1 = VFMIN;
+ if (!vsync2)
+ vsync2 = VFMAX;
+ if (IS_DVT && vsync1 < 60)
+ vsync1 = 60;
+ info->monspecs.vfmax = vsync2;
+ info->monspecs.vfmin = vsync1;
+ if (vsync2 < vsync1)
+ info->monspecs.vfmin = vsync2;
+}
+
+/**
+ * i810_init_defaults - initializes default values to use
+ * @par: pointer to i810fb_par structure
+ * @info: pointer to current fb_info structure
+ */
+static void __devinit i810_init_defaults(struct i810fb_par *par,
+ struct fb_info *info)
+{
+ if (voffset) {
+ v_offset_default = voffset;
+ }
+ else {
+ if (par->aperture.size > 32 * 1024 * 1024)
+ v_offset_default = 16;
+ else
+ v_offset_default = 8;
+ }
+
+ if (!vram)
+ vram = 1;
+
+ if (accel)
+ par->dev_flags |= HAS_ACCELERATION;
+
+ if (sync)
+ par->dev_flags |= ALWAYS_SYNC;
+
+ if (bpp < 8)
+ bpp = 8;
+
+ if (!vyres)
+ vyres = (vram << 20)/(xres*bpp >> 3);
+
+ par->i810fb_ops = i810fb_ops;
+ i810fb_default.xres = xres;
+ i810fb_default.yres = yres;
+ i810fb_default.yres_virtual = vyres;
+ i810fb_default.bits_per_pixel = bpp;
+
+ if (dcolor)
+ i810fb_default.nonstd = 1;
+
+ if (par->dev_flags & HAS_ACCELERATION)
+ i810fb_default.accel_flags = 1;
+
+ i810_init_monspecs(info);
+}
+
+/**
+ * i810_init_device - initialize device
+ * @par: pointer to i810fb_par structure
+ */
+static void __devinit i810_init_device(struct i810fb_par *par)
+{
+ u8 reg, *mmio = par->mmio_start_virtual;
+
+ if (mtrr) set_mtrr(par);
+
+ i810_init_cursor(par);
+
+ /* mvo: enable external vga-connector (for laptops) */
+ if (ext_vga) {
+ i810_writel(HVSYNC, mmio, 0);
+ i810_writel(PWR_CLKC, mmio, 3);
+ }
+
+ pci_read_config_byte(par->dev, 0x50, &reg);
+ reg &= FREQ_MASK;
+ par->mem_freq = (reg) ? 133 : 100;
+
+ i810fb_init_ringbuffer(par);
+}
+
+static int __devinit
+i810_allocate_pci_resource(struct i810fb_par *par,
+ const struct pci_device_id *entry)
+{
+ int err;
+
+ if ((err = pci_enable_device(par->dev))) {
+ printk("i810fb_init: cannot enable device\n");
+ return err;
+ }
+ par->res_flags |= PCI_DEVICE_ENABLED;
+
+ if (pci_resource_len(par->dev, 0) > 512 * 1024) {
+ par->aperture.physical = pci_resource_start(par->dev, 0);
+ par->aperture.size = pci_resource_len(par->dev, 0);
+ par->mmio_start_phys = pci_resource_start(par->dev, 1);
+ }
+ else {
+ par->aperture.physical = pci_resource_start(par->dev, 1);
+ par->aperture.size = pci_resource_len(par->dev, 1);
+ par->mmio_start_phys = pci_resource_start(par->dev, 0);
+ }
+ if (!par->aperture.size) {
+ printk("i810fb_init: device is disabled\n");
+ return -ENOMEM;
+ }
+
+ if (!request_mem_region(par->aperture.physical,
+ par->aperture.size,
+ i810_pci_list[entry->driver_data])) {
+ printk("i810fb_init: cannot request framebuffer region\n");
+ return -ENODEV;
+ }
+ par->res_flags |= FRAMEBUFFER_REQ;
+
+ par->aperture.virtual = ioremap(par->aperture.physical,
+ par->aperture.size);
+ if (!par->aperture.virtual) {
+ printk("i810fb_init: cannot remap framebuffer region\n");
+ return -ENODEV;
+ }
+
+ if (!request_mem_region(par->mmio_start_phys,
+ MMIO_SIZE,
+ i810_pci_list[entry->driver_data])) {
+ printk("i810fb_init: cannot request mmio region\n");
+ return -ENODEV;
+ }
+ par->res_flags |= MMIO_REQ;
+
+ par->mmio_start_virtual = ioremap_nocache(par->mmio_start_phys,
+ MMIO_SIZE);
+ if (!par->mmio_start_virtual) {
+ printk("i810fb_init: cannot remap mmio region\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+int __init i810fb_setup(char *options)
+{
+ char *this_opt, *suffix = NULL;
+
+ i810_init = 1;
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!strncmp(this_opt, "mtrr", 4))
+ mtrr = 1;
+ else if (!strncmp(this_opt, "accel", 5))
+ accel = 1;
+ else if (!strncmp(this_opt, "ext_vga", 7))
+ ext_vga = 1;
+ else if (!strncmp(this_opt, "sync", 4))
+ sync = 1;
+ else if (!strncmp(this_opt, "vram:", 5))
+ vram = (simple_strtoul(this_opt+5, NULL, 0));
+ else if (!strncmp(this_opt, "voffset:", 8))
+ voffset = (simple_strtoul(this_opt+8, NULL, 0));
+ else if (!strncmp(this_opt, "xres:", 5))
+ xres = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "yres:", 5))
+ yres = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "vyres:", 6))
+ vyres = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "bpp:", 4))
+ bpp = simple_strtoul(this_opt+4, NULL, 0);
+ else if (!strncmp(this_opt, "hsync1:", 7)) {
+ hsync1 = simple_strtoul(this_opt+7, &suffix, 0);
+ if (strncmp(suffix, "H", 1))
+ hsync1 *= 1000;
+ }
+ else if (!strncmp(this_opt, "hsync2:", 7)) {
+ hsync2 = simple_strtoul(this_opt+7, &suffix, 0);
+ if (strncmp(suffix, "H", 1))
+ hsync2 *= 1000;
+ }
+ else if (!strncmp(this_opt, "vsync1:", 7))
+ vsync1 = simple_strtoul(this_opt+7, NULL, 0);
+ else if (!strncmp(this_opt, "vsync2:", 7))
+ vsync2 = simple_strtoul(this_opt+7, NULL, 0);
+ else if (!strncmp(this_opt, "dcolor", 6))
+ dcolor = 1;
+ }
+ return 0;
+}
+
+static int __devinit i810fb_init_pci (struct pci_dev *dev,
+ const struct pci_device_id *entry)
+{
+ struct fb_info *info;
+ struct i810fb_par *par = NULL;
+ int err, vfreq, hfreq, pixclock;
+
+ if (!i810_init)
+ return -EINVAL;
+
+ if (!(info = kmalloc(sizeof(struct fb_info), GFP_KERNEL))) {
+ i810fb_release_resource(info, par);
+ return -ENOMEM;
+ }
+ memset(info, 0, sizeof(struct fb_info));
+
+ if(!(par = kmalloc(sizeof(struct i810fb_par), GFP_KERNEL))) {
+ i810fb_release_resource(info, par);
+ return -ENOMEM;
+ }
+ memset(par, 0, sizeof(struct i810fb_par));
+
+ par->dev = dev;
+ info->par = par;
+
+ if ((err = i810_allocate_pci_resource(par, entry))) {
+ i810fb_release_resource(info, par);
+ return err;
+ }
+
+ i810_init_defaults(par, info);
+
+ if ((err = i810_alloc_agp_mem(info))) {
+ i810fb_release_resource(info, par);
+ return err;
+ }
+
+ i810_init_device(par);
+
+ info->screen_base = par->fb.virtual;
+ info->node = NODEV;
+ info->fbops = &par->i810fb_ops;
+ info->pseudo_palette = par->pseudo_palette;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ fb_alloc_cmap(&info->cmap, 256, 0);
+
+ info->var = i810fb_default;
+ if ((err = info->fbops->fb_check_var(&info->var, info))) {
+ i810fb_release_resource(info, par);
+ return err;
+ }
+ encode_fix(&info->fix, info);
+
+ err = register_framebuffer(info);
+ if (err < 0) {
+ i810fb_release_resource(info, par);
+ printk("i810fb_init: cannot register framebuffer device\n");
+ return err;
+ }
+
+ pci_set_drvdata(dev, info);
+ pixclock = 1000000000/(info->var.pixclock);
+ pixclock *= 1000;
+ hfreq = pixclock/(info->var.xres + info->var.left_margin +
+ info->var.hsync_len + info->var.right_margin);
+ vfreq = hfreq/(info->var.yres + info->var.upper_margin +
+ info->var.vsync_len + info->var.lower_margin);
+ printk("fb: %s v%d.%d.%d%s, Tony Daplas\n"
+ " Video RAM : %dK\n"
+ " Mode : %dx%d-%dbpp@%dHz\n"
+ " Acceleration : %sabled\n"
+ " MTRR : %sabled\n"
+ " External VGA : %sabled\n"
+ " Video Timings : %s\n",
+ i810_pci_list[entry->driver_data],
+ VERSION_MAJOR, VERSION_MINOR, VERSION_TEENIE, BRANCH_VERSION,
+ (int) par->fb.size>>10, info->var.xres,
+ info->var.yres, info->var.bits_per_pixel, vfreq,
+ (par->dev_flags & HAS_ACCELERATION) ? "en" : "dis",
+ (par->dev_flags & HAS_MTRR) ? "en" : "dis",
+ (ext_vga) ? "en" : "dis", (IS_DVT) ?
+ "Intel(R) DVT" : "VESA GTF (US)");
+
+
+ return 0;
+}
+
+/***************************************************************
+ * Deinitialization *
+ ***************************************************************/
+
+static void i810fb_release_resource(struct fb_info *info,
+ struct i810fb_par *par)
+{
+ if (par) {
+ unset_mtrr(par);
+ if (par->drm_agp) {
+ drm_agp_t *agp = par->drm_agp;
+ struct gtt_data *gtt = &par->i810_gtt;
+
+ if (par->i810_gtt.i810_cursor_memory)
+ agp->free_memory(gtt->i810_cursor_memory);
+ if (par->i810_gtt.i810_fb_memory)
+ agp->free_memory(gtt->i810_fb_memory);
+
+ inter_module_put("drm_agp");
+ par->drm_agp = NULL;
+ }
+
+ if (par->mmio_start_virtual)
+ iounmap(par->mmio_start_virtual);
+ if (par->aperture.virtual)
+ iounmap(par->aperture.virtual);
+
+ if (par->res_flags & FRAMEBUFFER_REQ)
+ release_mem_region(par->aperture.physical,
+ par->aperture.size);
+ if (par->res_flags & MMIO_REQ)
+ release_mem_region(par->mmio_start_phys, MMIO_SIZE);
+
+ if (par->res_flags & PCI_DEVICE_ENABLED)
+ pci_disable_device(par->dev);
+
+ kfree(par);
+ }
+ if (info)
+ kfree(info);
+}
+
+static void __devexit i810fb_remove_pci(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct i810fb_par *par = (struct i810fb_par *) info->par;
+
+ unregister_framebuffer(info);
+ i810fb_release_resource(info, par);
+ pci_set_drvdata(dev, NULL);
+ printk("cleanup_module: unloaded i810 framebuffer device\n");
+}
+
+#ifndef MODULE
+int __init i810fb_init(void)
+{
+ if (agp_init()) {
+ printk("i810fb_init: cannot initialize agpgart\n");
+ return -ENODEV;
+ }
+
+ if (agp_intel_init()) {
+ printk("i810fb_init: cannot initialize intel agpgart\n");
+ return -ENODEV;
+ }
+
+ return (pci_module_init(&i810fb_driver));
+}
+#endif
+
+/*********************************************************************
+ * Modularization *
+ *********************************************************************/
+
+#ifdef MODULE
+
+int __init i810fb_init(void)
+{
+ i810_init = 1;
+ hsync1 *= 1000;
+ hsync2 *= 1000;
+
+ return (pci_module_init(&i810fb_driver));
+}
+
+MODULE_PARM(vram, "i");
+MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB"
+ " (default=4)");
+MODULE_PARM(voffset, "i");
+MODULE_PARM_DESC(voffset, "at what offset to place start of framebuffer "
+ "memory (0 to maximum aperture size), in MiB (default = 48)");
+MODULE_PARM(bpp, "i");
+MODULE_PARM_DESC(bpp, "Color depth for display in bits per pixel"
+ " (default = 8)");
+MODULE_PARM(xres, "i");
+MODULE_PARM_DESC(xres, "Hozizontal resolution in pixels (default = 640)");
+MODULE_PARM(yres, "i");
+MODULE_PARM_DESC(yres, "Vertical resolution in scanlines (default = 480)");
+MODULE_PARM(vyres, "i");
+MODULE_PARM_DESC(vyres, "Virtual vertical resolution in scanlines"
+ " (default = 480)");
+MODULE_PARM(hsync1, "i");
+MODULE_PARM_DESC(hsync1, "Mimimum horizontal frequency of monitor in KHz"
+ " (default = 31)");
+MODULE_PARM(hsync2, "i");
+MODULE_PARM_DESC(hsync2, "Maximum horizontal frequency of monitor in KHz"
+ " (default = 31)");
+MODULE_PARM(vsync1, "i");
+MODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz"
+ " (default = 50)");
+MODULE_PARM(vsync2, "i");
+MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz"
+ " (default = 60)");
+MODULE_PARM(accel, "i");
+MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
+MODULE_PARM(mtrr, "i");
+MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
+MODULE_PARM(ext_vga, "i");
+MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)");
+MODULE_PARM(sync, "i");
+MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
+ " (default = 0)");
+MODULE_PARM(dcolor, "i");
+MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
+ " (default = 0 = TrueColor)");
+
+MODULE_AUTHOR("Tony A. Daplas");
+MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
+ " compatible cards");
+MODULE_LICENSE("GPL");
+
+static void __exit i810fb_exit(void)
+{
+ pci_unregister_driver(&i810fb_driver);
+}
+module_init(i810fb_init);
+module_exit(i810fb_exit);
+
+#endif /* MODULE */
+
+
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
new file mode 100644
index 000000000000..cbc80aa11e0b
--- /dev/null
+++ b/drivers/video/i810/i810_main.h
@@ -0,0 +1,205 @@
+/*-*- linux-c -*-
+ * linux/drivers/video/i810fb_main.h -- Intel 810 frame buffer device
+ * main header file
+ *
+ * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef __I810_MAIN_H__
+#define __I810_MAIN_H__
+
+
+/* PCI */
+static const char *i810_pci_list[] __devinitdata = {
+ "Intel(R) 810 Framebuffer Device" ,
+ "Intel(R) 810-DC100 Framebuffer Device" ,
+ "Intel(R) 810E Framebuffer Device" ,
+ "Intel(R) 815 (Internal Graphics 100Mhz FSB) Framebuffer Device" ,
+ "Intel(R) 815 (Internal Graphics only) Framebuffer Device" ,
+ "Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device"
+};
+
+static struct pci_device_id i810fb_pci_tbl[] __devinitdata = {
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
+ /* mvo: added i815 PCI-ID */
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_NOAGP,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }
+};
+
+static int __devinit i810fb_init_pci (struct pci_dev *dev,
+ const struct pci_device_id *entry);
+static void __devexit i810fb_remove_pci(struct pci_dev *dev);
+
+static struct pci_driver i810fb_driver = {
+ .name = "i810fb",
+ .id_table = i810fb_pci_tbl,
+ .probe = i810fb_init_pci,
+ .remove = __devexit_p(i810fb_remove_pci),
+};
+
+static int i810_init __devinitdata = 0;
+static int vram __devinitdata = 4;
+static int bpp __devinitdata = 8;
+static int mtrr __devinitdata = 0;
+static int accel __devinitdata = 0;
+static int hsync1 __devinitdata = 0;
+static int hsync2 __devinitdata = 0;
+static int vsync1 __devinitdata = 0;
+static int vsync2 __devinitdata = 0;
+static int xres __devinitdata = 640;
+static int yres __devinitdata = 480;
+static int vyres __devinitdata = 0;
+static int sync __devinitdata = 0;
+static int ext_vga __devinitdata = 0;
+static int dcolor __devinitdata = 0;
+
+/* "use once" vars */
+static char i810fb_name[16] = "i810fb";
+static struct fb_var_screeninfo i810fb_default __devinitdata = {
+ /* 640x480, 8 bpp */
+ .xres = 640,
+ .yres = 480,
+ .xres_virtual = 640,
+ .yres_virtual = 480,
+ .xoffset = 0,
+ .yoffset = 0,
+ .bits_per_pixel = 8,
+ .grayscale = 0,
+ .red = {0, 8, 0},
+ .green = {0, 8, 0},
+ .blue = {0, 8, 0},
+ .transp = {0, 0, 0},
+ .nonstd = 0,
+ .activate = 0,
+ .height = -1,
+ .width = -1,
+ .accel_flags = 0,
+ .pixclock = 20000,
+ .left_margin = 64,
+ .right_margin = 64,
+ .upper_margin = 32,
+ .lower_margin = 32,
+ .hsync_len = 64,
+ .vsync_len = 2,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
+/*
+ * voffset - framebuffer offset in MiB from aperture start address. In order for
+ * the driver to work with X, we must try to use memory holes left untouched by X. The
+ * following table lists where X's different surfaces start at.
+ *
+ * ---------------------------------------------
+ * : : 64 MiB : 32 MiB :
+ * ----------------------------------------------
+ * : FrontBuffer : 0 : 0 :
+ * : DepthBuffer : 48 : 16 :
+ * : BackBuffer : 56 : 24 :
+ * ----------------------------------------------
+ *
+ * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
+ * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should
+ * work, allowing 7 + 1 MiB of Framebuffer memory.
+ * Note, the size of the hole may change depending on how much memory you allocate to X,
+ * and how the memory is split up between these surfaces.
+ *
+ * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
+ * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load.
+ *
+ * Experiment with v_offset to find out which works best for you.
+ */
+static u32 v_offset_default __devinitdata; /* For 32 MiB Aper size, 8 should be the default */
+static u32 voffset __devinitdata = 0;
+
+static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+
+/* Chipset Specific Functions */
+static int i810fb_set_par (struct fb_info *info);
+static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue,
+ u8 *transp, struct fb_info *info);
+static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info);
+static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+static int i810fb_blank (int blank_mode, struct fb_info *info);
+
+/* Initialization */
+static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par);
+extern int __init agp_intel_init(void);
+extern int __init agp_init(void);
+
+
+/* Video Timings */
+extern void round_off_xres (u32 *xres);
+extern void round_off_yres (u32 *xres, u32 *yres);
+extern u32 i810_get_watermark (const struct fb_var_screeninfo *var,
+ struct i810fb_par *par);
+extern void i810fb_encode_registers(const struct fb_var_screeninfo *var,
+ struct i810fb_par *par, u32 xres, u32 yres);
+extern void i810fb_fill_var_timings(struct fb_var_screeninfo *var);
+
+/* Accelerated Functions */
+extern void i810fb_fillrect (struct fb_info *p, struct fb_fillrect *rect);
+extern void i810fb_copyarea (struct fb_info *p, struct fb_copyarea *region);
+extern void i810fb_imageblit(struct fb_info *p, struct fb_image *image);
+extern int i810fb_sync (struct fb_info *p);
+
+extern void i810fb_init_ringbuffer (struct i810fb_par *par);
+
+/* Conditionals */
+#if defined(__i386__)
+inline void flush_cache(void)
+{
+ asm volatile ("wbinvd":::"memory");
+}
+#else
+#define flush_cache() do { } while(0)
+#endif
+
+#ifdef CONFIG_MTRR
+#define KERNEL_HAS_MTRR 1
+static inline void __devinit set_mtrr(struct i810fb_par *par)
+{
+ par->mtrr_reg = mtrr_add((u32) par->aperture.physical,
+ par->aperture.size, MTRR_TYPE_WRCOMB, 1);
+ if (par->mtrr_reg < 0) {
+ printk("set_mtrr: unable to set MTRR/n");
+ return;
+ }
+ par->dev_flags |= HAS_MTRR;
+}
+static inline void unset_mtrr(struct i810fb_par *par)
+{
+ if (par->dev_flags & HAS_MTRR)
+ mtrr_del(par->mtrr_reg, (u32) par->aperture.physical,
+ par->aperture.size);
+}
+#else
+#define KERNEL_HAS_MTRR 0
+#define set_mtrr(x) printk("set_mtrr: MTRR is disabled in the kernel\n")
+
+#define unset_mtrr(x) do { } while (0)
+#endif /* CONFIG_MTRR */
+
+#ifdef CONFIG_FB_I810_GTF
+#define IS_DVT (0)
+#else
+#define IS_DVT (1)
+#endif
+
+#endif /* __I810_MAIN_H__ */
diff --git a/drivers/video/i810/i810_regs.h b/drivers/video/i810/i810_regs.h
new file mode 100644
index 000000000000..6e4b9afa4d98
--- /dev/null
+++ b/drivers/video/i810/i810_regs.h
@@ -0,0 +1,274 @@
+/*-*- linux-c -*-
+ * linux/drivers/video/i810_regs.h -- Intel 810/815 Register List
+ *
+ * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+
+/*
+ * Intel 810 Chipset Family PRM 15 3.1
+ * GC Register Memory Address Map
+ *
+ * Based on:
+ * Intel (R) 810 Chipset Family
+ * Programmer s Reference Manual
+ * November 1999
+ * Revision 1.0
+ * Order Number: 298026-001 R
+ *
+ * All GC registers are memory-mapped. In addition, the VGA and extended VGA registers
+ * are I/O mapped.
+ */
+
+#ifndef __I810_REGS_H__
+#define __I810_REGS_H__
+
+/* Instruction and Interrupt Control Registers (01000h 02FFFh) */
+#define FENCE 0x02000
+#define PGTBL_CTL 0x02020
+#define PGTBL_ER 0x02024
+#define LRING 0x02030
+#define IRING 0x02040
+#define HWS_PGA 0x02080
+#define IPEIR 0x02088
+#define IPEHR 0x0208C
+#define INSTDONE 0x02090
+#define NOPID 0x02094
+#define HWSTAM 0x02098
+#define IER 0x020A0
+#define IIR 0x020A4
+#define IMR 0x020A8
+#define ISR 0x020AC
+#define EIR 0x020B0
+#define EMR 0x020B4
+#define ESR 0x020B8
+#define INSTPM 0x020C0
+#define INSTPS 0x020C4
+#define BBP_PTR 0x020C8
+#define ABB_SRT 0x020CC
+#define ABB_END 0x020D0
+#define DMA_FADD 0x020D4
+#define FW_BLC 0x020D8
+#define MEM_MODE 0x020DC
+
+/* Memory Control Registers (03000h 03FFFh) */
+#define DRT 0x03000
+#define DRAMCL 0x03001
+#define DRAMCH 0x03002
+
+
+/* Span Cursor Registers (04000h 04FFFh) */
+#define UI_SC_CTL 0x04008
+
+/* I/O Control Registers (05000h 05FFFh) */
+#define HVSYNC 0x05000
+#define GPIOA 0x05010
+#define GPIOB 0x05014
+
+/* Clock Control and Power Management Registers (06000h 06FFFh) */
+#define DCLK_0D 0x06000
+#define DCLK_1D 0x06004
+#define DCLK_2D 0x06008
+#define LCD_CLKD 0x0600C
+#define DCLK_0DS 0x06010
+#define PWR_CLKC 0x06014
+
+/* Graphics Translation Table Range Definition (10000h 1FFFFh) */
+#define GTT 0x10000
+
+/* Overlay Registers (30000h 03FFFFh) */
+#define OVOADDR 0x30000
+#define DOVOSTA 0x30008
+#define GAMMA 0x30010
+#define OBUF_0Y 0x30100
+#define OBUF_1Y 0x30104
+#define OBUF_0U 0x30108
+#define OBUF_0V 0x3010C
+#define OBUF_1U 0x30110
+#define OBUF_1V 0x30114
+#define OVOSTRIDE 0x30118
+#define YRGB_VPH 0x3011C
+#define UV_VPH 0x30120
+#define HORZ_PH 0x30124
+#define INIT_PH 0x30128
+#define DWINPOS 0x3012C
+#define DWINSZ 0x30130
+#define SWID 0x30134
+#define SWIDQW 0x30138
+#define SHEIGHT 0x3013F
+#define YRGBSCALE 0x30140
+#define UVSCALE 0x30144
+#define OVOCLRCO 0x30148
+#define OVOCLRC1 0x3014C
+#define DCLRKV 0x30150
+#define DLCRKM 0x30154
+#define SCLRKVH 0x30158
+#define SCLRKVL 0x3015C
+#define SCLRKM 0x30160
+#define OVOCONF 0x30164
+#define OVOCMD 0x30168
+#define AWINPOS 0x30170
+#define AWINZ 0x30174
+
+/* BLT Engine Status (40000h 4FFFFh) (Software Debug) */
+#define BR00 0x40000
+#define BRO1 0x40004
+#define BR02 0x40008
+#define BR03 0x4000C
+#define BR04 0x40010
+#define BR05 0x40014
+#define BR06 0x40018
+#define BR07 0x4001C
+#define BR08 0x40020
+#define BR09 0x40024
+#define BR10 0x40028
+#define BR11 0x4002C
+#define BR12 0x40030
+#define BR13 0x40034
+#define BR14 0x40038
+#define BR15 0x4003C
+#define BR16 0x40040
+#define BR17 0x40044
+#define BR18 0x40048
+#define BR19 0x4004C
+#define SSLADD 0x40074
+#define DSLH 0x40078
+#define DSLRADD 0x4007C
+
+
+/* LCD/TV-Out and HW DVD Registers (60000h 6FFFFh) */
+/* LCD/TV-Out */
+#define HTOTAL 0x60000
+#define HBLANK 0x60004
+#define HSYNC 0x60008
+#define VTOTAL 0x6000C
+#define VBLANK 0x60010
+#define VSYNC 0x60014
+#define LCDTV_C 0x60018
+#define OVRACT 0x6001C
+#define BCLRPAT 0x60020
+
+/* Display and Cursor Control Registers (70000h 7FFFFh) */
+#define DISP_SL 0x70000
+#define DISP_SLC 0x70004
+#define PIXCONF 0x70008
+#define PIXCONF1 0x70009
+#define BLTCNTL 0x7000C
+#define SWF 0x70014
+#define DPLYBASE 0x70020
+#define DPLYSTAS 0x70024
+#define CURCNTR 0x70080
+#define CURBASE 0x70084
+#define CURPOS 0x70088
+
+
+/* VGA Registers */
+
+/* SMRAM Registers */
+#define SMRAM 0x10
+
+/* Graphics Control Registers */
+#define GR_INDEX 0x3CE
+#define GR_DATA 0x3CF
+
+#define GR10 0x10
+#define GR11 0x11
+
+/* CRT Controller Registers */
+#define CR_INDEX_MDA 0x3B4
+#define CR_INDEX_CGA 0x3D4
+#define CR_DATA_MDA 0x3B5
+#define CR_DATA_CGA 0x3D5
+
+#define CR30 0x30
+#define CR31 0x31
+#define CR32 0x32
+#define CR33 0x33
+#define CR35 0x35
+#define CR39 0x39
+#define CR40 0x40
+#define CR41 0x41
+#define CR42 0x42
+#define CR70 0x70
+#define CR80 0x80
+#define CR81 0x82
+
+/* Extended VGA Registers */
+
+/* General Control and Status Registers */
+#define ST00 0x3C2
+#define ST01_MDA 0x3BA
+#define ST01_CGA 0x3DA
+#define FRC_READ 0x3CA
+#define FRC_WRITE_MDA 0x3BA
+#define FRC_WRITE_CGA 0x3DA
+#define MSR_READ 0x3CC
+#define MSR_WRITE 0x3C2
+
+/* Sequencer Registers */
+#define SR_INDEX 0x3C4
+#define SR_DATA 0x3C5
+
+#define SR01 0x01
+#define SR02 0x02
+#define SR03 0x03
+#define SR04 0x04
+#define SR07 0x07
+
+/* Graphics Controller Registers */
+#define GR00 0x00
+#define GR01 0x01
+#define GR02 0x02
+#define GR03 0x03
+#define GR04 0x04
+#define GR05 0x05
+#define GR06 0x06
+#define GR07 0x07
+#define GR08 0x08
+
+/* Attribute Controller Registers */
+#define ATTR_WRITE 0x3C0
+#define ATTR_READ 0x3C1
+
+/* VGA Color Palette Registers */
+
+/* CLUT */
+#define CLUT_DATA 0x3C9 /* DACDATA */
+#define CLUT_INDEX_READ 0x3C7 /* DACRX */
+#define CLUT_INDEX_WRITE 0x3C8 /* DACWX */
+#define DACMASK 0x3C6
+
+/* CRT Controller Registers */
+#define CR00 0x00
+#define CR01 0x01
+#define CR02 0x02
+#define CR03 0x03
+#define CR04 0x04
+#define CR05 0x05
+#define CR06 0x06
+#define CR07 0x07
+#define CR08 0x08
+#define CR09 0x09
+#define CR0A 0x0A
+#define CR0B 0x0B
+#define CR0C 0x0C
+#define CR0D 0x0D
+#define CR0E 0x0E
+#define CR0F 0x0F
+#define CR10 0x10
+#define CR11 0x11
+#define CR12 0x12
+#define CR13 0x13
+#define CR14 0x14
+#define CR15 0x15
+#define CR16 0x16
+#define CR17 0x17
+#define CR18 0x18
+
+#endif /* __I810_REGS_H__ */
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index f72ab497c041..4102c3fac1e3 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -75,36 +75,96 @@ struct fb_fix_screeninfo igafb_fix __initdata = {
};
struct fb_var_screeninfo default_var = {
- /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
- 640, 480, 640, 480, 0, 0, 8, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
- 0, FB_VMODE_NONINTERLACED
+ /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+ .xres = 640,
+ .yres = 480,
+ .xres_virtual = 640,
+ .yres_virtual = 480,
+ .bits_per_pixel = 8,
+ .red = {0, 8, 0 },
+ .green = {0, 8, 0 },
+ .blue = {0, 8, 0 },
+ .height = -1,
+ .width = -1,
+ .accel_flags = FB_ACCEL_NONE,
+ .pixclock = 39722,
+ .left_margin = 48,
+ .right_margin = 16,
+ .upper_margin = 33,
+ .lower_margin = 10,
+ .hsync_len = 96,
+ .vsync_len = 2,
+ .vmode = FB_VMODE_NONINTERLACED
};
#ifdef __sparc__
struct fb_var_screeninfo default_var_1024x768 __initdata = {
- /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
- 1024, 768, 1024, 768, 0, 0, 8, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 12699, 176, 16, 28, 1, 96, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+ .xres = 1024,
+ .yres = 768,
+ .xres_virtual = 1024,
+ .yres_virtual = 768,
+ .bits_per_pixel = 8,
+ .red = {0, 8, 0 },
+ .green = {0, 8, 0 },
+ .blue = {0, 8, 0 },
+ .height = -1,
+ .width = -1,
+ .accel_flags = FB_ACCEL_NONE,
+ .pixclock = 12699,
+ .left_margin = 176,
+ .right_margin = 16,
+ .upper_margin = 28,
+ .lower_margin = 1,
+ .hsync_len = 96,
+ .vsync_len = 3,
+ .vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
};
struct fb_var_screeninfo default_var_1152x900 __initdata = {
- /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
- 1152, 900, 1152, 900, 0, 0, 8, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 9091, 234, 24, 34, 3, 100, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
+ .xres = 1152,
+ .yres = 900,
+ .xres_virtual = 1152,
+ .yres_virtual = 900,
+ .bits_per_pixel = 8,
+ .red = { 0, 8, 0 },
+ .green = { 0, 8, 0 },
+ .blue = { 0, 8, 0 },
+ .height = -1,
+ .width = -1,
+ .accel_flags = FB_ACCEL_NONE,
+ .pixclock = 9091,
+ .left_margin = 234,
+ .right_margin = 24,
+ .upper_margin = 34,
+ .lower_margin = 3,
+ .hsync_len = 100,
+ .vsync_len = 3,
+ .vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
};
struct fb_var_screeninfo default_var_1280x1024 __initdata = {
- /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
- 1280, 1024, 1280, 1024, 0, 0, 8, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 7408, 248, 16, 38, 1, 144, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
+ .xres = 1280,
+ .yres = 1024,
+ .xres_virtual = 1280,
+ .yres_virtaul = 1024,
+ .bits_per_pixel = 8,
+ .red = {0, 8, 0 },
+ .green = {0, 8, 0 },
+ .blue = {0, 8, 0 },
+ .height = -1,
+ .width = -1,
+ .accel_flags = 0,
+ .pixclock = 7408,
+ .left_margin = 248,
+ .right_margin = 16,
+ .upper_margin = 38,
+ .lower_margin = 1,
+ .hsync_len = 144,
+ .vsync_len = 3,
+ .vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
};
/*
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index f772815444b3..57ecfbeb7471 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -393,6 +393,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
struct fb_fix_screeninfo *fix;
struct fb_var_screeninfo *var;
struct fb_info *info;
+ int size;
if (!request_mem_region(res_start, res_size, "offb"))
return;
@@ -421,7 +422,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
var = &info->var;
strcpy(fix->id, "OFfb ");
- strncat(fix->id, name, sizeof(fix->id));
+ strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb "));
fix->id[sizeof(fix->id) - 1] = '\0';
var->xres = var->xres_virtual = width;
@@ -522,8 +523,6 @@ static void __init offb_init_fb(const char *name, const char *full_name,
var->sync = 0;
var->vmode = FB_VMODE_NONINTERLACED;
- strcpy(fix->id, "OFfb ");
- strncat(fix->id, full_name, sizeof(fix->id));
info->node = NODEV;
info->fbops = &offb_ops;
info->screen_base = ioremap(address, fix->smem_len);
diff --git a/drivers/video/pmagb-b-fb.h b/drivers/video/pmagb-b-fb.h
index e93eafa49407..87b81a555139 100644
--- a/drivers/video/pmagb-b-fb.h
+++ b/drivers/video/pmagb-b-fb.h
@@ -4,7 +4,7 @@
* TurboChannel PMAGB-B framebuffer card support,
* Copyright (C) 1999, 2000, 2001 by
* Michael Engel <engel@unix-ag.org> and
- * Karsten Merker <merker@linxutag.org>
+ * Karsten Merker <merker@linuxtag.org>
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index ea8466a9bd7a..75163341953c 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -361,8 +361,6 @@ struct radeonfb_info {
unsigned char *EDID;
unsigned char *bios_seg;
- struct display disp; /* Will disappear */
-
u32 pseudo_palette[17];
struct { u8 red, green, blue, pad; } palette[256];
@@ -1289,7 +1287,7 @@ static int __devinit radeon_init_disp (struct radeonfb_info *rinfo)
fb_alloc_cmap(&info->cmap, 256, 0);
var.activate = FB_ACTIVATE_NOW;
- gen_set_var(&var, -1, info);
+ fb_set_var(&var, info);
return 0;
}
@@ -1508,7 +1506,7 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, int con, struct fb_info *info)
+ unsigned long arg, struct fb_info *info)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
unsigned int tmp;
@@ -1872,14 +1870,26 @@ static int radeonfb_set_par (struct fb_info *info)
newmode.crtc_pitch |= (newmode.crtc_pitch << 16);
#if defined(__BIG_ENDIAN)
- newmode.surface_cntl = SURF_TRANSLATION_DIS;
+ /*
+ * It looks like recent chips have a problem with SURFACE_CNTL,
+ * setting SURF_TRANSLATION_DIS completely disables the
+ * swapper as well, so we leave it unset now.
+ */
+ newmode.surface_cntl = 0;
+
+ /* Setup swapping on both apertures, though we currently
+ * only use aperture 0, enabling swapper on aperture 1
+ * won't harm
+ */
switch (mode->bits_per_pixel) {
case 16:
newmode.surface_cntl |= NONSURF_AP0_SWP_16BPP;
+ newmode.surface_cntl |= NONSURF_AP1_SWP_16BPP;
break;
case 24:
case 32:
newmode.surface_cntl |= NONSURF_AP0_SWP_32BPP;
+ newmode.surface_cntl |= NONSURF_AP1_SWP_32BPP;
break;
}
#endif
@@ -1934,7 +1944,12 @@ static int radeonfb_set_par (struct fb_info *info)
newmode.ppll_div_3 = rinfo->fb_div | (post_div->bitvalue << 16);
}
newmode.vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl;
-
+
+#ifdef CONFIG_ALL_PPC
+ /* Gross hack for iBook with M7 until I find out a proper fix */
+ if (machine_is_compatible("PowerBook4,3") && rinfo->arch == RADEON_M7)
+ newmode.ppll_div_3 = 0x000600ad;
+#endif /* CONFIG_ALL_PPC */
RTRACE("post div = 0x%x\n", rinfo->post_div);
RTRACE("fb_div = 0x%x\n", rinfo->fb_div);
@@ -2206,12 +2221,8 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
info = &rinfo->info;
- // XXX ???
- strncpy (info->modename, rinfo->name, sizeof(info->modename));
-
info->currcon = -1;
info->par = rinfo;
- info->disp = &rinfo->disp;
info->pseudo_palette = rinfo->pseudo_palette;
info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT;
@@ -2273,7 +2284,12 @@ static int radeon_set_backlight_enable(int on, int level, void *data)
unsigned int lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
int* conv_table;
- if (rinfo->arch == RADEON_M7)
+ /* Pardon me for that hack... maybe some day we can figure
+ * out in what direction backlight should work on a given
+ * panel ?
+ */
+ if ((rinfo->arch == RADEON_M7 || rinfo->arch == RADEON_M9)
+ && !machine_is_compatible("PowerBook4,3"))
conv_table = backlight_conv_m7;
else
conv_table = backlight_conv_m6;
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 0a44e6dc6a70..67d4c6550d5e 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -50,7 +50,7 @@
#endif
/* version number of this driver */
-#define RIVAFB_VERSION "0.9.3"
+#define RIVAFB_VERSION "0.9.4"
/* ------------------------------------------------------------------------- *
*
@@ -114,23 +114,43 @@ enum riva_chips {
CH_RIVA_128 = 0,
CH_RIVA_TNT,
CH_RIVA_TNT2,
- CH_RIVA_UTNT2, /* UTNT2 */
- CH_RIVA_VTNT2, /* VTNT2 */
- CH_RIVA_UVTNT2, /* VTNT2 */
- CH_RIVA_ITNT2, /* ITNT2 */
+ CH_RIVA_UTNT2,
+ CH_RIVA_VTNT2,
+ CH_RIVA_UVTNT2,
+ CH_RIVA_ITNT2,
CH_GEFORCE_SDR,
CH_GEFORCE_DDR,
CH_QUADRO,
CH_GEFORCE2_MX,
+ CH_GEFORCE2_MX2,
+ CH_GEFORCE2_GO,
CH_QUADRO2_MXR,
CH_GEFORCE2_GTS,
+ CH_GEFORCE2_GTS2,
CH_GEFORCE2_ULTRA,
CH_QUADRO2_PRO,
- CH_GEFORCE2_GO,
- CH_GEFORCE3,
- CH_GEFORCE3_1,
- CH_GEFORCE3_2,
- CH_QUADRO_DDC
+ CH_GEFORCE4_MX_460,
+ CH_GEFORCE4_MX_440,
+ CH_GEFORCE4_MX_420,
+ CH_GEFORCE4_440_GO,
+ CH_GEFORCE4_420_GO,
+ CH_GEFORCE4_420_GO_M32,
+ CH_QUADRO4_500XGL,
+ CH_GEFORCE4_440_GO_M64,
+ CH_QUADRO4_200,
+ CH_QUADRO4_550XGL,
+ CH_QUADRO4_500_GOGL,
+ CH_IGEFORCE2,
+ CH_GEFORCE3,
+ CH_GEFORCE3_1,
+ CH_GEFORCE3_2,
+ CH_QUADRO_DDC,
+ CH_GEFORCE4_TI_4600,
+ CH_GEFORCE4_TI_4400,
+ CH_GEFORCE4_TI_4200,
+ CH_QUADRO4_900XGL,
+ CH_QUADRO4_750XGL,
+ CH_QUADRO4_700XGL
};
/* directly indexed by riva_chips enum, above */
@@ -149,15 +169,35 @@ static struct riva_chip_info {
{ "GeForce-DDR", NV_ARCH_10},
{ "Quadro", NV_ARCH_10},
{ "GeForce2-MX", NV_ARCH_10},
+ { "GeForce2-MX", NV_ARCH_10},
+ { "GeForce2-Go", NV_ARCH_10},
{ "Quadro2-MXR", NV_ARCH_10},
{ "GeForce2-GTS", NV_ARCH_10},
+ { "GeForce2-GTS", NV_ARCH_10},
{ "GeForce2-ULTRA", NV_ARCH_10},
{ "Quadro2-PRO", NV_ARCH_10},
- { "GeForce2-Go", NV_ARCH_10},
- { "GeForce3", NV_ARCH_20},
+ { "GeForce4-MX-460", NV_ARCH_20 },
+ { "GeForce4-MX-440", NV_ARCH_20 },
+ { "GeForce4-MX-420", NV_ARCH_20 },
+ { "GeForce4-440-GO", NV_ARCH_20 },
+ { "GeForce4-420-GO", NV_ARCH_20 },
+ { "GeForce4-420-GO-M32", NV_ARCH_20 },
+ { "Quadro4-500-XGL", NV_ARCH_20 },
+ { "GeForce4-440-GO-M64", NV_ARCH_20 },
+ { "Quadro4-200", NV_ARCH_20 },
+ { "Quadro4-550-XGL", NV_ARCH_20 },
+ { "Quadro4-500-GOGL", NV_ARCH_20 },
+ { "GeForce2", NV_ARCH_20 },
+ { "GeForce3", NV_ARCH_20},
{ "GeForce3 Ti 200", NV_ARCH_20},
{ "GeForce3 Ti 500", NV_ARCH_20},
- { "Quadro DDC", NV_ARCH_20}
+ { "Quadro DDC", NV_ARCH_20},
+ { "GeForce4 Ti 4600", NV_ARCH_20 },
+ { "GeForce4 Ti 4400", NV_ARCH_20 },
+ { "GeForce4 Ti 4200", NV_ARCH_20 },
+ { "Quadro4-900-XGL", NV_ARCH_20 },
+ { "Quadro4-750-XGL", NV_ARCH_20 },
+ { "Quadro4-700-XGL", NV_ARCH_20 }
};
static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
@@ -184,56 +224,67 @@ static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX },
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX2 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GO },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_MXR },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS },
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_ULTRA },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GO },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_1 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_2 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO_DDC },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_460 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_440 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_420 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_440_GO },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_420_GO },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_420_GO_M32 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_500XGL },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_440_GO_M64 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_200 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_550XGL },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_500_GOGL },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_IGEFORCE2 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_1 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_2 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO_DDC },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4600 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4400 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4200 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_900XGL },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_750XGL },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_700XGL },
{ 0, } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
-
-
-/* ------------------------------------------------------------------------- *
- *
- * framebuffer related structures
- *
- * ------------------------------------------------------------------------- */
-
-extern struct display_switch fbcon_riva8;
-extern struct display_switch fbcon_riva16;
-extern struct display_switch fbcon_riva32;
-
-struct riva_cursor {
- int enable;
- int on;
- int vbl_cnt;
- int last_move_delay;
- int blink_rate;
- struct {
- u16 x, y;
- } pos, size;
- unsigned short image[MAX_CURS*MAX_CURS];
- struct timer_list *timer;
-};
-
/* ------------------------------------------------------------------------- *
*
* global variables
@@ -243,7 +294,7 @@ struct riva_cursor {
/* command line data, set in rivafb_setup() */
static u32 pseudo_palette[17];
#ifdef CONFIG_MTRR
-static char nomtrr __initdata = 0;
+static int nomtrr __initdata = 0;
#endif
#ifndef MODULE
@@ -581,6 +632,7 @@ static void riva_load_video_mode(struct fb_info *info)
{
int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
+ int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
struct riva_par *par = (struct riva_par *) info->par;
struct riva_regs newmode;
@@ -598,7 +650,10 @@ static void riva_load_video_mode(struct fb_info *info)
hEnd = (hDisplaySize + info->var.right_margin +
info->var.hsync_len) / 8 - 1;
hTotal = (hDisplaySize + info->var.right_margin +
- info->var.hsync_len + info->var.left_margin) / 8 - 1;
+ info->var.hsync_len + info->var.left_margin) / 8 - 5;
+ hBlankStart = hDisplay;
+ hBlankEnd = hTotal + 4;
+
height = info->var.yres_virtual;
vDisplay = info->var.yres - 1;
vStart = info->var.yres + info->var.lower_margin - 1;
@@ -606,47 +661,90 @@ static void riva_load_video_mode(struct fb_info *info)
info->var.vsync_len - 1;
vTotal = info->var.yres + info->var.lower_margin +
info->var.vsync_len + info->var.upper_margin + 2;
+ vBlankStart = vDisplay;
+ vBlankEnd = vTotal + 1;
dotClock = 1000000000 / info->var.pixclock;
memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
- newmode.crtc[0x0] = Set8Bits (hTotal - 4);
+ if (par->FlatPanel) {
+ vStart = vTotal - 3;
+ vEnd = vTotal - 2;
+ vBlankStart = vStart;
+ hStart = hTotal - 3;
+ hEnd = hTotal - 2;
+ hBlankEnd = hTotal + 4;
+ }
+
+ newmode.crtc[0x0] = Set8Bits (hTotal);
newmode.crtc[0x1] = Set8Bits (hDisplay);
- newmode.crtc[0x2] = Set8Bits (hDisplay);
- newmode.crtc[0x3] = SetBitField (hTotal, 4: 0, 4:0) | SetBit (7);
+ newmode.crtc[0x2] = Set8Bits (hBlankStart);
+ newmode.crtc[0x3] = SetBitField (hBlankEnd, 4: 0, 4:0) | SetBit (7);
newmode.crtc[0x4] = Set8Bits (hStart);
- newmode.crtc[0x5] = SetBitField (hTotal, 5: 5, 7:7)
+ newmode.crtc[0x5] = SetBitField (hBlankEnd, 5: 5, 7:7)
| SetBitField (hEnd, 4: 0, 4:0);
newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
| SetBitField (vDisplay, 8: 8, 1:1)
| SetBitField (vStart, 8: 8, 2:2)
- | SetBitField (vDisplay, 8: 8, 3:3)
+ | SetBitField (vBlankStart, 8: 8, 3:3)
| SetBit (4)
| SetBitField (vTotal, 9: 9, 5:5)
| SetBitField (vDisplay, 9: 9, 6:6)
| SetBitField (vStart, 9: 9, 7:7);
- newmode.crtc[0x9] = SetBitField (vDisplay, 9: 9, 5:5)
+ newmode.crtc[0x9] = SetBitField (vBlankStart, 9: 9, 5:5)
| SetBit (6);
newmode.crtc[0x10] = Set8Bits (vStart);
newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
| SetBit (5);
newmode.crtc[0x12] = Set8Bits (vDisplay);
- newmode.crtc[0x13] = ((width / 8) * ((bpp + 1) / 8)) & 0xFF;
- newmode.crtc[0x15] = Set8Bits (vDisplay);
- newmode.crtc[0x16] = Set8Bits (vTotal + 1);
+ newmode.crtc[0x13] = (width / 8) * ((bpp + 1) / 8);
+ newmode.crtc[0x15] = Set8Bits (vBlankStart);
+ newmode.crtc[0x16] = Set8Bits (vBlankEnd);
+
+ newmode.ext.screen = SetBitField(hBlankEnd,6:6,4:4)
+ | SetBitField(vBlankStart,10:10,3:3)
+ | SetBitField(vStart,10:10,2:2)
+ | SetBitField(vDisplay,10:10,1:1)
+ | SetBitField(vTotal,10:10,0:0);
+ newmode.ext.horiz = SetBitField(hTotal,8:8,0:0)
+ | SetBitField(hDisplay,8:8,1:1)
+ | SetBitField(hBlankStart,8:8,2:2)
+ | SetBitField(hStart,8:8,3:3);
+ newmode.ext.extra = SetBitField(vTotal,11:11,0:0)
+ | SetBitField(vDisplay,11:11,2:2)
+ | SetBitField(vStart,11:11,4:4)
+ | SetBitField(vBlankStart,11:11,6:6);
newmode.ext.bpp = bpp;
newmode.ext.width = width;
newmode.ext.height = height;
+ newmode.ext.interlace = 0xff; /* interlace off */
par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
- hDisplaySize, hDisplay, hStart, hEnd,
- hTotal, height, vDisplay, vStart, vEnd,
- vTotal, dotClock);
+ hDisplaySize, height, dotClock);
+ if (par->SecondCRTC) {
+ newmode.ext.head = par->riva.PCRTC0[0x00000860/4] & ~0x00001000;
+ newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] | 0x00001000;
+ newmode.ext.crtcOwner = 3;
+ newmode.ext.pllsel |= 0x20000800;
+ newmode.ext.vpll2 = newmode.ext.vpll;
+ } else if (par->riva.twoHeads) {
+ newmode.ext.head = par->riva.PCRTC0[0x00000860/4] | 0x00001000;
+ newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] & ~0x00001000;
+ newmode.ext.crtcOwner = 0;
+ newmode.ext.vpll2 = par->riva.PRAMDAC0[0x00000520/4];
+ }
+ if (par->FlatPanel == 1) {
+ newmode.ext.pixel |= (1 << 7);
+ newmode.ext.scale |= (1 << 8) ;
+ }
+ newmode.ext.cursorConfig = 0x02000100;
par->current_state = newmode;
riva_load_state(par, &par->current_state);
+ par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
+ rivafb_blank(0, info);
}
/**
@@ -916,6 +1014,7 @@ static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
size = width * h;
dat = cdat;
+
for (i = 0; i < size; i++) {
*dat = byte_rev[*dat];
dat++;
@@ -923,17 +1022,11 @@ static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
switch (info->var.bits_per_pixel) {
case 8:
- fgx = image->fg_color | ~((1 << 8) - 1);
- bgx = image->bg_color | ~((1 << 8) - 1);
+ fgx = image->fg_color;
+ bgx = image->bg_color;
break;
case 16:
- /* set alpha bit */
- if (info->var.green.length == 5) {
- fgx = 1 << 15;
- bgx = fgx;
- }
- /* Fall through... */
case 32:
fgx |= par->riva_palette[image->fg_color];
bgx |= par->riva_palette[image->bg_color];
@@ -1040,7 +1133,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
temp = xx & 0xFFFF;
temp |= yy << 16;
- *(par->riva.CURSORPOS) = temp;
+ par->riva.PRAMDAC[0x0000300/4] = temp;
}
if (flags & FB_CUR_SETSIZE) {
@@ -1168,7 +1261,10 @@ static int rivafb_open(struct fb_info *info, int user)
par->state.flags |= VGA_SAVE_CMAP;
save_vga(&par->state);
- RivaGetConfig(&par->riva);
+ RivaGetConfig(&par->riva, par->Chipset);
+ CRTCout(par, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */
+ par->riva.LockUnlock(&par->riva, 0);
+
riva_save_state(par, &par->initial_state);
}
@@ -1288,7 +1384,6 @@ static int rivafb_set_par(struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
- //rivafb_create_cursor(info, fontwidth(dsp), fontheight(dsp));
riva_load_video_mode(info);
if (info->var.accel_flags) {
riva_setup_accel(par);
@@ -1554,13 +1649,14 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
info->display_fg = NULL;
info->pseudo_palette = pseudo_palette;
- cmap_len = riva_get_cmap_len(&info->var);
- fb_alloc_cmap(&info->cmap, cmap_len, 0);
#ifndef MODULE
if (mode_option)
fb_find_mode(&info->var, info, mode_option,
NULL, 0, NULL, 8);
#endif
+ cmap_len = riva_get_cmap_len(&info->var);
+ fb_alloc_cmap(&info->cmap, cmap_len, 0);
+
return 0;
}
@@ -1693,7 +1789,9 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
strcat(rivafb_fix.id, rci->name);
default_par->riva.Architecture = rci->arch_rev;
-
+ default_par->riva.Chipset = pd->device;
+
+ printk(KERN_INFO PFX "nVidia device/chipset %X\n", pd->device);
rivafb_fix.mmio_len = pci_resource_len(pd, 0);
rivafb_fix.smem_len = pci_resource_len(pd, 1);
@@ -1713,13 +1811,6 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
goto err_out_free_base1;
}
- info->screen_base = ioremap(rivafb_fix.smem_start,
- rivafb_fix.smem_len);
- if (!info->screen_base) {
- printk(KERN_ERR PFX "cannot ioremap FB base\n");
- goto err_out_iounmap_ctrl;
- }
-
default_par->riva.EnableIRQ = 0;
default_par->riva.PRAMDAC = (unsigned *)(default_par->ctrl_base +
0x00680000);
@@ -1737,13 +1828,30 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
0x00000000);
default_par->riva.FIFO = (unsigned *)(default_par->ctrl_base +
0x00800000);
-
default_par->riva.PCIO = (U008 *)(default_par->ctrl_base + 0x00601000);
default_par->riva.PDIO = (U008 *)(default_par->ctrl_base + 0x00681000);
default_par->riva.PVIO = (U008 *)(default_par->ctrl_base + 0x000C0000);
-
default_par->riva.IO = (MISCin(default_par) & 0x01) ? 0x3D0 : 0x3B0;
+ if (default_par->riva.Architecture == NV_ARCH_03) {
+ /*
+ * We have to map the full BASE_1 aperture for Riva128's
+ * because they use the PRAMIN set in "framebuffer" space
+ */
+ if (!request_mem_region(rivafb_fix.smem_start,
+ rivafb_fix.smem_len, "rivafb")) {
+ printk(KERN_ERR PFX "cannot reserve FB region\n");
+ goto err_out_free_base0;
+ }
+
+ info->screen_base = ioremap(rivafb_fix.smem_start,
+ rivafb_fix.smem_len);
+ if (!info->screen_base) {
+ printk(KERN_ERR PFX "cannot ioremap FB base\n");
+ goto err_out_iounmap_ctrl;
+ }
+ }
+
switch (default_par->riva.Architecture) {
case NV_ARCH_03:
default_par->riva.PRAMIN = (unsigned *)(info->screen_base +
@@ -1767,17 +1875,23 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
info->par = default_par;
- if (!request_mem_region(rivafb_fix.smem_start,
- rivafb_fix.smem_len, "rivafb")) {
- printk(KERN_ERR PFX "cannot reserve FB region\n");
- goto err_out_free_base0;
- }
+ if (default_par->riva.Architecture != NV_ARCH_03) {
+ /*
+ * Now the _normal_ chipsets can just map the amount of
+ * real physical ram instead of the whole aperture
+ */
+ if (!request_mem_region(rivafb_fix.smem_start,
+ rivafb_fix.smem_len, "rivafb")) {
+ printk(KERN_ERR PFX "cannot reserve FB region\n");
+ goto err_out_free_base0;
+ }
- info->screen_base = ioremap(rivafb_fix.smem_start,
- rivafb_fix.smem_len);
- if (!info->screen_base) {
- printk(KERN_ERR PFX "cannot ioremap FB base\n");
- goto err_out_iounmap_ctrl;
+ info->screen_base = ioremap(rivafb_fix.smem_start,
+ rivafb_fix.smem_len);
+ if (!info->screen_base) {
+ printk(KERN_ERR PFX "cannot ioremap FB base\n");
+ goto err_out_iounmap_ctrl;
+ }
}
#ifdef CONFIG_MTRR
diff --git a/drivers/video/riva/nv_type.h b/drivers/video/riva/nv_type.h
new file mode 100644
index 000000000000..a69480c9a67c
--- /dev/null
+++ b/drivers/video/riva/nv_type.h
@@ -0,0 +1,58 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_type.h,v 1.35 2002/08/05 20:47:06 mvojkovi Exp $ */
+
+#ifndef __NV_STRUCT_H__
+#define __NV_STRUCT_H__
+
+#define NV_CHIP_RIVA_128 ((PCI_VENDOR_ID_NVIDIA_SGS << 16)| PCI_DEVICE_ID_NVIDIA_RIVA128)
+#define NV_CHIP_TNT ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT)
+#define NV_CHIP_TNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT2)
+#define NV_CHIP_UTNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UTNT2)
+#define NV_CHIP_VTNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_VTNT2)
+#define NV_CHIP_UVTNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UVTNT2)
+#define NV_CHIP_ITNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_ITNT2)
+#define NV_CHIP_GEFORCE_256 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_256)
+#define NV_CHIP_GEFORCE_DDR ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR)
+#define NV_CHIP_QUADRO ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_QUADRO)
+#define NV_CHIP_GEFORCE2_MX ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX)
+#define NV_CHIP_GEFORCE2_MX_100 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX_100)
+#define NV_CHIP_QUADRO2_MXR ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR)
+#define NV_CHIP_GEFORCE2_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO)
+#define NV_CHIP_GEFORCE2_GTS ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS)
+#define NV_CHIP_GEFORCE2_TI ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_TI)
+#define NV_CHIP_GEFORCE2_ULTRA ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA)
+#define NV_CHIP_QUADRO2_PRO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO)
+#define NV_CHIP_GEFORCE4_MX_460 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460)
+#define NV_CHIP_GEFORCE4_MX_440 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440)
+#define NV_CHIP_GEFORCE4_MX_420 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420)
+#define NV_CHIP_GEFORCE4_440_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO)
+#define NV_CHIP_GEFORCE4_420_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO)
+#define NV_CHIP_GEFORCE4_420_GO_M32 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32)
+#define NV_CHIP_QUADRO4_500XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL)
+#define NV_CHIP_GEFORCE4_440_GO_M64 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64)
+#define NV_CHIP_QUADRO4_200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_200)
+#define NV_CHIP_QUADRO4_550XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL)
+#define NV_CHIP_QUADRO4_500_GOGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL)
+#define NV_CHIP_0x0180 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0180)
+#define NV_CHIP_0x0181 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0181)
+#define NV_CHIP_0x0182 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0182)
+#define NV_CHIP_0x0188 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0188)
+#define NV_CHIP_0x018A ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018A)
+#define NV_CHIP_0x018B ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018B)
+#define NV_CHIP_IGEFORCE2 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_IGEFORCE2)
+#define NV_CHIP_0x01F0 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x01F0)
+#define NV_CHIP_GEFORCE3 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3)
+#define NV_CHIP_GEFORCE3_TI_200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_200)
+#define NV_CHIP_GEFORCE3_TI_500 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_500)
+#define NV_CHIP_QUADRO_DCC ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO_DCC)
+#define NV_CHIP_GEFORCE4_TI_4600 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600)
+#define NV_CHIP_GEFORCE4_TI_4400 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400)
+#define NV_CHIP_GEFORCE4_TI_4200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200)
+#define NV_CHIP_QUADRO4_900XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL)
+#define NV_CHIP_QUADRO4_750XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL)
+#define NV_CHIP_QUADRO4_700XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL)
+#define NV_CHIP_0x0280 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0280)
+#define NV_CHIP_0x0281 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0281)
+#define NV_CHIP_0x0288 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0288)
+#define NV_CHIP_0x0289 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0289)
+
+#endif /* __NV_STRUCT_H__ */
diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
index ae7da6ed1815..4e840a3a28ec 100644
--- a/drivers/video/riva/riva_hw.c
+++ b/drivers/video/riva/riva_hw.c
@@ -46,8 +46,12 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.8 2000/02/08 17:19:11 dawes Exp $ */
+#include <linux/pci_ids.h>
+#include <linux/pci.h>
#include "riva_hw.h"
#include "riva_tbl.h"
+#include "nv_type.h"
+
/*
* This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT
* operate identically (except TNT has more memory and better 3D quality.
@@ -73,32 +77,39 @@ static int nv10Busy
{
return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01));
}
-static void nv3LockUnlock
+
+static void vgaLockUnlock
(
RIVA_HW_INST *chip,
- int LockUnlock
+ int Lock
)
{
- VGA_WR08(chip->PVIO, 0x3C4, 0x06);
- VGA_WR08(chip->PVIO, 0x3C5, LockUnlock ? 0x99 : 0x57);
+ U008 cr11;
+ VGA_WR08(chip->PCIO, 0x3D4, 0x11);
+ cr11 = VGA_RD08(chip->PCIO, 0x3D5);
+ if(Lock) cr11 |= 0x80;
+ else cr11 &= ~0x80;
+ VGA_WR08(chip->PCIO, 0x3D5, cr11);
}
-static void nv4LockUnlock
+static void nv3LockUnlock
(
RIVA_HW_INST *chip,
- int LockUnlock
+ int Lock
)
{
- VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
- VGA_WR08(chip->PCIO, 0x3D5, LockUnlock ? 0x99 : 0x57);
+ VGA_WR08(chip->PVIO, 0x3C4, 0x06);
+ VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57);
+ vgaLockUnlock(chip, Lock);
}
-static void nv10LockUnlock
+static void nv4LockUnlock
(
RIVA_HW_INST *chip,
- int LockUnlock
+ int Lock
)
{
VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
- VGA_WR08(chip->PCIO, 0x3D5, LockUnlock ? 0x99 : 0x57);
+ VGA_WR08(chip->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
+ vgaLockUnlock(chip, Lock);
}
static int ShowHideCursor
@@ -107,13 +118,13 @@ static int ShowHideCursor
int ShowHide
)
{
- int current;
- current = chip->CurrentState->cursor1;
+ int cursor;
+ cursor = chip->CurrentState->cursor1;
chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) |
(ShowHide & 0x01);
VGA_WR08(chip->PCIO, 0x3D4, 0x31);
VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1);
- return (current & 0x01);
+ return (cursor & 0x01);
}
/****************************************************************************\
@@ -1093,7 +1104,6 @@ static void nv10UpdateArbitrationSettings
static int CalcVClock
(
int clockIn,
- int double_scan,
int *clockOut,
int *mOut,
int *nOut,
@@ -1109,18 +1119,16 @@ static int CalcVClock
DeltaOld = 0xFFFFFFFF;
VClk = (unsigned)clockIn;
- if (double_scan)
- VClk *= 2;
- if (chip->CrystalFreqKHz == 14318)
+ if (chip->CrystalFreqKHz == 13500)
{
- lowM = 8;
- highM = 14 - (chip->Architecture == NV_ARCH_03);
+ lowM = 7;
+ highM = 13 - (chip->Architecture == NV_ARCH_03);
}
else
{
- lowM = 7;
- highM = 13 - (chip->Architecture == NV_ARCH_03);
+ lowM = 8;
+ highM = 14 - (chip->Architecture == NV_ARCH_03);
}
highP = 4 - (chip->Architecture == NV_ARCH_03);
@@ -1131,8 +1139,9 @@ static int CalcVClock
{
for (M = lowM; M <= highM; M++)
{
- N = (VClk * M / chip->CrystalFreqKHz) << P;
- Freq = (chip->CrystalFreqKHz * N / M) >> P;
+ N = (VClk << P) * M / chip->CrystalFreqKHz;
+ if(N <= 255) {
+ Freq = (chip->CrystalFreqKHz * N / M) >> P;
if (Freq > VClk)
DeltaNew = Freq - VClk;
else
@@ -1148,6 +1157,7 @@ static int CalcVClock
}
}
}
+ }
return (DeltaOld != 0xFFFFFFFF);
}
/*
@@ -1161,15 +1171,7 @@ static void CalcStateExt
int bpp,
int width,
int hDisplaySize,
- int hDisplay,
- int hStart,
- int hEnd,
- int hTotal,
int height,
- int vDisplay,
- int vStart,
- int vEnd,
- int vTotal,
int dotClock
)
{
@@ -1184,8 +1186,7 @@ static void CalcStateExt
* Extended RIVA registers.
*/
pixelDepth = (bpp + 1)/8;
- CalcVClock(dotClock, hDisplaySize < 512, /* double scan? */
- &VClk, &m, &n, &p, chip);
+ CalcVClock(dotClock, &VClk, &m, &n, &p, chip);
switch (chip->Architecture)
{
@@ -1225,9 +1226,9 @@ static void CalcStateExt
&(state->arbitration0),
&(state->arbitration1),
chip);
- state->cursor0 = 0x00;
- state->cursor1 = 0xFC;
- state->cursor2 = 0x00000000;
+ state->cursor0 = 0x00;
+ state->cursor1 = 0xFC;
+ state->cursor2 = 0x00000000;
state->pllsel = 0x10000700;
state->config = chip->PFB[0x00000200/4];
state->general = bpp == 16 ? 0x00101100 : 0x00100100;
@@ -1235,13 +1236,7 @@ static void CalcStateExt
break;
}
state->vpll = (p << 16) | (n << 8) | m;
- state->screen = ((hTotal & 0x040) >> 2)
- | ((vDisplay & 0x400) >> 7)
- | ((vStart & 0x400) >> 8)
- | ((vDisplay & 0x400) >> 9)
- | ((vTotal & 0x400) >> 10);
state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
- state->horiz = hTotal < 260 ? 0x00 : 0x01;
state->pixel = pixelDepth > 2 ? 3 : pixelDepth;
state->offset0 =
state->offset1 =
@@ -1285,6 +1280,7 @@ static void UpdateFifoState
chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
break;
case NV_ARCH_10:
+ case NV_ARCH_20:
/*
* Initialize state for the RivaTriangle3D05 routines.
*/
@@ -1503,7 +1499,7 @@ static void LoadStateExt
chip->PGRAPH[0x00000F50/4] = 0x00000040;
for (i = 0; i < 4; i++)
chip->PGRAPH[0x00000F54/4] = 0x00000000;
- break;
+ break;
}
LOAD_FIXED_STATE(Riva,FIFO);
UpdateFifoState(chip);
@@ -1532,11 +1528,12 @@ static void LoadStateExt
chip->PRAMDAC[0x00000508/4] = state->vpll;
chip->PRAMDAC[0x0000050C/4] = state->pllsel;
chip->PRAMDAC[0x00000600/4] = state->general;
+
/*
* Turn off VBlank enable and reset.
*/
- *(chip->VBLANKENABLE) = 0;
- *(chip->VBLANK) = chip->VBlankBit;
+ chip->PCRTC[0x00000140/4] = 0;
+ chip->PCRTC[0x00000100/4] = chip->VBlankBit;
/*
* Set interrupt enable.
*/
@@ -1806,9 +1803,6 @@ static void nv3GetConfig
}
chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000020) ? 14318 : 13500;
chip->CURSOR = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]);
- chip->CURSORPOS = &(chip->PRAMDAC[0x0300/4]);
- chip->VBLANKENABLE = &(chip->PGRAPH[0x0140/4]);
- chip->VBLANK = &(chip->PGRAPH[0x0100/4]);
chip->VBlankBit = 0x00000100;
chip->MaxVClockFreqKHz = 256000;
/*
@@ -1867,9 +1861,6 @@ static void nv4GetConfig
}
chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
- chip->CURSORPOS = &(chip->PRAMDAC[0x0300/4]);
- chip->VBLANKENABLE = &(chip->PCRTC[0x0140/4]);
- chip->VBLANK = &(chip->PCRTC[0x0100/4]);
chip->VBlankBit = 0x00000001;
chip->MaxVClockFreqKHz = 350000;
/*
@@ -1887,12 +1878,30 @@ static void nv4GetConfig
}
static void nv10GetConfig
(
- RIVA_HW_INST *chip
+ RIVA_HW_INST *chip,
+ unsigned int chipset
)
{
+ struct pci_dev* dev;
+ int amt;
+
+#ifdef __BIG_ENDIAN
+ /* turn on big endian register access */
+ chip->PMC[0x00000004/4] = 0x01000001;
+#endif
+
/*
* Fill in chip configuration.
*/
+ if(chipset == NV_CHIP_IGEFORCE2) {
+ dev = pci_find_slot(0, 1);
+ pci_read_config_dword(dev, 0x7C, &amt);
+ chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
+ } else if(chipset == NV_CHIP_0x01F0) {
+ dev = pci_find_slot(0, 1);
+ pci_read_config_dword(dev, 0x84, &amt);
+ chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
+ } else {
switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF)
{
case 0x02:
@@ -1920,6 +1929,7 @@ static void nv10GetConfig
chip->RamAmountKBytes = 1024 * 16;
break;
}
+ }
switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
{
case 3:
@@ -1931,9 +1941,6 @@ static void nv10GetConfig
}
chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
- chip->CURSORPOS = &(chip->PRAMDAC[0x0300/4]);
- chip->VBLANKENABLE = &(chip->PCRTC[0x0140/4]);
- chip->VBLANK = &(chip->PCRTC[0x0100/4]);
chip->VBlankBit = 0x00000001;
chip->MaxVClockFreqKHz = 350000;
/*
@@ -1947,11 +1954,12 @@ static void nv10GetConfig
chip->SetStartAddress = SetStartAddress;
chip->SetSurfaces2D = nv10SetSurfaces2D;
chip->SetSurfaces3D = nv10SetSurfaces3D;
- chip->LockUnlock = nv10LockUnlock;
+ chip->LockUnlock = nv4LockUnlock;
}
int RivaGetConfig
(
- RIVA_HW_INST *chip
+ RIVA_HW_INST *chip,
+ unsigned int chipset
)
{
/*
@@ -1970,11 +1978,13 @@ int RivaGetConfig
nv4GetConfig(chip);
break;
case NV_ARCH_10:
- nv10GetConfig(chip);
+ case NV_ARCH_20:
+ nv10GetConfig(chip, chipset);
break;
default:
return (-1);
}
+ chip->Chipset = chipset;
/*
* Fill in FIFO pointers.
*/
diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h
index 22d056b0fd2e..e54b015bd529 100644
--- a/drivers/video/riva/riva_hw.h
+++ b/drivers/video/riva/riva_hw.h
@@ -44,11 +44,25 @@
* from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99
*/
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.6 2000/02/08 17:19:12 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.21 2002/10/14 18:22:46 mvojkovi Exp $ */
#ifndef __RIVA_HW_H__
#define __RIVA_HW_H__
#define RIVA_SW_VERSION 0x00010003
+#ifndef Bool
+typedef int Bool;
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+
/*
* Typedefs to force certain sized values.
*/
@@ -59,8 +73,14 @@ typedef unsigned int U032;
/*
* HW access macros.
*/
+#if defined(__powerpc__)
+#include <asm/io.h>
+#define NV_WR08(p,i,d) out_8(p+i, d)
+#define NV_RD08(p,i) in_8(p+i)
+#else
#define NV_WR08(p,i,d) (((U008 *)(p))[i]=(d))
#define NV_RD08(p,i) (((U008 *)(p))[i])
+#endif
#define NV_WR16(p,i,d) (((U016 *)(p))[(i)/2]=(d))
#define NV_RD16(p,i) (((U016 *)(p))[(i)/2])
#define NV_WR32(p,i,d) (((U032 *)(p))[(i)/4]=(d))
@@ -75,6 +95,7 @@ typedef unsigned int U032;
#define NV_ARCH_04 0x04
#define NV_ARCH_10 0x10
#define NV_ARCH_20 0x20
+
/***************************************************************************\
* *
* FIFO registers. *
@@ -87,8 +108,12 @@ typedef unsigned int U032;
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop;
+#endif
U032 reserved01[0x0BB];
U032 Rop3;
} RivaRop;
@@ -98,8 +123,12 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop;
+#endif
U032 reserved01[0x0BD];
U032 Shape;
U032 reserved03[0x001];
@@ -113,8 +142,12 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop;
+#endif
U032 reserved01[0x0BB];
U032 TopLeft;
U032 WidthHeight;
@@ -125,8 +158,12 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop[1];
+#endif
U032 reserved01[0x0BC];
U032 Color;
U032 reserved03[0x03E];
@@ -139,8 +176,12 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop;
+#endif
U032 reserved01[0x0BB];
U032 TopLeftSrc;
U032 TopLeftDst;
@@ -152,8 +193,12 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop[1];
+#endif
U032 reserved01[0x0BC];
U032 TopLeft;
U032 WidthHeight;
@@ -167,8 +212,12 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop;
+#endif
U032 reserved01[0x0BB];
U032 reserved03[(0x040)-1];
U032 Color1A;
@@ -229,8 +278,12 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop;
+#endif
U032 reserved01[0x0BC];
U032 TextureOffset;
U032 TextureFormat;
@@ -255,8 +308,12 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop;
+#endif
U032 reserved01[0x0BB];
U032 ColorKey;
U032 TextureOffset;
@@ -289,8 +346,12 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop[1];
+#endif
U032 reserved01[0x0BC];
U032 Color; /* source color 0304-0307*/
U032 Reserved02[0x03e];
@@ -320,16 +381,24 @@ typedef volatile struct
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop;
+#endif
U032 reserved01[0x0BE];
U032 Offset;
} RivaSurface;
typedef volatile struct
{
U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
U016 FifoFree;
U016 Nop;
+#endif
U032 reserved01[0x0BD];
U032 Pitch;
U032 RenderBufferOffset;
@@ -342,6 +411,9 @@ typedef volatile struct
* *
\***************************************************************************/
+#define FP_ENABLE 1
+#define FP_DITHER 2
+
struct _riva_hw_inst;
struct _riva_hw_state;
/*
@@ -354,6 +426,7 @@ typedef struct _riva_hw_inst
*/
U032 Architecture;
U032 Version;
+ U032 Chipset;
U032 CrystalFreqKHz;
U032 RamAmountKBytes;
U032 MaxVClockFreqKHz;
@@ -363,11 +436,15 @@ typedef struct _riva_hw_inst
U032 VBlankBit;
U032 FifoFreeCount;
U032 FifoEmptyCount;
+ U032 CursorStart;
+ U032 flatPanel;
+ Bool twoHeads;
/*
* Non-FIFO registers.
*/
+ volatile U032 *PCRTC0;
volatile U032 *PCRTC;
- volatile U032 *PRAMDAC;
+ volatile U032 *PRAMDAC0;
volatile U032 *PFB;
volatile U032 *PFIFO;
volatile U032 *PGRAPH;
@@ -377,17 +454,17 @@ typedef struct _riva_hw_inst
volatile U032 *PRAMIN;
volatile U032 *FIFO;
volatile U032 *CURSOR;
- volatile U032 *CURSORPOS;
- volatile U032 *VBLANKENABLE;
- volatile U032 *VBLANK;
+ volatile U008 *PCIO0;
volatile U008 *PCIO;
volatile U008 *PVIO;
+ volatile U008 *PDIO0;
volatile U008 *PDIO;
+ volatile U032 *PRAMDAC;
/*
* Common chip functions.
*/
int (*Busy)(struct _riva_hw_inst *);
- void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int,int,int,int,int,int,int,int,int);
+ void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int);
void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
void (*SetStartAddress)(struct _riva_hw_inst *,U032);
@@ -420,17 +497,26 @@ typedef struct _riva_hw_state
U032 bpp;
U032 width;
U032 height;
+ U032 interlace;
U032 repaint0;
U032 repaint1;
U032 screen;
+ U032 scale;
+ U032 dither;
+ U032 extra;
U032 pixel;
U032 horiz;
U032 arbitration0;
U032 arbitration1;
U032 vpll;
+ U032 vpll2;
U032 pllsel;
U032 general;
+ U032 crtcOwner;
+ U032 head;
+ U032 head2;
U032 config;
+ U032 cursorConfig;
U032 cursor0;
U032 cursor1;
U032 cursor2;
@@ -446,16 +532,16 @@ typedef struct _riva_hw_state
/*
* External routines.
*/
-int RivaGetConfig(RIVA_HW_INST *);
+int RivaGetConfig(RIVA_HW_INST *, unsigned int);
/*
* FIFO Free Count. Should attempt to yield processor if RIVA is busy.
*/
-#define RIVA_FIFO_FREE(hwinst,hwptr,cnt) \
-{ \
- while ((hwinst).FifoFreeCount < (cnt)) \
- (hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2; \
- (hwinst).FifoFreeCount -= (cnt); \
+#define RIVA_FIFO_FREE(hwinst,hwptr,cnt) \
+{ \
+ while ((hwinst).FifoFreeCount < (cnt)) \
+ (hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2; \
+ (hwinst).FifoFreeCount -= (cnt); \
}
#endif /* __RIVA_HW_H__ */
diff --git a/drivers/video/riva/riva_tbl.h b/drivers/video/riva/riva_tbl.h
index 3843ffa73ae4..7ee7d72932d4 100644
--- a/drivers/video/riva/riva_tbl.h
+++ b/drivers/video/riva/riva_tbl.h
@@ -44,7 +44,9 @@
* from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99
*/
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_tbl.h,v 1.5 2000/02/08 17:19:12 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_tbl.h,v 1.9 2002/01/30 01:35:03 mvojkovi Exp $ */
+
+
/*
* RIVA Fixed Functionality Init Tables.
*/
@@ -69,6 +71,7 @@ static unsigned RivaTableFIFO[][2] =
{0x00001800, 0x80000010},
{0x00002000, 0x80000011},
{0x00002800, 0x80000012},
+ {0x00003000, 0x80000016},
{0x00003800, 0x80000013}
};
static unsigned nv3TablePFIFO[][2] =
@@ -174,6 +177,8 @@ static unsigned nv3TablePRAMIN[][2] =
{0x00000249, 0x00CC0346},
{0x0000024C, 0x80000013},
{0x0000024D, 0x00D70347},
+ {0x00000258, 0x80000016},
+ {0x00000259, 0x00CA034C},
{0x00000D05, 0x00000000},
{0x00000D06, 0x00000000},
{0x00000D07, 0x00000000},
@@ -210,7 +215,10 @@ static unsigned nv3TablePRAMIN[][2] =
{0x00000D2C, 0x10830200},
{0x00000D2D, 0x00000000},
{0x00000D2E, 0x00000000},
- {0x00000D2F, 0x00000000}
+ {0x00000D2F, 0x00000000},
+ {0x00000D31, 0x00000000},
+ {0x00000D32, 0x00000000},
+ {0x00000D33, 0x00000000}
};
static unsigned nv3TablePRAMIN_8BPP[][2] =
{
@@ -222,7 +230,8 @@ static unsigned nv3TablePRAMIN_8BPP[][2] =
{0x00000D10, 0x10118203},
{0x00000D14, 0x10110203},
{0x00000D18, 0x10110203},
- {0x00000D1C, 0x10419208}
+ {0x00000D1C, 0x10419208},
+ {0x00000D30, 0x10118203}
};
static unsigned nv3TablePRAMIN_15BPP[][2] =
{
@@ -234,7 +243,8 @@ static unsigned nv3TablePRAMIN_15BPP[][2] =
{0x00000D10, 0x10118200},
{0x00000D14, 0x10110200},
{0x00000D18, 0x10110200},
- {0x00000D1C, 0x10419208}
+ {0x00000D1C, 0x10419208},
+ {0x00000D30, 0x10118200}
};
static unsigned nv3TablePRAMIN_32BPP[][2] =
{
@@ -246,7 +256,8 @@ static unsigned nv3TablePRAMIN_32BPP[][2] =
{0x00000D10, 0x10118201},
{0x00000D14, 0x10110201},
{0x00000D18, 0x10110201},
- {0x00000D1C, 0x10419208}
+ {0x00000D1C, 0x10419208},
+ {0x00000D30, 0x10118201}
};
static unsigned nv4TableFIFO[][2] =
{
@@ -370,6 +381,8 @@ static unsigned nv4TablePRAMIN[][2] =
{0x00000009, 0x80011149},
{0x0000000A, 0x80000015},
{0x0000000B, 0x8001114A},
+ {0x0000000C, 0x80000016},
+ {0x0000000D, 0x8001114F},
{0x00000020, 0x80000000},
{0x00000021, 0x80011142},
{0x00000022, 0x80000001},
@@ -437,7 +450,10 @@ static unsigned nv4TablePRAMIN[][2] =
{0x00000537, 0x00000000},
{0x00000538, 0x0000005B},
{0x0000053A, 0x11401140},
- {0x0000053B, 0x00000000}
+ {0x0000053B, 0x00000000},
+ {0x0000053C, 0x0300A01C},
+ {0x0000053E, 0x11401140},
+ {0x0000053F, 0x00000000}
};
static unsigned nv4TablePRAMIN_8BPP[][2] =
{
@@ -452,7 +468,8 @@ static unsigned nv4TablePRAMIN_8BPP[][2] =
{0x0000052D, 0x00000302},
{0x0000052E, 0x00000302},
{0x00000535, 0x00000000},
- {0x00000539, 0x00000000}
+ {0x00000539, 0x00000000},
+ {0x0000053D, 0x00000302}
};
static unsigned nv4TablePRAMIN_15BPP[][2] =
{
@@ -467,7 +484,8 @@ static unsigned nv4TablePRAMIN_15BPP[][2] =
{0x0000052D, 0x00000902},
{0x0000052E, 0x00000902},
{0x00000535, 0x00000702},
- {0x00000539, 0x00000702}
+ {0x00000539, 0x00000702},
+ {0x0000053D, 0x00000902}
};
static unsigned nv4TablePRAMIN_16BPP[][2] =
{
@@ -482,7 +500,8 @@ static unsigned nv4TablePRAMIN_16BPP[][2] =
{0x0000052D, 0x00000C02},
{0x0000052E, 0x00000C02},
{0x00000535, 0x00000702},
- {0x00000539, 0x00000702}
+ {0x00000539, 0x00000702},
+ {0x0000053D, 0x00000C02}
};
static unsigned nv4TablePRAMIN_32BPP[][2] =
{
@@ -497,7 +516,8 @@ static unsigned nv4TablePRAMIN_32BPP[][2] =
{0x0000052D, 0x00000E02},
{0x0000052E, 0x00000E02},
{0x00000535, 0x00000E02},
- {0x00000539, 0x00000E02}
+ {0x00000539, 0x00000E02},
+ {0x0000053D, 0x00000E02}
};
static unsigned nv10TableFIFO[][2] =
{
@@ -810,6 +830,8 @@ static unsigned nv10TablePRAMIN[][2] =
{0x00000009, 0x80011149},
{0x0000000A, 0x80000015},
{0x0000000B, 0x8001114A},
+ {0x0000000C, 0x80000016},
+ {0x0000000D, 0x80011150},
{0x00000020, 0x80000000},
{0x00000021, 0x80011142},
{0x00000022, 0x80000001},
@@ -830,29 +852,45 @@ static unsigned nv10TablePRAMIN[][2] =
{0x00000501, 0x01FFFFFF},
{0x00000502, 0x00000002},
{0x00000503, 0x00000002},
+#ifdef __BIG_ENDIAN
+ {0x00000508, 0x01088043},
+#else
{0x00000508, 0x01008043},
+#endif
{0x0000050A, 0x00000000},
{0x0000050B, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x0000050C, 0x01088019},
+#else
{0x0000050C, 0x01008019},
+#endif
{0x0000050E, 0x00000000},
{0x0000050F, 0x00000000},
-#if 1
- {0x00000510, 0x01008018},
+#ifdef __BIG_ENDIAN
+ {0x00000510, 0x01088018},
#else
- {0x00000510, 0x01008044},
+ {0x00000510, 0x01008018},
#endif
{0x00000512, 0x00000000},
{0x00000513, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x00000514, 0x01088021},
+#else
{0x00000514, 0x01008021},
+#endif
{0x00000516, 0x00000000},
{0x00000517, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x00000518, 0x0108805F},
+#else
{0x00000518, 0x0100805F},
+#endif
{0x0000051A, 0x00000000},
{0x0000051B, 0x00000000},
-#if 1
- {0x0000051C, 0x0100804B},
+#ifdef __BIG_ENDIAN
+ {0x0000051C, 0x0108804B},
#else
- {0x0000051C, 0x0100804A},
+ {0x0000051C, 0x0100804B},
#endif
{0x0000051E, 0x00000000},
{0x0000051F, 0x00000000},
@@ -868,10 +906,18 @@ static unsigned nv10TablePRAMIN[][2] =
{0x00000529, 0x00000D01},
{0x0000052A, 0x11401140},
{0x0000052B, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x0000052C, 0x00080058},
+#else
{0x0000052C, 0x00000058},
+#endif
{0x0000052E, 0x11401140},
{0x0000052F, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x00000530, 0x00080059},
+#else
{0x00000530, 0x00000059},
+#endif
{0x00000532, 0x11401140},
{0x00000533, 0x00000000},
{0x00000534, 0x0000005A},
@@ -882,7 +928,14 @@ static unsigned nv10TablePRAMIN[][2] =
{0x0000053B, 0x00000000},
{0x0000053C, 0x00000093},
{0x0000053E, 0x11401140},
- {0x0000053F, 0x00000000}
+ {0x0000053F, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x00000540, 0x0308A01C},
+#else
+ {0x00000540, 0x0300A01C},
+#endif
+ {0x00000542, 0x11401140},
+ {0x00000543, 0x00000000}
};
static unsigned nv10TablePRAMIN_8BPP[][2] =
{
@@ -898,7 +951,8 @@ static unsigned nv10TablePRAMIN_8BPP[][2] =
{0x0000052E, 0x00000302},
{0x00000535, 0x00000000},
{0x00000539, 0x00000000},
- {0x0000053D, 0x00000000}
+ {0x0000053D, 0x00000000},
+ {0x00000541, 0x00000302}
};
static unsigned nv10TablePRAMIN_15BPP[][2] =
{
@@ -914,7 +968,8 @@ static unsigned nv10TablePRAMIN_15BPP[][2] =
{0x0000052E, 0x00000902},
{0x00000535, 0x00000902},
{0x00000539, 0x00000902},
- {0x0000053D, 0x00000902}
+ {0x0000053D, 0x00000902},
+ {0x00000541, 0x00000902}
};
static unsigned nv10TablePRAMIN_16BPP[][2] =
{
@@ -930,7 +985,8 @@ static unsigned nv10TablePRAMIN_16BPP[][2] =
{0x0000052E, 0x00000C02},
{0x00000535, 0x00000C02},
{0x00000539, 0x00000C02},
- {0x0000053D, 0x00000C02}
+ {0x0000053D, 0x00000C02},
+ {0x00000541, 0x00000C02}
};
static unsigned nv10TablePRAMIN_32BPP[][2] =
{
@@ -946,6 +1002,7 @@ static unsigned nv10TablePRAMIN_32BPP[][2] =
{0x0000052E, 0x00000E02},
{0x00000535, 0x00000E02},
{0x00000539, 0x00000E02},
- {0x0000053D, 0x00000E02}
+ {0x0000053D, 0x00000E02},
+ {0x00000541, 0x00000E02}
};
diff --git a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h
index f0bdd484ff37..9de0230fa8af 100644
--- a/drivers/video/riva/rivafb.h
+++ b/drivers/video/riva/rivafb.h
@@ -41,9 +41,16 @@ struct riva_par {
u32 riva_palette[16];
u32 cursor_data[32 * 32/4];
int cursor_reset;
+ unsigned char *EDID;
+ unsigned int Chipset;
+ int forceCRTC;
+ Bool SecondCRTC;
+ int FlatPanel;
#ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr;
#endif
};
+void riva_common_setup(struct riva_par *);
+
#endif /* __RIVAFB_H */
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index fd6aba8342d7..bb95b6dc51ab 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -129,6 +129,40 @@ int xxxfb_init(void);
int xxxfb_setup(char*);
/**
+ * xxxfb_open - Optional function. Called when the framebuffer is
+ * first accessed.
+ * @info: frame buffer structure that represents a single frame buffer
+ * @user: tell us if the userland (value=1) or the console is accessing
+ * the framebuffer.
+ *
+ * This function is the first function called in the framebuffer api.
+ * Usually you don't need to provide this function. The case where it
+ * is used is to change from a text mode hardware state to a graphics
+ * mode state.
+ */
+static int xxxfb_open(const struct fb_info *info, int user)
+{
+ return 0;
+}
+
+/**
+ * xxxfb_release - Optional function. Called when the framebuffer
+ * device is closed.
+ * @info: frame buffer structure that represents a single frame buffer
+ * @user: tell us if the userland (value=1) or the console is accessing
+ * the framebuffer.
+ *
+ * Thus function is called when we close /dev/fb or the framebuffer
+ * console system is released. Usually you don't need this function.
+ * The case where it is usually used is to go from a graphics state
+ * to a text mode state.
+ */
+static int xxxfb_release(const struct fb_info *info, int user)
+{
+ return 0;
+}
+
+/**
* xxxfb_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
@@ -143,7 +177,10 @@ int xxxfb_setup(char*);
* off by what the hardware can support then we alter the var PASSED in
* to what we can do. If the hardware doesn't support mode change
* a -EINVAL will be returned by the upper layers. You don't need to
- * implement this function then.
+ * implement this function then. If you hardware doesn't support
+ * changing the resolution then this function is not needed. In this
+ * case the driver woudl just provide a var that represents the static
+ * state the screen is in.
*
* Returns negative errno on error, or zero on success.
*/
@@ -164,6 +201,7 @@ static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
* fb_info since we are using that data. This means we depend on the
* data in var inside fb_info to be supported by the hardware.
* xxxfb_check_var is always called before xxxfb_set_par to ensure this.
+ * Again if you can't can't the resolution you don't need this function.
*
*/
static int xxxfb_set_par(struct fb_info *info)
@@ -175,8 +213,8 @@ static int xxxfb_set_par(struct fb_info *info)
/**
* xxxfb_setcolreg - Optional function. Sets a color register.
- * @regno: boolean, 0 copy local, 1 get_user() function
- * @red: frame buffer colormap structure
+ * @regno: Which register in the CLUT we are programming
+ * @red: The red value which can be up to 16 bits wide
* @green: The green value which can be up to 16 bits wide
* @blue: The blue value which can be up to 16 bits wide.
* @transp: If supported the alpha value which can be up to 16 bits wide.
@@ -284,12 +322,6 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
}
/**
- * xxxfb_cursor -
- *
- * Returns negative errno on error, or zero on success.
- */
-
-/**
* xxxfb_pan_display - NOT a required function. Pans the display.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
@@ -299,7 +331,6 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
* If the values don't fit, return -EINVAL.
*
* Returns negative errno on error, or zero on success.
- *
*/
static int xxxfb_pan_display(struct fb_var_screeninfo *var,
const struct fb_info *info)
@@ -335,12 +366,9 @@ static int xxxfb_blank(int blank_mode, const struct fb_info *info)
/*
* We provide our own functions if we have hardware acceleration
* or non packed pixel format layouts. If we have no hardware
- * acceleration, we use a generic unaccelerated function. If using
- * a pack pixel format just use the functions in cfb*.c. Each file
- * has one of the three different accel functions we support. You
- * can use these functions as fallbacks if hardware unsupported
- * action is requested. Also if you have non pack pixel modes and
- * non accelerated cards you have to provide your own functions.
+ * acceleration, we can use a generic unaccelerated function. If using
+ * a pack pixel format just use the functions in cfb_*.c. Each file
+ * has one of the three different accel functions we support.
*/
/**
@@ -349,41 +377,52 @@ static int xxxfb_blank(int blank_mode, const struct fb_info *info)
* Draws a rectangle on the screen.
*
* @info: frame buffer structure that represents a single frame buffer
- * @x1: The x and y corrdinates of the upper left hand corner of the
- * @y1: area we want to draw to.
- * @width: How wide the rectangle is we want to draw.
- * @height: How tall the rectangle is we want to draw.
- * @color: The color to fill in the rectangle with.
- * @rop: The rater operation. We can draw the rectangle with a COPY
- * of XOR which provides erasing effect.
+ * @region: The structure representing the rectangular region we
+ * wish to draw to.
*
* This drawing operation places/removes a retangle on the screen
* depending on the rastering operation with the value of color which
* is in the current color depth format.
*/
-void xxxfb_fillrect(struct fb_info *p, struct fb_fillrect *region)
+void xxfb_fillrect(struct fb_info *p, struct fb_fillrect *region)
{
+/* Meaning of struct fb_fillrect
+ *
+ * @dx: The x and y corrdinates of the upper left hand corner of the
+ * @dy: area we want to draw to.
+ * @width: How wide the rectangle is we want to draw.
+ * @height: How tall the rectangle is we want to draw.
+ * @color: The color to fill in the rectangle with.
+ * @rop: The raster operation. We can draw the rectangle with a COPY
+ * of XOR which provides erasing effect.
+ */
}
/**
* xxxfb_copyarea - REQUIRED function. Can use generic routines if
* non acclerated hardware and packed pixel based.
- * Copies on area of the screen to another area.
+ * Copies one area of the screen to another area.
*
* @info: frame buffer structure that represents a single frame buffer
- * @sx: The x and y corrdinates of the upper left hand corner of the
- * @sy: source area on the screen.
- * @width: How wide the rectangle is we want to copy.
- * @height: How tall the rectangle is we want to copy.
- * @dx: The x and y coordinates of the destination area on the screen.
+ * @area: Structure providing the data to copy the framebuffer contents
+ * from one region to another.
*
* This drawing operation copies a rectangular area from one area of the
* screen to another area.
*/
void xxxfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
{
+/*
+ * @dx: The x and y coordinates of the upper left hand corner of the
+ * @dy: destination area on the screen.
+ * @width: How wide the rectangle is we want to copy.
+ * @height: How tall the rectangle is we want to copy.
+ * @sx: The x and y coordinates of the upper left hand corner of the
+ * @sy: source area on the screen.
+ */
}
+
/**
* xxxfb_imageblit - REQUIRED function. Can use generic routines if
* non acclerated hardware and packed pixel based.
@@ -398,9 +437,89 @@ void xxxfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
*/
void xxxfb_imageblit(struct fb_info *p, struct fb_image *image)
{
+/*
+ * @dx: The x and y coordinates of the upper left hand corner of the
+ * @dy: destination area to place the image on the screen.
+ * @width: How wide the image is we want to copy.
+ * @height: How tall the image is we want to copy.
+ * @fg_color: For mono bitmap images this is color data for
+ * @bg_color: the foreground and background of the image to
+ * write directly to the frmaebuffer.
+ * @depth: How many bits represent a single pixel for this image.
+ * @data: The actual data used to construct the image on the display.
+ * @cmap: The colormap used for color images.
+ */
}
-/* ------------ Hardware Independent Functions ------------ */
+/**
+ * xxxfb_cursor - REQUIRED function. If your hardware lacks support
+ * for a cursor you can use the default cursor whose
+ * function is called soft_cursor. It will always
+ * work since it uses xxxfb_imageblit function which
+ * is required.
+ *
+ * @info: frame buffer structure that represents a single frame buffer
+ * @cursor: structure defining the cursor to draw.
+ *
+ * This operation is used to set or alter the properities of the
+ * cursor.
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+/*
+ * @set: Which fields we are altering in struct fb_cursor
+ * @enable: Disable or enable the cursor
+ * @rop: The bit operation we want to do.
+ * @mask: This is the cursor mask bitmap.
+ * @dest: A image of the area we are going to display the cursor.
+ * Used internally by the driver.
+ * @hot: The hot spot.
+ * @image: The actual data for the cursor image.
+ */
+}
+
+/**
+ * xxxfb_rotate - NOT a required function. If your hardware
+ * supports rotation the whole screen then
+ * you would provide a hook for this.
+ *
+ * @info: frame buffer structure that represents a single frame buffer
+ * @angle: The angle we rotate the screen.
+ *
+ * This operation is used to set or alter the properities of the
+ * cursor.
+ */
+void xxxfb_rotate(struct fb_info *info, int angle)
+{
+}
+
+/**
+ * xxxfb_poll - NOT a required function. The purpose of this
+ * function is to provide a way for some process
+ * to wait until a specific hardware event occurs
+ * for the framebuffer device.
+ *
+ * @info: frame buffer structure that represents a single frame buffer
+ * @wait: poll table where we store process that await a event.
+ */
+void xxxfb_poll(struct fb_info *info, poll_table *wait)
+{
+}
+
+/**
+ * xxxfb_sync - NOT a required function. Normally the accel engine
+ * for a graphics card take a specific amount of time.
+ * Often we have to wait for the accelerator to finish
+ * its operation before we can write to the framebuffer
+ * so we can have consistant display output.
+ *
+ * @info: frame buffer structure that represents a single frame buffer
+ */
+void xxxfb_sync(struct fb_info *info)
+{
+}
/*
* Initialization
@@ -480,39 +599,32 @@ int __init xxxfb_setup(char *options)
/* Parse user speficied options (`video=xxxfb:') */
}
-
/* ------------------------------------------------------------------------- */
/*
* Frame buffer operations
*/
-/* If all you need is that - just don't define ->fb_open */
-static int xxxfb_open(const struct fb_info *info, int user)
-{
- return 0;
-}
-
-/* If all you need is that - just don't define ->fb_release */
-static int xxxfb_release(const struct fb_info *info, int user)
-{
- return 0;
-}
-
static struct fb_ops xxxfb_ops = {
.owner = THIS_MODULE,
- .fb_open = xxxfb_open, /* only if you need it to do something */
- .fb_release = xxxfb_release, /* only if you need it to do something */
+ .fb_open = xxxfb_open,
+ .fb_read = xxxfb_read,
+ .fb_write = xxxfb_write,
+ .fb_release = xxxfb_release,
.fb_check_var = xxxfb_check_var,
- .fb_set_par = xxxfb_set_par, /* optional */
+ .fb_set_par = xxxfb_set_par,
.fb_setcolreg = xxxfb_setcolreg,
- .fb_blank = xxxfb_blank, /* optional */
- .fb_pan_display = xxxfb_pan_display, /* optional */
- .fb_fillrect = xxxfb_fillrect,
- .fb_copyarea = xxxfb_copyarea,
- .fb_imageblit = xxxfb_imageblit,
- .fb_ioctl = xxxfb_ioctl, /* optional */
- .fb_mmap = xxxfb_mmap, /* optional */
+ .fb_blank = xxxfb_blank,
+ .fb_pan_display = xxxfb_pan_display,
+ .fb_fillrect = xxxfb_fillrect, /* Needed !!! */
+ .fb_copyarea = xxxfb_copyarea, /* Needed !!! */
+ .fb_imageblit = xxxfb_imageblit, /* Needed !!! */
+ .fb_cursor = xxxfb_cursor, /* Needed !!! */
+ .fb_rotate = xxxfb_rotate,
+ .fb_poll = xxxfb_poll,
+ .fb_sync = xxxfb_sync,
+ .fb_ioctl = xxxfb_ioctl,
+ .fb_mmap = xxxfb_mmap,
};
/* ------------------------------------------------------------------------- */
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 024a4fb2e963..d8e483bde68a 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -7,13 +7,15 @@
*
* Contributions (and many thanks) :
*
- * 03/2001 James Simmons <jsimmons@linux-fbdev.org>
+ * 03/2001 James Simmons <jsimmons@infradead.org>
* 04/2001 Paul Mundt <lethal@chaoticdreams.org>
* 05/2001 Urs Ganse <ursg@uni.de>
- * (initial work on voodoo2 port, interlace)
+ * (initial work on voodoo2 port, interlace)
+ * 09/2002 Helge Deller <deller@gmx.de>
+ * (enable driver on big-endian machines (hppa), ioctl fixes)
+ * 12/2002 Helge Deller <deller@gmx.de>
+ * (port driver to new frambuffer infrastructure)
*
- *
- * $Id: sstfb.c,v 1.37 2002/05/10 19:35:11 ghoz Exp $
*/
/*
@@ -27,13 +29,9 @@
* misc notes, TODOs, toASKs, and deep thoughts
-TODO: at one time or another test that the mode is acceptable by the monitor
--ASK: I can choose different ordering for the color bitfields (rgba argb ...)
+-ASK: Can I choose different ordering for the color bitfields (rgba argb ...)
wich one should i use ? is there any preferred one ? It seems ARGB is
the one ...
--ASK: later: how to cope with endianness ? the fbi chip has builtin functions
- to do byte swizling /swapping, maybe use that ...
--TODO: check the error paths . if something get wrong, the error doesn't seem
- to be very well handled...if handled at all.. not good.
-TODO: in set_var check the validity of timings (hsync vsync)...
-TODO: check and recheck the use of sst_wait_idle : we dont flush the fifo via
a nop command . so it's ok as long as the commands we pass don't go
@@ -42,9 +40,7 @@
state.
-FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20)
-ASK: I stole "inverse" but seems it doesn't work... check what it realy does...
--TODO: change struct sst_info fb_info from static to array/dynamic
-
- *
+-TODO: change struct fb_info fb_info from static to array/dynamic
*/
/*
@@ -62,24 +58,20 @@
* SST_DEBUG_VAR : debug display/var structs
* 0 : no debug
* 1 : dumps display, fb_var
- * SST_DEBUG_IOCTL : enable sstfb specific ioctls
- * 0 : disable
- * 1 : enable debug ioctls :
+ *
+ * sstfb specific ioctls:
* toggle vga (0x46db) : toggle vga_pass_through
* fill fb (0x46dc) : fills fb
- * dump var (0x46dd) : logs display[0-5].var
- * test disp (0x46de) : draws a test motif
+ * test disp (0x46de) : draws a test image
*/
-#define SST_DEBUG
-//#undef SST_DEBUG
+#undef SST_DEBUG
#define SST_DEBUG_REG 0
#define SST_DEBUG_FUNC 0
#define SST_DEBUG_VAR 0
-#define SST_DEBUG_IOCTL 1
-/* #define EN_24_32_BPP *//* enable 24/32 bpp functions for testing only */
+/* enable 24/32 bpp functions ? (completely untested!) */
#undef EN_24_32_BPP
/*
@@ -88,16 +80,16 @@
1 640x480@75 took from glide
2 1024x768@76 std fb.mode
3 640x480@60 glide default */
-#define DEFAULT_MODE 1
+#define DEFAULT_MODE 3
+
/*
* Includes
*/
-#include <linux/string.h>
#include <linux/config.h>
+#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/delay.h>
@@ -107,145 +99,33 @@
#include <asm/io.h>
#include <asm/ioctl.h>
-
-#include <video/fbcon.h>
-#include <video/fbcon-cfb16.h>
-#ifdef EN_24_32_BPP
-# include <video/fbcon-cfb24.h>
-# include <video/fbcon-cfb32.h>
-#endif
+#include <asm/uaccess.h>
#include "sstfb.h"
-void __Dump_regs(struct sstfb_info *);
-#define Dump_regs __Dump_regs(sst_info) //XXX
-
-/********/
/* initialized by setup */
-static int inverse; /* =0 */ /* invert colormap */
-static int vgapass; /* =0 */ /* enable Vga passthrough cable */
-static int mem; /* =0 */ /* mem size in Mb , 0 = autodetect */
+
+static int inverse; /* invert colormap */
+static int vgapass; /* enable Vga passthrough cable */
+static int mem; /* mem size in Mb , 0 = autodetect */
static int clipping = 1; /* use clipping (slower, safer) */
-static int gfxclk; /* =0 */ /* force FBI freq in Mhz . Dangerous */
-static int slowpci; /* =0 */ /* slow PCI settings */
+static int gfxclk; /* force FBI freq in Mhz . Dangerous */
+static int slowpci; /* slow PCI settings */
static int dev = -2; /* specify device (0..n) -2=all -1=none*/
-static char * mode_option ;
-
-
-/********/
-
-int sstfb_init(void);
-int sstfb_setup(char *options);
-static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void __devexit sstfb_remove(struct pci_dev *pdev);
-
-
-/* Framebuffer API */
-static int sstfb_open(struct fb_info *info, int user);
-static int sstfb_release(struct fb_info *info, int user);
-static int sstfb_get_fix(struct fb_fix_screeninfo *fix,
- int con, struct fb_info *info);
-static int sstfb_get_var(struct fb_var_screeninfo *var,
- int con, struct fb_info *info);
-static int sstfb_set_var(struct fb_var_screeninfo *var,
- int con, struct fb_info *info);
-static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc,
- int con, struct fb_info *info);
-static int sstfb_set_cmap(struct fb_cmap *cmap, int kspc,
- int con, struct fb_info *info);
-static int sstfb_pan_display(struct fb_var_screeninfo *var,
- int con, struct fb_info *info);
-static int sstfb_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg, int con,
- struct fb_info *info);
-
-/* Interface to the low level console driver */
-static int sstfbcon_switch(int con, struct fb_info *info);
-static int sstfbcon_updatevar(int con, struct fb_info *info);
-static void sstfbcon_blank(int blank, struct fb_info *info);
-
-/* Internal routines */
-static void sstfb_install_cmap(int con, struct fb_info *info);
-static int sstfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
- u_int *transp, struct fb_info *info);
-static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info);
-
-static int sstfb_set_par(const struct sstfb_par *par,
- struct sstfb_info *sst_info);
-static int sstfb_decode_var (const struct fb_var_screeninfo *var,
- struct sstfb_par *par,
- const struct sstfb_info *sst_info);
-static int sstfb_encode_var (struct fb_var_screeninfo *var,
- const struct sstfb_par *par,
- const struct sstfb_info *sst_info);
-
-static void sstfb_test16(struct sstfb_info *sst_info);
-
-#ifdef EN_24_32_BPP
-static void sstfb_test32(struct sstfb_info *sst_info);
-#endif
-
-/* Low level routines */
-static int sst_get_memsize(struct sstfb_info *sst_info, u_long *memsize);
-static int __sst_wait_idle(u_long vbase);
-#define sst_wait_idle() __sst_wait_idle(sst_info->mmio.vbase)
-static int sst_detect_dactype(struct sstfb_info *sst_info);
-static int sst_detect_att(struct sstfb_info *sst_info);
-static int sst_detect_ti(struct sstfb_info *sst_info);
-static int sst_detect_ics(struct sstfb_info *sst_info);
-static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t);
-static int sst_set_pll_att_ti(struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);
-static int sst_set_pll_ics(struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);
-static void sst_set_vidmod_att_ti(struct sstfb_info *sst_info, const int bpp);
-static void sst_set_vidmod_ics(struct sstfb_info *sst_info, const int bpp);
-static int sst_init(struct sstfb_info *sst_info);
-static void sst_shutdown(struct sstfb_info *sst_info);
-
-static struct fb_ops sstfb_ops = {
- .owner = THIS_MODULE,
- .fb_open = sstfb_open,
- .fb_release = sstfb_release,
- .fb_get_fix = sstfb_get_fix,
- .fb_get_var = sstfb_get_var,
- .fb_set_var = sstfb_set_var,
- .fb_get_cmap = sstfb_get_cmap,
- .fb_set_cmap = sstfb_set_cmap,
- .fb_pan_display = sstfb_pan_display,
- .fb_ioctl = sstfb_ioctl,
-};
+static char *mode_option __devinitdata;
enum {
ID_VOODOO1 = 0,
ID_VOODOO2 = 1,
};
-#define IS_VOODOO2(info) ((info)->type == ID_VOODOO2 )
+#define IS_VOODOO2(par) ((par)->type == ID_VOODOO2 )
static struct sst_spec voodoo_spec[] __devinitdata = {
- { .name = "Voodoo Graphics",
- .default_gfx_clock = 50000,
- .max_gfxclk = 60, },
- { .name = "Voodoo2",
- .default_gfx_clock = 75000,
- .max_gfxclk = 85, },
-};
-
-static struct pci_device_id sstfb_id_tbl[] __devinitdata = {
- { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 },
- { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 },
- { 0 },
-};
-
-static struct pci_driver sstfb_driver = {
- .name = "sstfb",
- .id_table = sstfb_id_tbl,
- .probe = sstfb_probe,
- .remove = __devexit_p(sstfb_remove),
+ { .name = "Voodoo Graphics", .default_gfx_clock = 50000, .max_gfxclk = 60 },
+ { .name = "Voodoo2", .default_gfx_clock = 75000, .max_gfxclk = 85 },
};
static struct fb_var_screeninfo sstfb_default =
@@ -256,55 +136,88 @@ static struct fb_var_screeninfo sstfb_default =
0, 0, -1, -1, 0,
25000, 86, 41, 23, 1, 127, 4,
0, FB_VMODE_NONINTERLACED };
-#endif
-#if ( DEFAULT_MODE == 1 )
+#elif ( DEFAULT_MODE == 1 )
{/* 640x480@75, 16 bpp .borowed from glide/sst1/include/sst1init.h */
640, 480, 640, 480, 0, 0, 16, 0,
{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
0, 0, -1, -1, 0,
31746, 118, 17, 16, 1, 63, 3,
0, FB_VMODE_NONINTERLACED };
-#endif
-#if ( DEFAULT_MODE == 2 )
+#elif ( DEFAULT_MODE == 2 )
{ /* 1024x768@76 took from my /etc/fb.modes */
1024, 768, 1024, 768,0, 0, 16,0,
{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
0, 0, -1, -1, 0,
11764, 208, 8, 36, 16, 120, 3 ,
0, FB_VMODE_NONINTERLACED };
-#endif
-#if ( DEFAULT_MODE == 3 )
+#elif ( DEFAULT_MODE == 3 )
{ /* 640x480@60 , 16bpp glide default ?*/
640, 480, 640, 480, 0, 0, 16, 0,
{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
0, 0, -1, -1, 0,
39721 , 38, 26 , 25 ,18 , 96 ,2,
0, FB_VMODE_NONINTERLACED };
+#elif
+ #error "Invalid DEFAULT_MODE value !"
#endif
-static struct dac_switch dacs[] __devinitdata = {
- { .name = "TI TVP3409",
- .detect = sst_detect_ti,
- .set_pll = sst_set_pll_att_ti,
- .set_vidmod = sst_set_vidmod_att_ti },
-
- { .name = "AT&T ATT20C409",
- .detect = sst_detect_att,
- .set_pll = sst_set_pll_att_ti,
- .set_vidmod = sst_set_vidmod_att_ti },
- { .name = "ICS ICS5342",
- .detect = sst_detect_ics,
- .set_pll = sst_set_pll_ics,
- .set_vidmod = sst_set_vidmod_ics },
-};
-
/*
- *
- * Definitions
- *
+ * debug functions
*/
+static void sstfb_test16(struct fb_info *info);
+#if EN_24_32_BPP
+static void sstfb_test32(struct fb_info *info);
+#endif
+
+#if 0
+static void __Dump_regs (struct sstfb_info *sst_info)
+{
+ struct { u32 reg ; char * reg_name;} pci_regs [] = {
+ { PCI_INIT_ENABLE, "initenable"},
+ { PCI_VCLK_ENABLE, "enable vclk"},
+ { PCI_VCLK_DISABLE, "disable vclk"},
+ };
+
+ struct { u32 reg ; char * reg_name;} sst_regs [] = {
+ {FBIINIT0,"fbiinit0"},
+ {FBIINIT1,"fbiinit1"},
+ {FBIINIT2,"fbiinit2"},
+ {FBIINIT3,"fbiinit3"},
+ {FBIINIT4,"fbiinit4"},
+ {FBIINIT5,"fbiinit5"},
+ {FBIINIT6,"fbiinit6"},
+ {FBIINIT7,"fbiinit7"},
+ {LFBMODE,"lfbmode"},
+ {FBZMODE,"fbzmode"},
+ };
+ int pci_s = sizeof(pci_regs)/sizeof(*pci_regs);
+ int sst_s = sizeof(sst_regs)/sizeof(*sst_regs);
+ u32 pci_res[pci_s];
+ u32 sst_res[sst_s];
+
+ struct pci_dev * dev = sst_info->dev;
+
+ int i;
+
+ for (i=0; i < pci_s ; i++ ) {
+ pci_read_config_dword ( dev, pci_regs[i].reg , &pci_res[i]) ;
+ }
+ for (i=0; i < sst_s ; i++ ) {
+ sst_res[i]=sst_read(sst_regs[i].reg);
+ }
+
+ dprintk ("Dump regs\n");
+ for (i=0; i < pci_s ; i++ ) {
+ dprintk("%s = %0#10x\n", pci_regs[i].reg_name , pci_res[i]) ;
+ }
+ for (i=0; i < sst_s ; i++ ) {
+ dprintk("%s = %0#10x\n", sst_regs[i].reg_name , sst_res[i]) ;
+ }
+}
+#endif
+
#if (SST_DEBUG_VAR > 0)
/* debug info / dump a fb_var_screeninfo */
static void sst_dbg_print_var(struct fb_var_screeninfo *var) {
@@ -331,15 +244,16 @@ static void sst_dbg_print_var(struct fb_var_screeninfo *var) {
#if (SST_DEBUG_REG > 0)
static void sst_dbg_print_read_reg (u32 reg, u32 val) {
- char * regname =NULL;
+ const char *regname;
switch (reg) {
- case FBIINIT0: regname="FbiInit0"; break;
- case FBIINIT1: regname="FbiInit1"; break;
- case FBIINIT2: regname="FbiInit2"; break;
- case FBIINIT3: regname="FbiInit3"; break;
- case FBIINIT4: regname="FbiInit4"; break;
- case FBIINIT5: regname="FbiInit5"; break;
- case FBIINIT6: regname="FbiInit6"; break;
+ case FBIINIT0: regname = "FbiInit0"; break;
+ case FBIINIT1: regname = "FbiInit1"; break;
+ case FBIINIT2: regname = "FbiInit2"; break;
+ case FBIINIT3: regname = "FbiInit3"; break;
+ case FBIINIT4: regname = "FbiInit4"; break;
+ case FBIINIT5: regname = "FbiInit5"; break;
+ case FBIINIT6: regname = "FbiInit6"; break;
+ default: regname = NULL; break;
}
if (regname == NULL)
r_ddprintk("sst_read(%#x): %#x\n", reg, val);
@@ -348,16 +262,16 @@ static void sst_dbg_print_read_reg (u32 reg, u32 val) {
}
static void sst_dbg_print_write_reg (u32 reg, u32 val) {
- char * regname = NULL;
-
+ const char *regname;
switch (reg) {
- case FBIINIT0: regname="FbiInit0"; break;
- case FBIINIT1: regname="FbiInit1"; break;
- case FBIINIT2: regname="FbiInit2"; break;
- case FBIINIT3: regname="FbiInit3"; break;
- case FBIINIT4: regname="FbiInit4"; break;
- case FBIINIT5: regname="FbiInit5"; break;
- case FBIINIT6: regname="FbiInit6"; break;
+ case FBIINIT0: regname = "FbiInit0"; break;
+ case FBIINIT1: regname = "FbiInit1"; break;
+ case FBIINIT2: regname = "FbiInit2"; break;
+ case FBIINIT3: regname = "FbiInit3"; break;
+ case FBIINIT4: regname = "FbiInit4"; break;
+ case FBIINIT5: regname = "FbiInit5"; break;
+ case FBIINIT6: regname = "FbiInit6"; break;
+ default: regname = NULL; break;
}
if (regname == NULL)
r_ddprintk("sst_write(%#x, %#x)\n", reg, val);
@@ -365,25 +279,27 @@ static void sst_dbg_print_write_reg (u32 reg, u32 val) {
r_dprintk(" sst_write(%s, %#x)\n", regname, val);
}
#else /* (SST_DEBUG_REG > 0) */
-# define sst_dbg_print_read_reg(reg, val) do {}while(0)
-# define sst_dbg_print_write_reg(reg, val) do {}while(0)
+# define sst_dbg_print_read_reg(reg, val) do {} while(0)
+# define sst_dbg_print_write_reg(reg, val) do {} while(0)
#endif /* (SST_DEBUG_REG > 0) */
+/*
+ * hardware access functions
+ */
+
/* register access */
-#define sst_read(reg) __sst_read(sst_info->mmio.vbase, reg)
-#define sst_write(reg,val) __sst_write(sst_info->mmio.vbase, reg, val)
-#define sst_set_bits(reg,val) __sst_set_bits(sst_info->mmio.vbase, reg, val)
-#define sst_unset_bits(reg,val) __sst_unset_bits(sst_info->mmio.vbase, reg, val)
-#define sst_dac_read(reg) __sst_dac_read(sst_info->mmio.vbase, reg)
-#define sst_dac_write(reg,val) __sst_dac_write(sst_info->mmio.vbase, reg, val)
-#define dac_i_read(reg) __dac_i_read(sst_info->mmio.vbase, reg)
-#define dac_i_write(reg,val) __dac_i_write(sst_info->mmio.vbase, reg, val)
+#define sst_read(reg) __sst_read(par->mmio_vbase, reg)
+#define sst_write(reg,val) __sst_write(par->mmio_vbase, reg, val)
+#define sst_set_bits(reg,val) __sst_set_bits(par->mmio_vbase, reg, val)
+#define sst_unset_bits(reg,val) __sst_unset_bits(par->mmio_vbase, reg, val)
+#define sst_dac_read(reg) __sst_dac_read(par->mmio_vbase, reg)
+#define sst_dac_write(reg,val) __sst_dac_write(par->mmio_vbase, reg, val)
+#define dac_i_read(reg) __dac_i_read(par->mmio_vbase, reg)
+#define dac_i_write(reg,val) __dac_i_write(par->mmio_vbase, reg, val)
static inline u32 __sst_read(u_long vbase, u32 reg)
{
- u32 ret;
-
- ret = readl(vbase + reg);
+ u32 ret = readl(vbase + reg);
sst_dbg_print_read_reg(reg, ret);
return ret;
}
@@ -406,6 +322,37 @@ static inline void __sst_unset_bits(u_long vbase, u32 reg, u32 val)
__sst_write(vbase, reg, __sst_read(vbase, reg) & ~val);
}
+/*
+ * wait for the fbi chip. ASK: what happens if the fbi is stuck ?
+ *
+ * the FBI is supposed to be ready if we receive 5 time
+ * in a row a "idle" answer to our requests
+ */
+
+#define sst_wait_idle() __sst_wait_idle(par->mmio_vbase)
+
+static int __sst_wait_idle(u_long vbase)
+{
+ int count = 0;
+
+ f_ddprintk("sst_wait_idle\n");
+ while(1) {
+ if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
+ f_dddprintk("status: busy\n");
+/* FIXME basicaly, this is a busy wait. maybe not that good. oh well;
+ * this is a small loop after all.
+ * Or maybe we should use mdelay() or udelay() here instead ? */
+ count = 0;
+ } else {
+ count++;
+ f_dddprintk("status: idle(%d)\n", count);
+ }
+ if (count >= 5) return 1;
+/* XXX do something to avoid hanging the machine if the voodoo is out */
+ }
+}
+
+
/* dac access */
/* dac_read should be remaped to FbiInit2 (via the pci reg init_enable) */
static u8 __sst_dac_read(u_long vbase, u8 reg)
@@ -421,10 +368,10 @@ static u8 __sst_dac_read(u_long vbase, u8 reg)
reg &= 0x07;
__sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );
__sst_wait_idle(vbase);
- /*udelay(10);*/
- ret=(__sst_read(vbase, DAC_READ) & 0xff);
+ /* udelay(10); */
+ ret = __sst_read(vbase, DAC_READ) & 0xff;
r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret);
- return (u8)ret;
+ return ret;
}
static void __sst_dac_write(u_long vbase, u8 reg, u8 val)
@@ -456,270 +403,188 @@ static void __dac_i_write(u_long vbase, u8 reg,u8 val)
__sst_dac_write(vbase, DACREG_DATA_I, val);
}
-/*
- *
- * Internal routines
+/* compute the m,n,p , returns the real freq
+ * (ics datasheet : N <-> N1 , P <-> N2)
*
+ * Fout= Fref * (M+2)/( 2^P * (N+2))
+ * we try to get close to the asked freq
+ * with P as high, and M as low as possible
+ * range:
+ * ti/att : 0 <= M <= 255; 0 <= P <= 3; 0<= N <= 63
+ * ics : 1 <= M <= 127; 0 <= P <= 3; 1<= N <= 31
+ * we'll use the lowest limitation, should be precise enouth
*/
-
-static void sstfb_install_cmap(int con, struct fb_info *info)
-{
-#define sst_info ((struct sstfb_info *) info)
- f_dprintk("sstfb_install_cmap(con: %d)\n",con);
- f_ddprintk("currcon: %d\n", sst_info->currcon);
- if (con != sst_info->currcon)
- return;
- if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, 1, sstfb_setcolreg, info);
- else
- fb_set_cmap(
- fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- 1, sstfb_setcolreg, info);
-#undef sst_info
-}
-
-static int sstfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
- u_int *transp, struct fb_info *info)
-{
-#define sst_info ((struct sstfb_info *) info)
- f_dddprintk("sstfb_getcolreg\n");
- if (regno >= 16) return 1;
-
- *red = sst_info->palette[regno].red;
- *green = sst_info->palette[regno].green;
- *blue = sst_info->palette[regno].blue;
- *transp = sst_info->palette[regno].transp;
- f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n",
- regno,*red, *green, *blue, *transp);
- return 0;
-#undef sst_info
-}
-
-static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info)
+static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
{
-#define sst_info ((struct sstfb_info *) info)
- u32 col;
- struct display * disp;
+ int m, m2, n, p, best_err, fout;
+ int best_n = -1;
+ int best_m = -1;
- f_dddprintk("sstfb_setcolreg\n");
- f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n",
- regno, red, green, blue, transp);
- if (regno >= 16) return 1;
+ f_dprintk("sst_calc_pll(%dKhz)\n", freq);
+ best_err = freq;
+ p = 3;
+ /* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/
+ while (((1 << p) * freq > VCO_MAX) && (p >= 0))
+ p--;
+ if (p == -1)
+ return -EINVAL;
+ for (n = 1; n < 32; n++) {
+ /* calc 2 * m so we can round it later*/
+ m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ;
- sst_info->palette[regno].red = red;
- sst_info->palette[regno].green = green;
- sst_info->palette[regno].blue = blue;
- sst_info->palette[regno].transp= transp;
-
- disp=&sst_info->disp;
- red >>= (16 - disp->var.red.length);
- green >>= (16 - disp->var.green.length);
- blue >>= (16 - disp->var.blue.length);
- transp >>= (16 - disp->var.transp.length);
- col = (red << disp->var.red.offset)
- | (green << disp->var.green.offset)
- | (blue << disp->var.blue.offset)
- | (transp << disp->var.transp.offset);
-
- switch(disp->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB16
- case 16:
- sst_info->fbcon_cmap.cfb16[regno]=(u16)col;
- break;
-#endif
-#ifdef EN_24_32_BPP
-#ifdef FBCON_HAS_CFB24
- case 24:
- sst_info->fbcon_cmap.cfb32[regno]=col;
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
- sst_info->fbcon_cmap.cfb32[regno]=col;
- break;
-#endif
-#endif
- default:
- eprintk("bug line %d: bad depth '%u'\n",__LINE__,
- disp->var.bits_per_pixel);
- break;
+ m = (m2 % 2 ) ? m2/2+1 : m2/2 ;
+ if (m >= 128)
+ break;
+ fout = (DAC_FREF * (m + 2)) / ((1 << p) * (n + 2));
+ if ((ABS(fout - freq) < best_err) && (m > 0)) {
+ best_n = n;
+ best_m = m;
+ best_err = ABS(fout - freq);
+ /* we get the lowest m , allowing 0.5% error in freq*/
+ if (200*best_err < freq) break;
+ }
}
- f_dddprintk("bpp: %d . encoded color: %#x\n",
- disp->var.bits_per_pixel, col);
+ if (best_n == -1) /* unlikely, but who knows ? */
+ return -EINVAL;
+ t->p = p;
+ t->n = best_n;
+ t->m = best_m;
+ *freq_out = (DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2));
+ f_ddprintk ("m: %d, n: %d, p: %d, F: %dKhz\n",
+ t->m, t->n, t->p, *freq_out);
return 0;
-#undef sst_info
}
-/* set par according to var ( checks var ) */
-static int sstfb_decode_var (const struct fb_var_screeninfo *var,
- struct sstfb_par *par,
- const struct sstfb_info *sst_info)
+/*
+ * Frame buffer API
+ */
+static int sstfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
- int real_length;
-
- f_dprintk("sstfb_decode_var\n");
- /* Check var validity */
- par->valid=0;
-
- memset(par, 0, sizeof(par));
- par->xDim = var->xres;
- par->hSyncOn = var->hsync_len;
- par->hSyncOff = var->xres + var->right_margin + var->left_margin;
- par->hBackPorch = var->left_margin;
- par->yDim = var->yres;
- par->vSyncOn = var->vsync_len;
- par->vSyncOff = var->yres + var->lower_margin + var->upper_margin;
- par->vBackPorch = var->upper_margin;
-
- if(sst_calc_pll (PS2KHZ(var->pixclock), &par->freq, &par->pll)) {
- eprintk("Pixclock %d out of range\n", var->pixclock);
- return -EINVAL; //XXX
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
+ int hSyncOff = var->xres + var->right_margin + var->left_margin;
+ int vSyncOff = var->yres + var->lower_margin + var->upper_margin;
+ int vBackPorch = var->left_margin, yDim = var->yres, vSyncOn = var->vsync_len;
+ int tiles_in_X, real_length;
+ unsigned int freq;
+
+ f_dprintk("sstfb_check_var()\n");
+
+ if (sst_calc_pll(PICOS2KHZ(var->pixclock), &freq, &par->pll)) {
+ eprintk("Pixclock at %ld KHZ out of range\n", PICOS2KHZ(var->pixclock));
+ return -EINVAL;
}
-
- par->sync=var->sync & (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
-
- par->vmode=var->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);
- /* in laced mode, vBackPorch should be even. odd -> funky display */
- if (par->vmode & FB_VMODE_INTERLACED)
- par->vBackPorch += (par->vBackPorch % 2);
- if (par->vmode & FB_VMODE_DOUBLE) {
- par->vBackPorch <<= 1;
- par->yDim <<=1;
- par->vSyncOn <<=1;
- par->vSyncOff <<=1;
+ var->pixclock = KHZ2PICOS(freq);
+
+ if (var->vmode & FB_VMODE_INTERLACED)
+ vBackPorch += (vBackPorch % 2);
+ if (var->vmode & FB_VMODE_DOUBLE) {
+ vBackPorch <<= 1;
+ yDim <<=1;
+ vSyncOn <<=1;
+ vSyncOff <<=1;
}
switch (var->bits_per_pixel) {
case 0 ... 16 :
- par->bpp = 16;
+ var->bits_per_pixel = 16;
break;
#ifdef EN_24_32_BPP
case 17 ... 24 :
- par->bpp = 24;
+ var->bits_per_pixel = 24;
break;
case 25 ... 32 :
- par->bpp = 32;
+ var->bits_per_pixel = 32;
break;
#endif
default :
- eprintk ("Unsupported bpp %d\n", par->bpp);
+ eprintk("Unsupported bpp %d\n", var->bits_per_pixel);
return -EINVAL;
break;
}
-
- if (IS_VOODOO2(sst_info)) {
- /* voodoo2 has 32 pixel wide tiles , BUT stange things
- happen with odd number of tiles */
- par->tiles_in_X= (par->xDim + 63 ) / 64 * 2;
- } else {
- /* voodoo1 has 64 pixels wide tiles. */
- par->tiles_in_X= (par->xDim + 63 ) / 64;
- }
-
+
/* validity tests */
- if((par->xDim <= 1) || (par->yDim <= 0 )
- || (par->hSyncOn <= 1)
- || (par->hSyncOff <= 1)
- || (par->hBackPorch <= 2)
- || (par->vSyncOn <= 0)
- || (par->vSyncOff <= 0)
- || (par->vBackPorch <= 0)
- || (par->tiles_in_X <= 0)) {
+ if ((var->xres <= 1) || (yDim <= 0 )
+ || (var->hsync_len <= 1)
+ || (hSyncOff <= 1)
+ || (var->left_margin <= 2)
+ || (vSyncOn <= 0)
+ || (vSyncOff <= 0)
+ || (vBackPorch <= 0)) {
return -EINVAL;
}
- if (IS_VOODOO2(sst_info)) {
+
+ if (IS_VOODOO2(par)) {
/* Voodoo 2 limits */
- if(((par->xDim-1) >= POW2(11)) || (par->yDim >= POW2(11))) {
- eprintk ("Unsupported resolution %dx%d\n",
+ tiles_in_X = (var->xres + 63 ) / 64 * 2;
+
+ if (((var->xres - 1) >= POW2(11)) || (yDim >= POW2(11))) {
+ eprintk("Unsupported resolution %dx%d\n",
var->xres, var->yres);
return -EINVAL;
}
- if (((par->hSyncOn-1) >= POW2(9))
- || ((par->hSyncOff-1) >= POW2(11))
- || ((par->hBackPorch-2) >= POW2(9))
- || (par->vSyncOn >= POW2(13))
- || (par->vSyncOff >= POW2(13))
- || (par->vBackPorch >= POW2(9))
- || (par->tiles_in_X >= POW2(6))) {
- eprintk ("Unsupported Timing\n");
+
+ if (((var->hsync_len-1) >= POW2(9))
+ || ((hSyncOff-1) >= POW2(11))
+ || ((var->left_margin - 2) >= POW2(9))
+ || (vSyncOn >= POW2(13))
+ || (vSyncOff >= POW2(13))
+ || (vBackPorch >= POW2(9))
+ || (tiles_in_X >= POW2(6))
+ || (tiles_in_X <= 0)) {
+ eprintk("Unsupported Timings\n");
return -EINVAL;
}
} else {
/* Voodoo limits */
- if (par->vmode) {
+ tiles_in_X = (var->xres + 63 ) / 64;
+
+ if (var->vmode) {
eprintk("Interlace/Doublescan not supported %#x\n",
- par->vmode);
+ var->vmode);
return -EINVAL;
}
- if(((par->xDim-1) >= POW2(10)) || (par->yDim >= POW2(10))) {
- eprintk ("Unsupported resolution %dx%d\n",
+ if (((var->xres - 1) >= POW2(10)) || (var->yres >= POW2(10))) {
+ eprintk("Unsupported resolution %dx%d\n",
var->xres, var->yres);
return -EINVAL;
}
- if (((par->hSyncOn-1) >= POW2(8))
- || ((par->hSyncOff-1) >= POW2(10))
- || ((par->hBackPorch-2) >= POW2(8))
- || (par->vSyncOn >= POW2(12))
- || (par->vSyncOff >= POW2(12))
- || (par->vBackPorch >= POW2(8))
- || (par->tiles_in_X >= POW2(4))) {
- eprintk ("Unsupported Timings\n");
+ if (((var->hsync_len - 1) >= POW2(8))
+ || ((hSyncOff-1) >= POW2(10))
+ || ((var->left_margin - 2) >= POW2(8))
+ || (vSyncOn >= POW2(12))
+ || (vSyncOff >= POW2(12))
+ || (vBackPorch >= POW2(8))
+ || (tiles_in_X >= POW2(4))
+ || (tiles_in_X <= 0)) {
+ eprintk("Unsupported Timings\n");
return -EINVAL;
}
}
- /* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem*/
- /* FIXME: i don't like this... looks wrong*/
- real_length = par->tiles_in_X * (IS_VOODOO2(sst_info) ? 32 : 64 )
- * ((par->bpp == 16) ? 2 : 4);
+ /* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem */
+ /* FIXME: i don't like this... looks wrong */
+ real_length = tiles_in_X * (IS_VOODOO2(par) ? 32 : 64 )
+ * ((var->bits_per_pixel == 16) ? 2 : 4);
- if ((real_length * var->yres) > sst_info->video.len) {
- eprintk ("Not enough video memory\n");
+ if ((real_length * yDim) > info->fix.smem_len) {
+ eprintk("Not enough video memory\n");
return -ENOMEM;
}
- par->valid=1;
- return 0;
-}
-/* sets var according to par (basicaly, sets sane values) */
-static int sstfb_encode_var (struct fb_var_screeninfo *var,
- const struct sstfb_par *par,
- const struct sstfb_info *sst_info)
-{
- memset(var,0,sizeof(struct fb_var_screeninfo));
-
- var->xres = par->xDim;
- var->yres = par->yDim;
- var->xres_virtual = par->xDim;
- var->yres_virtual = par->yDim;
- var->bits_per_pixel = par->bpp;
- /* {x|y}offset = 0 */
- var->height = -1;
- var->width = -1;
- var->pixclock = KHZ2PS(par->freq);
- var->left_margin = par->hBackPorch;
- var->right_margin = par->hSyncOff - par->xDim - par->hBackPorch;
- var->upper_margin = par->vBackPorch;
- var->lower_margin = par->vSyncOff - par->yDim - par->vBackPorch;
- var->hsync_len = par->hSyncOn;
- var->vsync_len = par->vSyncOn;
- var->sync = par->sync;
- var->vmode = par->vmode;
- if (var->vmode & FB_VMODE_DOUBLE) {
- var->yres >>=1;
- var->yres_virtual >>=1;
- var->vsync_len >>=1;
- var->upper_margin >>=1;
- var->lower_margin >>=1;
- }
+ var->sync &= (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
+ var->vmode &= (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);
+ var->xoffset = 0;
+ var->yoffset = 0;
+ var->height = -1;
+ var->width = -1;
/*
* correct the color bit fields
*/
- /* var->{red|green|blue}.msb_right = 0; */
+ /* var->{red|green|blue}.msb_right = 0; */
- switch (par->bpp) {
+ switch (var->bits_per_pixel) {
case 16: /* RGB 565 LfbMode 0 */
var->red.length = 5;
var->green.length = 6;
@@ -746,309 +611,311 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var,
break;
#endif
default:
- eprintk ("bug line %d: bad depth '%u'\n", __LINE__, par->bpp);
- break;
+ BUG();
+ return -EINVAL;
}
return 0;
}
-/*
- * Frame buffer API
- */
-
-static int sstfb_open(struct fb_info *info, int user)
+static int sstfb_set_par(struct fb_info *info)
{
- f_dprintk("sstfb_open(user: %d)\n",user);
- return 0;
-}
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
+ u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
+ struct pci_dev *sst_dev = par->dev;
+ unsigned int freq;
+ int ntiles;
-static int sstfb_release(struct fb_info *info, int user)
-{
- f_dprintk("sstfb_release(user: %d)\n",user);
- return 0;
-}
+ par->hSyncOff = info->var.xres + info->var.right_margin + info->var.left_margin;
-static int sstfb_get_fix(struct fb_fix_screeninfo *fix,
- int con, struct fb_info *info)
-{
-#define sst_info ((struct sstfb_info *) info)
+ par->yDim = info->var.yres;
+ par->vSyncOn = info->var.vsync_len;
+ par->vSyncOff = info->var.yres + info->var.lower_margin + info->var.upper_margin;
+ par->vBackPorch = info->var.upper_margin;
- struct fb_var_screeninfo *var;
+ /* We need par->pll */
+ sst_calc_pll(PICOS2KHZ(info->var.pixclock), &freq, &par->pll);
- f_dprintk("sstfb_get_fix(con: %d)\n",con);
- if (con == -1)
- sstfb_encode_var(var, &sst_info->current_par, sst_info);
- else
- var = &fb_display[con].var;
+ if (info->var.vmode & FB_VMODE_INTERLACED)
+ par->vBackPorch += (par->vBackPorch % 2);
+ if (info->var.vmode & FB_VMODE_DOUBLE) {
+ par->vBackPorch <<= 1;
+ par->yDim <<=1;
+ par->vSyncOn <<=1;
+ par->vSyncOff <<=1;
+ }
- strcpy(fix->id, sst_info->info.modename);
- /* lfb phys address = membase + 4Mb */
- fix->smem_start = sst_info->video.base;
- fix->smem_len = sst_info->video.len;
+ if (IS_VOODOO2(par)) {
+ /* voodoo2 has 32 pixel wide tiles , BUT stange things
+ happen with odd number of tiles */
+ par->tiles_in_X= (info->var.xres + 63 ) / 64 * 2;
+ } else {
+ /* voodoo1 has 64 pixels wide tiles. */
+ par->tiles_in_X= (info->var.xres + 63 ) / 64;
+ }
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->visual = FB_VISUAL_TRUECOLOR;
- /*
- * According to the specs, the linelength must be of 1024 *pixels*.
- * and the 24bpp mode is in fact a 32 bpp mode.
- */
- fix->line_length = (var->bits_per_pixel == 16) ? 2048 : 4096 ;
- return 0;
-#undef sst_info
-}
+ f_dprintk("sst_set_par(%dx%d)\n", info->var.xres, info->var.yres);
+ f_ddprintk("var->hsync_len hSyncOff var->vsync_len vSyncOff\n");
+ f_ddprintk("%-7d %-8d %-7d %-8d\n",
+ info->var.hsync_len, par->hSyncOff,
+ par->vSyncOn, par->vSyncOff);
+ f_ddprintk("var->left_margin var->upper_margin var->xres var->yres Freq\n");
+ f_ddprintk("%-10d %-10d %-4d %-4d %-8d\n",
+ info->var.left_margin, var->upper_margin,
+ info->var.xres, info->var.yres, par->freq);
-static int sstfb_get_var(struct fb_var_screeninfo *var,
- int con, struct fb_info *info)
-{
-#define sst_info ((struct sstfb_info *) info)
- f_dprintk("sstfb_get_var(con: %d)\n",con);
- if (con == -1)
- sstfb_encode_var(var, &sst_info->current_par, sst_info);
- else
- *var = fb_display[con].var;
- print_var(var, "var");
- return 0;
-#undef sst_info
- }
+ sst_write(NOPCMD, 0);
+ sst_wait_idle();
+ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
+ sst_set_bits(FBIINIT1, VIDEO_RESET);
+ sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
+ sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
+ sst_wait_idle();
-static int sstfb_set_var(struct fb_var_screeninfo *var,
- int con, struct fb_info *info)
-{
-#define sst_info ((struct sstfb_info *) info)
+ /*sst_unset_bits (FBIINIT0, FBI_RESET); / reenable FBI ? */
- struct sstfb_par par;
- struct display *display;
- int err;
- int old_bpp,old_xres,old_yres;
-
- f_dprintk("sstfb_set_var(con: %d)\n",con);
- f_ddprintk("xres yres vxres vyres bpp activate\n");
- f_ddprintk("%-4d %-4d %-5d %-5d %-3d %#-8x\n",
- var->xres,var->yres,var->xres_virtual,var->yres_virtual,
- var->bits_per_pixel,var->activate);
- if (con < 0)
- display = &sst_info->disp;
- else
- display = &fb_display[con];
+ sst_write(BACKPORCH, par->vBackPorch << 16 | (info->var.left_margin - 2));
+ sst_write(VIDEODIMENSIONS, par->yDim << 16 | (info->var.xres - 1));
+ sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (info->var.hsync_len - 1));
+ sst_write(VSYNC, par->vSyncOff << 16 | par->vSyncOn);
- if ((err = sstfb_decode_var(var, &par, sst_info)))
- return err;
- sstfb_encode_var (var, &par, sst_info);
+ fbiinit2=sst_read(FBIINIT2);
+ fbiinit3=sst_read(FBIINIT3);
- switch (var->activate & FB_ACTIVATE_MASK) {
- case FB_ACTIVATE_TEST:
- return 0;
- case FB_ACTIVATE_NXTOPEN:
- case FB_ACTIVATE_NOW:
- break;
- default:
- return -EINVAL;
+ /* everything is reset. we enable fbiinit2/3 remap : dac acces ok */
+ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+ PCI_EN_INIT_WR | PCI_REMAP_DAC );
+
+ par->dac_sw.set_vidmod(info, info->var.bits_per_pixel);
+
+ /* set video clock */
+ par->dac_sw.set_pll(info, &par->pll, VID_CLOCK);
+
+ /* disable fbiinit2/3 remap */
+ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+ PCI_EN_INIT_WR);
+
+ /* restore fbiinit2/3 */
+ sst_write(FBIINIT2,fbiinit2);
+ sst_write(FBIINIT3,fbiinit3);
+
+ fbiinit1 = (sst_read(FBIINIT1) & VIDEO_MASK)
+ | EN_DATA_OE
+ | EN_BLANK_OE
+ | EN_HVSYNC_OE
+ | EN_DCLK_OE
+/* | (15 << TILES_IN_X_SHIFT)*/
+ | SEL_INPUT_VCLK_2X
+/* | (2 << VCLK_2X_SEL_DEL_SHIFT)
+ | (2 << VCLK_DEL_SHIFT)*/;
+/* try with vclk_in_delay =0 (bits 29:30) , vclk_out_delay =0 (bits(27:28)
+ in (near) future set them accordingly to revision + resolution (cf glide)
+ first understand what it stands for :)
+ FIXME: there are some artefacts... check for the vclk_in_delay
+ lets try with 6ns delay in both vclk_out & in...
+ doh... they're still there :\
+*/
+
+ ntiles = par->tiles_in_X;
+ if (IS_VOODOO2(par)) {
+ fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT
+ | ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT ;
+/* as the only value of importance for us in fbiinit6 is tiles in X (lsb),
+ and as reading fbinit 6 will return crap (see FBIINIT6_DEFAULT) we just
+ write our value. BTW due to the dac unable to read odd number of tiles, this
+ field is always null ... */
+ fbiinit6 = (ntiles & 0x1) << TILES_IN_X_LSB_SHIFT;
}
- old_xres = display->var.xres;
- old_yres = display->var.yres;
- old_bpp = display->var.bits_per_pixel;
- display->var = *var;
-
- if ((old_xres != var->xres) || (old_yres != var->yres)
- || (old_bpp != var->bits_per_pixel)) {
- /* 2-3 lignes redondantes avec get_fix */
- display->screen_base = (char *) sst_info->video.vbase;
- display->visual = FB_VISUAL_TRUECOLOR;
- display->type = FB_TYPE_PACKED_PIXELS;
- display->type_aux = 0;
- display->ypanstep = 0;
- display->ywrapstep = 0;
- display->line_length = (var->bits_per_pixel==16) ? 2048 : 4096;
- display->inverse = 0;
- switch (var->bits_per_pixel) {
-#ifdef FBCON_HAS_CFB16
- case 16:
- display->dispsw = &fbcon_cfb16;
- display->dispsw_data = sst_info->fbcon_cmap.cfb16;
- break;
-#endif
+ else
+ fbiinit1 |= ntiles << TILES_IN_X_SHIFT;
+
+ switch (info->var.bits_per_pixel) {
+ case 16:
+ fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL;
+ break;
#ifdef EN_24_32_BPP
-#if defined (FBCON_HAS_CFB24) || defined (FBCON_HAS_CFB32 )
- case 24: /*24bpp non packed <=> 32 bpp */
- case 32:
- display->dispsw = &fbcon_cfb32;
- display->dispsw_data = sst_info->fbcon_cmap.cfb32;
- break;
-#endif
+ case 24:
+ case 32:
+/* orig sst_set_bits(FBIINIT1, SEL_SOURCE_VCLK_2X_DIV2 | EN_24BPP); */
+ fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL | EN_24BPP;
+ break;
#endif
- default:
- display->dispsw = &fbcon_dummy;
- break;
- }
- display->scrollmode = SCROLL_YREDRAW;
- if (sst_info->info.changevar) {
- v_dprintk("fb_info.changevar(con: %d)\n", con);
- (*sst_info->info.changevar)(con);
- v_dprintk("fb_info.changevar: done \n");
- } else {
- v_dprintk("fb_info.changevar() == NULL . \n");
- }
+ default:
+ dprintk("bug line %d: bad depth '%u'\n", __LINE__,
+ info->var.bits_per_pixel );
+ return 0;
+ break;
}
-
- if ((con == -1) || (con==sst_info->currcon)) {
- sstfb_set_par (&par, sst_info);
+ sst_write(FBIINIT1, fbiinit1);
+ if (IS_VOODOO2(par)) {
+ sst_write(FBIINIT6, fbiinit6);
+ fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;
+ if (info->var.vmode & FB_VMODE_INTERLACED)
+ fbiinit5 |= INTERLACE;
+ if (info->var.vmode & FB_VMODE_DOUBLE )
+ fbiinit5 |= VDOUBLESCAN;
+ if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ fbiinit5 |= HSYNC_HIGH;
+ if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ fbiinit5 |= VSYNC_HIGH;
+ sst_write(FBIINIT5, fbiinit5);
}
- print_var(var, "var");
- print_var(&display->var, "&display->var");
+ sst_wait_idle();
+ sst_unset_bits(FBIINIT1, VIDEO_RESET);
+ sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
+ sst_set_bits(FBIINIT2, EN_DRAM_REFRESH);
+/* disables fbiinit writes */
+ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
- if (old_bpp != var->bits_per_pixel) {
- if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
- return err;
- sstfb_install_cmap(con, info);
+ /* set lfbmode : set mode + front buffer for reads/writes
+ + disable pipeline */
+ switch (info->var.bits_per_pixel) {
+ case 16:
+ lfbmode = LFB_565;
+ break;
+#ifdef EN_24_32_BPP
+ case 24:
+ lfbmode = LFB_888;
+ break;
+ case 32:
+ lfbmode = LFB_8888;
+ break;
+#endif
+ default:
+ dprintk("bug line %d: bad depth '%u'\n", __LINE__,
+ info->var.bits_per_pixel );
+ return 0;
+ break;
}
- return 0;
-#undef sst_info
-}
-
-
-static int sstfb_set_cmap(struct fb_cmap *cmap, int kspc,
- int con, struct fb_info *info)
-{
-#define sst_info ((struct sstfb_info *) info)
- struct display *d = (con<0) ? info->disp : fb_display + con;
+#if defined(__BIG_ENDIAN)
+ /* Enable byte-swizzle functionality in hardware.
+ * With this enabled, all our read- and write-accesses to
+ * the voodoo framebuffer can be done in native format, and
+ * the hardware will automatically convert it to little-endian.
+ * (tested on HP-PARISC, deller@gmx.de) */
+ lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR |
+ LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );
+#endif
+
+ if (clipping) {
+ sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);
+ /*
+ * Set "clipping" dimensions. If clipping is disabled and
+ * writes to offscreen areas of the framebuffer are performed,
+ * the "behaviour is undefined" (_very_ undefined) - Urs
+ */
+ /* btw, it requires enabling pixel pipeline in LFBMODE .
+ off screen read/writes will just wrap and read/print pixels
+ on screen. Ugly but not that dangerous */
- f_dprintk("sstfb_set_cmap\n");
- f_ddprintk("con: %d, currcon: %d, d->cmap.len %d\n",
- con, sst_info->currcon, d->cmap.len);
+ f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n",
+ info->var.xres - 1, par->yDim - 1);
- if (d->cmap.len != 16 ) { /* or test if cmap.len == 0 ? */
- int err;
- err = fb_alloc_cmap(&d->cmap, 16, 0); /* cmap size=16 */
- if (err) return err;
- }
- if (con == sst_info->currcon) {
- return fb_set_cmap(cmap, kspc, sstfb_setcolreg, info);
+ sst_write(CLIP_LEFT_RIGHT, info->var.xres );
+ sst_write(CLIP_LOWY_HIGHY, par->yDim );
+ sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE);
} else {
- fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1);
+ /* no clipping : direct access, no pipeline */
+ sst_write(LFBMODE, lfbmode );
}
- return 0;
-#undef sst_info
+ return 1;
}
-static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc,
- int con, struct fb_info *info)
+static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
{
-#define sst_info ((struct sstfb_info *) info)
- f_dprintk("sstfb_get_cmap\n");
- f_ddprintk("con %d, curcon %d, cmap.len %d\n",
- con, sst_info->currcon, fb_display[con].cmap.len);
-
- /* FIXME: check if con = -1 ? cf sstfb_set_cmap... */
- if (con == sst_info->currcon)
- return fb_get_cmap(cmap, kspc, sstfb_getcolreg, info);
- else if (fb_display[con].cmap.len)
- fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
- else
- fb_copy_cmap(
- fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- cmap, kspc ? 0 : 2);
- return 0;
-#undef sst_info
-}
+ u32 col;
-/* TODO */
-static int sstfb_pan_display(struct fb_var_screeninfo *var,
- int con, struct fb_info *info)
-{
- f_dprintk("sstfb_pan_display\n");
- return -EINVAL;
+ f_dddprintk("sstfb_setcolreg\n");
+ f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
+ regno, red, green, blue, transp);
+ if (regno >= 16) return 1;
+
+ red >>= (16 - info->var.red.length);
+ green >>= (16 - info->var.green.length);
+ blue >>= (16 - info->var.blue.length);
+ transp >>= (16 - info->var.transp.length);
+ col = (red << info->var.red.offset)
+ | (green << info->var.green.offset)
+ | (blue << info->var.blue.offset)
+ | (transp << info->var.transp.offset);
+ return 0;
}
static int sstfb_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg, int con,
- struct fb_info *info)
+ u_int cmd, u_long arg, struct fb_info *info )
{
-#define sst_info ((struct sstfb_info *) info)
-#if (SST_DEBUG_IOCTL >0)
- int i;
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct pci_dev *sst_dev = par->dev;
+ u32 fbiinit0, tmp, val;
u_long p;
- u32 tmp;
- u32 fbiinit0;
- struct pci_dev * sst_dev = sst_info->dev;
-#endif
f_dprintk("sstfb_ioctl(%x)\n", cmd);
-#if (SST_DEBUG_IOCTL >0)
switch (cmd) {
-# if (SST_DEBUG_VAR >0)
-/* tmp ioctl : dumps fb_display[0-5] */
- case _IO('F', 0xdb): /* 0x46db */
- f_dprintk("dumping fb_display[0-5].var\n");
- for (i = 0 ; i< 6 ; i++) {
- print_var(&fb_display[i].var, "var(%d)", i);
- }
- return 0;
-# endif /* (SST_DEBUG_VAR >0) */
-/* fills the lfb up to *(u32*)arg */
+
+ /* fills lfb with #arg pixels */
case _IOW('F', 0xdc, u32): /* 0x46dc */
- if (*(u32*)arg > 0x400000 )
- *(u32*) arg = 0x400000;
- f_dprintk("filling %#x \n", *(u32*)arg);
- for (p = 0 ; p < *(u32*)arg; p+=2)
- writew( p >> 6 , sst_info->video.vbase + p);
+ if (copy_from_user(&val, (void *) arg, sizeof(val)))
+ return -EFAULT;
+ if (val > info->fix.smem_len)
+ val = info->fix.smem_len;
+ f_dprintk("filling %#x \n", val);
+ for (p = 0 ; p < val; p+=2)
+ writew( p >> 6 , info->screen_base + p);
return 0;
-/* change VGA pass_through */
+
+ /* change VGA pass_through mode */
case _IOW('F', 0xdd, u32): /* 0x46dd */
+ if (copy_from_user(&val, (void *) arg, sizeof(val)))
+ return -EFAULT;
f_dprintk("switch VGA pass-through\n");
pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
tmp | PCI_EN_INIT_WR );
fbiinit0 = sst_read (FBIINIT0);
- if (* (u32*)arg) {
+ if (val) {
sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH);
- iprintk ( "Disabling VGA pass-through\n");
+ iprintk( "Disabling VGA pass-through\n");
} else {
sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH);
- iprintk ( "Enabling VGA pass-through\n");
+ iprintk( "Enabling VGA pass-through\n");
}
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
return 0;
+
+ /* draw test image */
case _IO('F', 0xde): /* 0x46de */
f_dprintk("test color display\n");
- f_ddprintk("currcon: %d, bpp %d\n", sst_info->currcon,
- sst_info->current_par.bpp);
- memset_io(sst_info->video.vbase, 0, sst_info->video.len);
- switch (sst_info->current_par.bpp) {
-/* FIXME broken : if we call this ioctl from a tty not bound to the fb, we use its depth and not the current one ... */
- case 16:
- sstfb_test16(sst_info);
+ f_ddprintk("bpp %d\n",
+ sst_info->par.bpp);
+ memset_io(info->screen_base, 0, info->fix.smem_len);
+ switch (info->var.bits_per_pixel) {
+ case 16:
+ sstfb_test16(info);
break;
-# ifdef EN_24_32_BPP
- case 24:
- case 32:
- sstfb_test32(sst_info);
+#ifdef EN_24_32_BPP
+ case 24:
+ case 32:
+ sstfb_test32(info);
break;
-# endif
- default:
- dprintk("bug line %d: bad depth '%u'\n", __LINE__,
- sst_info->current_par.bpp);
- }
- return 0;
- case _IO('F', 0xdf): /* 0x46db */
- Dump_regs;
+#endif
+ default:
+ BUG();
+ }
return 0;
}
-#endif /* (SST_DEBUG_IOCTL >0) */
return -EINVAL;
-#undef sst_info
}
-
/*
* Low level routines
*/
/* get lfb size */
-static int __devinit sst_get_memsize(struct sstfb_info *sst_info, u_long *memsize)
+static int __devinit sst_get_memsize(struct fb_info *info, u_long *memsize)
{
- u_long fbbase_virt = sst_info->video.vbase;
+ u_long fbbase_virt = (ulong) info->screen_base;
f_dprintk("sst_get_memsize\n");
/* force memsize */
@@ -1084,62 +951,20 @@ static int __devinit sst_get_memsize(struct sstfb_info *sst_info, u_long *memsiz
}
-/*
- * wait for the fbi chip. ASK: what happens if the fbi is stuck ?
- *
- * the FBI is supposed to be ready if we receive 5 time
- * in a row a "idle" answer to our requests
+/*
+ * DAC detection routines
*/
-static int __sst_wait_idle(u_long vbase)
-{
- int count = 0;
-
- f_ddprintk("sst_wait_idle\n");
- while(1) {
- if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
- f_dddprintk("status: busy\n");
-/* FIXME basicaly, this is a busy wait. maybe not that good. oh well; this is a small loop after all ...*/
- count = 0;
- } else {
- count++;
- f_dddprintk("status: idle(%d)\n", count);
- }
- if (count >= 5) return 1;
-//XXX do something to avoid hanging the machine if the voodoo is out
- }
-}
-
-/*
- * detect dac type
- * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset,
- * dram refresh disabled, FbiInit remaped.
- * TODO: mmh.. maybe i shoud put the "prerequisite" in the func ...
- */
-static int __devinit sst_detect_dactype(struct sstfb_info * sst_info)
-{
- int ret=0,i;
- f_dprintk("sst_detect_dactype\n");
- for (i=0; i< sizeof(dacs)/sizeof(dacs[0]) ; i++) {
- ret = dacs[i].detect(sst_info);
- if (ret) break;
- }
- if (!ret)
- return 0;
- f_dprintk("found %s\n", dacs[i].name);
- sst_info->dac_sw=dacs[i];
- return 1;
-}
-
/* fbi should be idle, and fifo emty and mem disabled */
/* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */
-static int __devinit sst_detect_att(struct sstfb_info * sst_info)
+static int __devinit sst_detect_att(struct fb_info *info)
{
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
int i, mir, dir;
f_dprintk("sst_detect_att\n");
- for (i = 0; i<3; i++) {
+ for (i=0; i<3; i++) {
sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* read 4 times RMR */
sst_dac_read(DACREG_RMR);
@@ -1159,8 +984,9 @@ static int __devinit sst_detect_att(struct sstfb_info * sst_info)
return 0;
}
-static int __devinit sst_detect_ti(struct sstfb_info * sst_info)
+static int __devinit sst_detect_ti(struct fb_info *info)
{
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
int i, mir, dir;
f_dprintk("sst_detect_ti\n");
@@ -1195,11 +1021,13 @@ static int __devinit sst_detect_ti(struct sstfb_info * sst_info)
* touched...
* is it realy safe ? how can i reset this ramdac ? geee...
*/
-static int __devinit sst_detect_ics(struct sstfb_info * sst_info)
+static int __devinit sst_detect_ics(struct fb_info *info)
{
- int i;
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
int m_clk0_1, m_clk0_7, m_clk1_b;
int n_clk0_1, n_clk0_7, n_clk1_b;
+ int i;
+
f_dprintk("sst_detect_ics\n");
for (i = 0; i<5; i++ ) {
sst_dac_write(DACREG_ICS_PLLRMA, 0x1); /* f1 */
@@ -1224,68 +1052,19 @@ static int __devinit sst_detect_ics(struct sstfb_info * sst_info)
return 0;
}
-/* compute the m,n,p , returns the real freq
- * (ics datasheet : N <-> N1 , P <-> N2)
- *
- * Fout= Fref * (M+2)/( 2^P * (N+2))
- * we try to get close to the asked freq
- * with P as high, and M as low as possible
- * range:
- * ti/att : 0 <= M <= 255; 0 <= P <= 3; 0<= N <= 63
- * ics : 1 <= M <= 127; 0 <= P <= 3; 1<= N <= 31
- * we'll use the lowest limitation, should be precise enouth
- */
-static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
-{
- int m, m2, n, p, best_err, fout;
- int best_n=-1;
- int best_m=-1;
-
- f_dprintk("sst_calc_pll(%dKhz)\n", freq);
- best_err = freq;
- p=3;
- /* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/
- while (((1 << p) * freq > VCO_MAX) && (p >= 0))
- p--;
- if (p == -1)
- return -EINVAL;
- for (n = 1; n < 32; n++) {
- /* calc 2 * m so we can round it later*/
- m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ;
-
- m = (m2 % 2 ) ? m2/2+1 : m2/2 ;
- if (m >= 128)
- break;
- fout = (DAC_FREF * (m + 2)) / ((1 << p) * (n + 2));
- if ((ABS(fout - freq) < best_err) && (m > 0)) {
- best_n = n;
- best_m = m;
- best_err = ABS(fout - freq);
- /* we get the lowest m , allowing 0.5% error in freq*/
- if (200*best_err < freq) break;
- }
- }
- if (best_n == -1) /* unlikely, but who knows ? */
- return -EINVAL;
- t->p=p;
- t->n=best_n;
- t->m=best_m;
- *freq_out=(DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2));
- f_ddprintk ("m: %d, n: %d, p: %d, F: %dKhz\n",
- t->m, t->n, t->p, *freq_out);
- return 0;
-}
/*
* gfx, video, pci fifo should be reset, dram refresh disabled
* see detect_dac
*/
-static int sst_set_pll_att_ti(struct sstfb_info * sst_info, const struct pll_timing *t, const int clock)
+static int sst_set_pll_att_ti(struct fb_info *info,
+ const struct pll_timing *t, const int clock)
{
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
u8 cr0, cc;
- f_dprintk("sst_set_pll_att_ti\n");
+ f_dprintk("sst_set_pll_att_ti\n");
/* enable indexed mode */
sst_dac_write(DACREG_WMA, 0); /* backdoor */
@@ -1335,8 +1114,10 @@ static int sst_set_pll_att_ti(struct sstfb_info * sst_info, const struct pll_tim
return 1;
}
-static int sst_set_pll_ics(struct sstfb_info * sst_info, const struct pll_timing *t, const int clock)
+static int sst_set_pll_ics(struct fb_info *info,
+ const struct pll_timing *t, const int clock)
{
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
u8 pll_ctrl;
f_dprintk("sst_set_pll_ics\n");
@@ -1373,178 +1154,9 @@ static int sst_set_pll_ics(struct sstfb_info * sst_info, const struct pll_timing
return 1;
}
-static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_info)
-{
- u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
- int ntiles;
- struct pci_dev * sst_dev = sst_info->dev;
-
- f_dprintk("sst_set_par(%dx%d)\n", par->xDim, par->yDim);
- f_ddprintk("hSyncOn hSyncOff vSyncOn vSyncOff\n");
- f_ddprintk("%-7d %-8d %-7d %-8d\n",
- par->hSyncOn, par->hSyncOff,
- par->vSyncOn, par->vSyncOff);
- f_ddprintk("hBackPorch vBackPorch xDim yDim Freq\n");
- f_ddprintk("%-10d %-10d %-4d %-4d %-8d\n",
- par->hBackPorch, par->vBackPorch,
- par->xDim, par->yDim, par->freq);
-
- if (!par->valid) {
- BUG();
- return -1;
- }
- sst_write(NOPCMD, 0);
- sst_wait_idle();
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
- sst_set_bits(FBIINIT1, VIDEO_RESET);
- sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
- sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
- sst_wait_idle();
-
- /*sst_unset_bits (FBIINIT0, FBI_RESET); / reenable FBI ? */
-
- sst_write(BACKPORCH, par->vBackPorch << 16 | (par->hBackPorch - 2));
- sst_write(VIDEODIMENSIONS, par->yDim << 16 | (par->xDim - 1));
- sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (par->hSyncOn - 1));
- sst_write(VSYNC, par->vSyncOff << 16 | par->vSyncOn);
-
- fbiinit2=sst_read(FBIINIT2);
- fbiinit3=sst_read(FBIINIT3);
-
- /* everything is reset. we enable fbiinit2/3 remap : dac acces ok */
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
- PCI_EN_INIT_WR | PCI_REMAP_DAC );
-
- sst_info->dac_sw.set_vidmod(sst_info, par->bpp);
-
- /* set video clock */
- sst_info->dac_sw.set_pll(sst_info, &par->pll, VID_CLOCK);
-
- /* disable fbiinit2/3 remap */
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
- PCI_EN_INIT_WR);
-
- /* restore fbiinit2/3 */
- sst_write(FBIINIT2,fbiinit2);
- sst_write(FBIINIT3,fbiinit3);
-
- fbiinit1 = (sst_read(FBIINIT1) & VIDEO_MASK)
- | EN_DATA_OE
- | EN_BLANK_OE
- | EN_HVSYNC_OE
- | EN_DCLK_OE
-/* | (15 << TILES_IN_X_SHIFT)*/
- | SEL_INPUT_VCLK_2X
-/* | (2 << VCLK_2X_SEL_DEL_SHIFT)
- | (2 << VCLK_DEL_SHIFT)*/;
-/* try with vclk_in_delay =0 (bits 29:30) , vclk_out_delay =0 (bits(27:28)
- in (near) future set them accordingly to revision + resolution (cf glide)
- first understand what it stands for :)
- FIXME: there are some artefacts... check for the vclk_in_delay
- lets try with 6ns delay in both vclk_out & in...
- doh... they're still there :\
-*/
-
- ntiles = par->tiles_in_X;
- if (IS_VOODOO2(sst_info)) {
- fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT
- | ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT ;
-/* as the only value of importance for us in fbiinit6 is tiles in X (lsb),
- and as reading fbinit 6 will return crap (see FBIINIT6_DEFAULT) we just
- write our value. BTW due to the dac unable to read odd number of tiles, this
- field is always null ... */
- fbiinit6 = (ntiles & 0x1) << TILES_IN_X_LSB_SHIFT;
- }
- else
- fbiinit1 |= ntiles << TILES_IN_X_SHIFT;
-
- switch(par->bpp) {
- case 16:
- fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL;
- break;
-#ifdef EN_24_32_BPP
- case 24:
- case 32:
-/* orig sst_set_bits(FBIINIT1, SEL_SOURCE_VCLK_2X_DIV2 | EN_24BPP); */
- fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL | EN_24BPP;
- break;
-#endif
- default:
- dprintk("bug line %d: bad depth '%u'\n", __LINE__,
- par->bpp );
- return 0;
- break;
- }
- sst_write(FBIINIT1, fbiinit1);
- if (IS_VOODOO2(sst_info)) {
- sst_write(FBIINIT6, fbiinit6);
- fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;
- if (par->vmode & FB_VMODE_INTERLACED)
- fbiinit5 |= INTERLACE;
- if (par->vmode & FB_VMODE_DOUBLE )
- fbiinit5 |= VDOUBLESCAN;
- if (par->sync & FB_SYNC_HOR_HIGH_ACT)
- fbiinit5 |= HSYNC_HIGH;
- if (par->sync & FB_SYNC_VERT_HIGH_ACT)
- fbiinit5 |= VSYNC_HIGH;
- sst_write(FBIINIT5, fbiinit5);
- }
- sst_wait_idle();
- sst_unset_bits(FBIINIT1, VIDEO_RESET);
- sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
- sst_set_bits(FBIINIT2, EN_DRAM_REFRESH);
-/* disables fbiinit writes */
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
-
- /* set lfbmode : set mode + front buffer for reads/writes
- + disable pipeline + disable byte swapping */
- switch(par->bpp) {
- case 16:
- lfbmode = LFB_565;
- break;
-#ifdef EN_24_32_BPP
- case 24:
- lfbmode = LFB_888;
- break;
- case 32:
- lfbmode = LFB_8888;
- break;
-#endif
- default:
- dprintk("bug line %d: bad depth '%u'\n", __LINE__,
- par->bpp );
- return 0;
- break;
- }
-
- if (clipping) {
- sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);
- /*
- * Set "clipping" dimensions. If clipping is disabled and
- * writes to offscreen areas of the framebuffer are performed,
- * the "behaviour is undefined" (_very_ undefined) - Urs
- */
- /* btw, it requires enabling pixel pipeline in LFBMODE .
- off screen read/writes will just wrap and read/print pixels
- on screen. Ugly but not that dangerous */
-
- f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n",
- par->xDim-1, par->yDim-1);
-
- sst_write(CLIP_LEFT_RIGHT, par->xDim );
- sst_write(CLIP_LOWY_HIGHY, par->yDim );
- sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE);
- } else {
- /* no clipping : direct access, no pipeline */
- sst_write(LFBMODE, lfbmode );
- }
-
- sst_info->current_par = *par ;
- return 1;
-}
-
-static void sst_set_vidmod_att_ti(struct sstfb_info * sst_info, const int bpp)
+static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
{
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
u8 cr0;
f_dprintk("sst_set_vidmod_att_ti(bpp: %d)\n", bpp);
@@ -1579,8 +1191,10 @@ static void sst_set_vidmod_att_ti(struct sstfb_info * sst_info, const int bpp)
}
}
-static void sst_set_vidmod_ics(struct sstfb_info * sst_info, const int bpp)
+static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
{
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
+
f_dprintk("sst_set_vidmod_ics(bpp: %d)\n", bpp);
switch(bpp) {
case 16:
@@ -1598,18 +1212,58 @@ static void sst_set_vidmod_ics(struct sstfb_info * sst_info, const int bpp)
}
}
-static int __devinit sst_init(struct sstfb_info *sst_info)
+/*
+ * detect dac type
+ * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset,
+ * dram refresh disabled, FbiInit remaped.
+ * TODO: mmh.. maybe i shoud put the "prerequisite" in the func ...
+ */
+
+
+static struct dac_switch dacs[] __devinitdata = {
+ { .name = "TI TVP3409",
+ .detect = sst_detect_ti,
+ .set_pll = sst_set_pll_att_ti,
+ .set_vidmod = sst_set_vidmod_att_ti },
+
+ { .name = "AT&T ATT20C409",
+ .detect = sst_detect_att,
+ .set_pll = sst_set_pll_att_ti,
+ .set_vidmod = sst_set_vidmod_att_ti },
+ { .name = "ICS ICS5342",
+ .detect = sst_detect_ics,
+ .set_pll = sst_set_pll_ics,
+ .set_vidmod = sst_set_vidmod_ics },
+};
+
+static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
+{
+ int ret = 0,i;
+
+ f_dprintk("sst_detect_dactype\n");
+ for (i=0; i<sizeof(dacs)/sizeof(dacs[0]); i++) {
+ ret = dacs[i].detect(info);
+ if (ret) break;
+ }
+ if (!ret)
+ return 0;
+ f_dprintk("found %s\n", dacs[i].name);
+ par->dac_sw = dacs[i];
+ return 1;
+}
+
+/*
+ * Internal Routines
+ */
+static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
{
+ u32 fbiinit0, fbiinit1, fbiinit4;
+ struct pci_dev *dev = par->dev;
struct pll_timing gfx_timings;
struct sst_spec * spec;
- struct pci_dev * sst_dev = sst_info->dev;
int Fout;
- u32 fbiinit0, fbiinit1, fbiinit4;
- dprintk("sst_init\n"); //XXX
- Dump_regs; //XXX
-
- spec = &voodoo_spec[sst_info->type];
+ spec = &voodoo_spec[par->type];
f_dprintk("sst_init\n");
f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 "
" fbiinit6\n");
@@ -1617,10 +1271,10 @@ static int __devinit sst_init(struct sstfb_info *sst_info)
sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2),
sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6));
/* disable video clock */
- pci_write_config_dword(sst_dev, PCI_VCLK_DISABLE,0);
+ pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
/* enable writing to init registers ,disable pci fifo*/
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
+ pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
/* reset video */
sst_set_bits(FBIINIT1, VIDEO_RESET);
sst_wait_idle();
@@ -1639,29 +1293,29 @@ static int __devinit sst_init(struct sstfb_info *sst_info)
sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
sst_wait_idle();
/* remap fbinit2/3 to dac */
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+ pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR | PCI_REMAP_DAC );
/* detect dac type */
- if (!sst_detect_dactype(sst_info)) {
+ if (!sst_detect_dactype(info, par)) {
eprintk("Unknown dac type\n");
- //FIXME watch it : we are not in a safe state , bad bad bad .
+ //FIXME watch it : we are not in a safe state, bad bad bad .
return 0;
}
/* set graphic clock */
- sst_info->gfx_clock = spec->default_gfx_clock;
+ par->gfx_clock = spec->default_gfx_clock;
if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
- iprintk ("Using supplied graphic freq : %dMHz\n", gfxclk);
- sst_info->gfx_clock = gfxclk *1000;
+ iprintk("Using supplied graphic freq : %dMHz\n", gfxclk);
+ par->gfx_clock = gfxclk *1000;
} else if (gfxclk) {
wprintk ("You fool, %dMhz is way out of spec! Using default\n", gfxclk);
}
- sst_calc_pll(sst_info->gfx_clock, &Fout, &gfx_timings);
- sst_info->dac_sw.set_pll(sst_info, &gfx_timings, GFX_CLOCK);
+ sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings);
+ par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
/* disable fbiinit remap */
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+ pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR| PCI_EN_FIFO_WR );
/* defaults init registers */
/* FbiInit0: unreset gfx, unreset fifo */
@@ -1689,42 +1343,42 @@ static int __devinit sst_init(struct sstfb_info *sst_info)
sst_wait_idle();
sst_write(FBIINIT4, fbiinit4);
sst_wait_idle();
- if (IS_VOODOO2(sst_info)) {
+ if (IS_VOODOO2(par)) {
sst_write(FBIINIT6, FBIINIT6_DEFAULT);
sst_wait_idle();
}
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR );
- pci_write_config_dword(sst_dev, PCI_VCLK_ENABLE, 0);
-
+ pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR );
+ pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0);
return 1;
}
-static void __devexit sst_shutdown(struct sstfb_info *sst_info)
+static void __devexit sst_shutdown(struct fb_info *info)
{
- struct pci_dev * sst_dev = sst_info->dev;
+ struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct pci_dev *dev = par->dev;
struct pll_timing gfx_timings;
int Fout;
f_dprintk("sst_shutdown\n");
/* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
+ pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING);
sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
sst_wait_idle();
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+ pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR | PCI_REMAP_DAC );
/*set 20Mhz gfx clock */
sst_calc_pll(20000, &Fout, &gfx_timings);
- sst_info->dac_sw.set_pll(sst_info, &gfx_timings, GFX_CLOCK);
+ par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
/* TODO maybe shutdown the dac, vrefresh and so on... */
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+ pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR);
sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH);
- pci_write_config_dword(sst_dev, PCI_VCLK_DISABLE,0);
+ pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct at the beginining ? */
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, 0);
+ pci_write_config_dword(dev, PCI_INIT_ENABLE, 0);
}
@@ -1769,35 +1423,30 @@ int __init sstfb_setup(char *options)
else if (!strncmp(this_opt, "dev:",4))
dev=simple_strtoul (this_opt+4, NULL, 0);
else
- mode_option=this_opt;
+ mode_option = this_opt;
}
return 0;
}
-int __devinit sstfb_init(void)
-{
- f_dprintk("sstfb_init\n");
- dprintk("Compile date: "__DATE__" "__TIME__"\n");
- return pci_module_init(&sstfb_driver);
-}
-
-void __devexit sstfb_exit(void)
-{
- f_dprintk("sstfb_exit\n");
- pci_unregister_driver(&sstfb_driver);
-}
-
-#ifdef MODULE
-module_init(sstfb_init);
-module_exit(sstfb_exit);
-#endif
+static struct fb_ops sstfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = sstfb_check_var,
+ .fb_set_par = sstfb_set_par,
+ .fb_setcolreg = sstfb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
+ .fb_ioctl = sstfb_ioctl,
+};
static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct fb_var_screeninfo var;
- struct sstfb_info * sst_info;
- struct sst_spec * spec;
- int tmp,err;
+ struct sstfb_par *default_par;
+ struct fb_fix_screeninfo *fix;
+ struct sst_spec *spec;
+ struct fb_info *info;
+ int err;
f_dprintk("sstfb_probe\n");
/* dev > 0 the device is not the one asked for. skip */
@@ -1805,268 +1454,269 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i
/* dev == -1 we already inited the asked device. skip */
/* dev < -1 init all devices. including this one. init */
if ((dev == -1 ) || (dev-- > 0))
- return -1;
+ return -ENODEV;
if ((err=pci_enable_device(pdev))) {
eprintk("cannot enable device\n");
return err;
}
- sst_info = (struct sstfb_info*)kmalloc(sizeof(*sst_info), GFP_KERNEL);
- if (!sst_info)
- goto fail_kmalloc;
- pci_set_drvdata(pdev, sst_info);
- sst_info->type = id->driver_data;
- spec = &voodoo_spec[sst_info->type];
+ info = kmalloc(sizeof(struct fb_info) + sizeof(struct sstfb_par), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ default_par = (struct sstfb_par *) (info + 1);
+ fix = &info->fix;
+ info->par = default_par;
+
+ pci_set_drvdata(pdev, info);
+ default_par->type = id->driver_data;
+ spec = &voodoo_spec[default_par->type];
f_ddprintk("found device : %s\n", spec->name);
- sst_info->dev = pdev;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &sst_info->revision);
+ default_par->dev = pdev;
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &default_par->revision);
- sst_info->mmio.base = pci_resource_start(pdev,0);
- sst_info->video.base = sst_info->mmio.base+0x400000;
+ fix->mmio_start = pci_resource_start(pdev,0);
+ fix->smem_start = fix->mmio_start + 0x400000;
- if (!request_mem_region(sst_info->mmio.base,0x400000,"sstfb MMIO")) {
- eprintk ("cannot reserve mmio memory\n");
+ if (!request_mem_region(fix->mmio_start, 0x400000,"sstfb MMIO")) {
+ eprintk("cannot reserve mmio memory\n");
goto fail_mmio_mem;
}
- if (!request_mem_region(sst_info->video.base,0x400000,"sstfb FB")) {
- eprintk ("cannot reserve fb memory\n");
+ if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) {
+ eprintk("cannot reserve fb memory\n");
goto fail_fb_mem;
}
- sst_info->mmio.vbase = (u_long) ioremap_nocache(sst_info->mmio.base, 0x400000);
- if (!sst_info->mmio.vbase) {
+ default_par->mmio_vbase = (u_long) ioremap_nocache(fix->mmio_start, 0x400000);
+ if (!default_par->mmio_vbase) {
eprintk("cannot remap register area %#lx\n",
- sst_info->mmio.base);
+ fix->mmio_start);
goto fail_mmio_remap;
}
- sst_info->video.vbase = (u_long) ioremap_nocache(sst_info->video.base, 0x400000);
- if (!sst_info->video.vbase) {
+ info->screen_base = ioremap_nocache(fix->smem_start, 0x400000);
+ if (!info->screen_base) {
eprintk("cannot remap framebuffer %#lx\n",
- sst_info->video.base);
+ fix->smem_start);
goto fail_fb_remap;
}
- if(!sst_init(sst_info)) {
+ if(!sst_init(info, default_par)) {
eprintk("Init failed\n");
goto fail;
}
- sst_get_memsize(sst_info, &sst_info->video.len);
- strncpy(sst_info->info.modename, spec->name, 16);
+ sst_get_memsize(info, (unsigned long *) &fix->smem_len);
+ strncpy(fix->id, spec->name, sizeof(fix->id));
- iprintk("%s with %s dac\n", sst_info->info.modename, sst_info->dac_sw.name);
+ iprintk("%s with %s dac\n", fix->id, default_par->dac_sw.name);
iprintk("framebuffer at %#lx, mapped to %#lx,"
- " size %ldMb\n",
- sst_info->video.base, sst_info->video.vbase,
- sst_info->video.len >> 20);
-
- f_ddprintk("revision: %d\n", sst_info->revision);
- f_ddprintk("regbase_virt: %#lx\n", sst_info->mmio.vbase);
- f_ddprintk("membase_phys: %#lx\n", sst_info->video.base);
- f_ddprintk("fbbase_virt: %#lx\n", sst_info->video.vbase);
-
- sst_info->info.node = -1 ;
- sst_info->info.flags = FBINFO_FLAG_DEFAULT;
- sst_info->info.fbops = &sstfb_ops;
- sst_info->info.disp = &sst_info->disp;
- sst_info->info.changevar = NULL;
- sst_info->info.switch_con = &sstfbcon_switch;
- sst_info->info.updatevar = &sstfbcon_updatevar;
- sst_info->info.blank = &sstfbcon_blank;
-
- tmp=0;
- var = sstfb_default;
- if ( mode_option &&
- fb_find_mode(&var, &sst_info->info, mode_option,
- NULL, 0, NULL, 16)) {
- if (sstfb_set_var(&var, -1, &sst_info->info)) {
- eprintk("can't set supplied video mode. Using default\n");
- var = sstfb_default;
- } else {
- /* set the new default */
- sstfb_default = var;
- tmp=1; /* no need to set the mode. */
- }
- }
-
- if (!tmp && sstfb_set_var(&var, -1, &sst_info->info)) {
+ " size %dMb\n",
+ fix->smem_start, (unsigned long) info->screen_base,
+ fix->smem_len >> 20);
+
+ f_ddprintk("revision: %d\n", default_par->revision);
+ f_ddprintk("regbase_virt: %#lx\n", default_par->mmio_vbase);
+ f_ddprintk("membase_phys: %#lx\n", fix->smem_start);
+ f_ddprintk("fbbase_virt: %#lx\n", info->screen_base);
+
+ info->node = NODEV;
+ info->flags = FBINFO_FLAG_DEFAULT;
+ info->fbops = &sstfb_ops;
+
+ fix->mmio_len = 0x400000;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->accel = FB_ACCEL_NONE; /* FIXME */
+ /*
+ * According to the specs, the linelength must be of 1024 *pixels*.
+ * and the 24bpp mode is in fact a 32 bpp mode.
+ */
+ fix->line_length= 2048; /* default value, for 24 or 32bit: 4096*/
+
+ if ( mode_option &&
+ fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16)) {
+ eprintk("can't set supplied video mode. Using default\n");
+ info->var = sstfb_default;
+ } else
+ info->var = sstfb_default;
+
+ if (sstfb_check_var(&info->var, info)) {
eprintk("can't set default video mode.\n");
goto fail;
}
- /*clear fb */
- memset_io(sst_info->video.vbase, 0, sst_info->video.len);
- /* print some squares ... */
- sstfb_test16(sst_info); /* FIXME this is only for 16bpp */
+
+ fb_alloc_cmap(&info->cmap, 16, 0);
/* register fb */
- if (register_framebuffer(&sst_info->info) < 0) {
+ if (register_framebuffer(info) < 0) {
eprintk("can't register framebuffer.\n");
goto fail;
}
printk(KERN_INFO "fb%d: %s frame buffer device\n",
- minor(sst_info->info.node),sst_info->info.modename);
+ minor(info->node), fix->id);
+
return 0;
fail:
- iounmap((void *)sst_info->video.base);
+ iounmap(info->screen_base);
fail_fb_remap:
- iounmap((void *)sst_info->mmio.base);
+ iounmap((void *)default_par->mmio_vbase);
fail_mmio_remap:
- release_mem_region(sst_info->video.base,0x400000);
+ release_mem_region(fix->smem_start, 0x400000);
fail_fb_mem:
- release_mem_region(sst_info->mmio.base,0x400000);
+ release_mem_region(fix->mmio_start, 0x400000);
fail_mmio_mem:
- kfree(sst_info);
-fail_kmalloc:
+ kfree(info);
return -ENXIO; /* no voodoo detected */
}
static void __devexit sstfb_remove(struct pci_dev *pdev)
{
- struct sstfb_info * sst_info;
+ struct sstfb_par *par;
+ struct fb_info *info;
f_dprintk("sstfb_remove\n");
- sst_info=pci_get_drvdata(pdev);
- sst_shutdown(sst_info);
-
- unregister_framebuffer(&sst_info->info);
- iounmap((void*)sst_info->video.vbase);
- iounmap((void*)sst_info->mmio.vbase);
- release_mem_region(sst_info->video.base,0x400000);
- release_mem_region(sst_info->mmio.base,0x400000);
- kfree(sst_info);
+ info = pci_get_drvdata(pdev);
+ par = (struct sstfb_par *) info->par;
+
+ sst_shutdown(info);
+ unregister_framebuffer(info);
+ iounmap(info->screen_base);
+ iounmap((void*)par->mmio_vbase);
+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+ kfree(info);
}
-/*
- * console driver
- */
-static int sstfbcon_switch(int con, struct fb_info *info)
-{
-#define sst_info ((struct sstfb_info *) info)
- struct sstfb_par par;
-
- f_dprintk("sstfbcon_switch(con: %d)\n",con);
- f_ddprintk("currcon: %d\n", sst_info->currcon);
- v_dprintk("currcon: %d\n", sst_info->currcon);
+static struct pci_device_id sstfb_id_tbl[] __devinitdata = {
+ { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 },
+ { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 },
+ { 0 },
+};
- if (sst_info->currcon >= 0) {
- if (fb_display[sst_info->currcon].cmap.len)
- fb_get_cmap(&fb_display[sst_info->currcon].cmap, 1,
- sstfb_getcolreg, info);
- }
- sst_info->currcon = con;
- fb_display[con].var.activate = FB_ACTIVATE_NOW;
+static struct pci_driver sstfb_driver = {
+ .name = "sstfb",
+ .id_table = sstfb_id_tbl,
+ .probe = sstfb_probe,
+ .remove = __devexit_p(sstfb_remove),
+};
- print_var(&fb_display[con].var, "&fb_display[con: %d].var",con);
- sstfb_decode_var(&fb_display[con].var, &par, sst_info);
- if (memcmp(&par,&(sst_info->current_par),sizeof(par))) {
- sstfb_set_par(&par, sst_info);
- }
- sstfb_install_cmap(con, info);
- return 0;
-#undef sst_info
-}
-static int sstfbcon_updatevar(int con, struct fb_info *info)
+int __devinit sstfb_init(void)
{
- f_dprintk("sstfbcon_updatevar\n");
- return -EINVAL;
+ f_dprintk("sstfb_init\n");
+ dprintk("Compile date: "__DATE__" "__TIME__"\n");
+ return pci_module_init(&sstfb_driver);
}
-static void sstfbcon_blank(int blank, struct fb_info *info)
+void __devexit sstfb_exit(void)
{
- f_dprintk("sstfbcon_blank(level %d)\n", blank);
+ f_dprintk("sstfb_exit\n");
+ pci_unregister_driver(&sstfb_driver);
}
+/*
+ * console driver
+ */
+
+#if 1
/* print some squares on the fb (presuming 16bpp) */
-static void sstfb_test16(struct sstfb_info *sst_info)
+static void sstfb_test16(struct fb_info *info)
{
- int i,j;
+ u_long fbbase_virt = (u_long) info->screen_base;
u_long p;
- u_long fbbase_virt = sst_info->video.vbase;
+ int i,j;
f_dprintk("sstfb_test16\n");
- /* rect blanc 20x100+200+0 */
- for (i=0 ; i< 100; i++) {
- p = fbbase_virt + 2048 *i+400;
- for (j=0 ; j < 10 ; j++) {
- writel( 0xffffffff, p);
- p+=4;
+ /* draw white rect 20x100+200+0 */
+ for (i=0 ; i<100; i++) {
+ p = fbbase_virt + 2048*i+400;
+ for (j=0 ; j<10 ; j++) {
+ writel(0xffffffff, p);
+ p += 4;
}
}
- /* rect bleu 180x200+0+0 */
- for (i=0 ; i< 200; i++) {
- p = fbbase_virt + 2048 *i;
- for (j=0 ; j < 90 ; j++) {
- writel(0x001f001f,p);
- p+=4;
+ /* draw blue rect 180x200+0+0 */
+ for (i=0 ; i<200; i++) {
+ p = fbbase_virt + 2048*i;
+ for (j=0 ; j<90 ; j++) {
+ writel(0x001f001f, p);
+ p += 4;
}
}
- /* carre vert 40x40+100+0 */
- for (i=0 ; i< 40 ; i++) {
- p = fbbase_virt + 2048 *i + 200;
+ /* draw green rect 40x40+100+0 */
+ for (i=0 ; i<40 ; i++) {
+ p = fbbase_virt + 2048*i + 200;
for (j=0; j <20;j++) {
writel(0x07e007e0, p);
- p+=4;
+ p += 4;
}
}
- /*carre rouge 40x40+100+40 */
+ /* draw red rect 40x40+100+40 */
for (i=0; i<40; i++) {
p = fbbase_virt + 2048 * (i+40) + 200;
- for (j=0; j <20;j++) {
- writel( 0xf800f800, p);
- p+=4;
+ for (j=0; j<20;j++) {
+ writel(0xf800f800, p);
+ p += 4;
}
}
}
+#endif
-/* print some squares on the fb (24/32bpp) */
#ifdef EN_24_32_BPP
-static void sstfb_test32(struct sstfb_info *sst_info)
+/* print some squares on the fb (24/32bpp) */
+static void sstfb_test32(struct fb_info *info)
{
int i,j;
u_long p;
- u_long fbbase_virt = sst_info->video.vbase;
+ u_long fbbase_virt = info->screen_base;
f_dprintk("sstfb_test32\n");
- /* rect blanc 20x100+200+0 */
- for (i=0 ; i< 100; i++) {
+ /* draw white rect 20x100+200+0 */
+ for (i=0 ; i<100; i++) {
p = fbbase_virt + 4096*i + 800;
- for (j=0 ; j < 20 ; j++) {
- writel( 0x00ffffff, p);
- p+=4;
+ for (j=0 ; j<20; j++) {
+ writel(0x00ffffff, p);
+ p += 4;
}
}
- /* rect bleu 180x200+0+0 */
- for (i=0 ; i< 200; i++) {
- p = fbbase_virt + 4096 * i;
- for (j=0 ; j < 180 ; j++) {
+ /* draw blue rect 180x200+0+0 */
+ for (i=0 ; i<200; i++) {
+ p = fbbase_virt + 4096*i;
+ for (j=0 ; j<180; j++) {
writel(0x000000ff,p);
- p+=4;
+ p += 4;
}
}
- /* carre vert 40x40+100+0 */
- for (i=0 ; i< 40 ; i++) {
- p = fbbase_virt + 4096 *i + 400;
- for (j=0; j <40;j++) {
+ /* draw green rect 40x40+100+0 */
+ for (i=0 ; i<40 ; i++) {
+ p = fbbase_virt + 4096*i + 400;
+ for (j=0; j<40; j++) {
writel(0x0000ff00, p);
- p+=4;
+ p += 4;
}
}
- /*carre rouge 40x40+100+10 */
+ /* draw red rect 40x40+100+10 */
for (i=0; i<40; i++) {
p = fbbase_virt + 4096 * (i+40) + 400;
- for (j=0; j <40;j++) {
- writel( 0x00ff0000, p);
- p+=4;
+ for (j=0; j<40; j++) {
+ writel(0x00ff0000, p);
+ p += 4;
}
}
}
-#endif /* EN_24_32_BPP */
+#endif
+
+
+#ifdef MODULE
+module_init(sstfb_init);
+module_exit(sstfb_exit);
+#endif
MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
@@ -2087,57 +1737,3 @@ MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
MODULE_PARM(dev,"i");
MODULE_PARM_DESC(dev , "Attach to device ID (0..n) (default=1st device)");
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
-#if 1
-void __Dump_regs (struct sstfb_info * sst_info)
-{
- struct { u32 reg ; char * reg_name;} pci_regs [] = {
- { PCI_INIT_ENABLE, "initenable"},
- { PCI_VCLK_ENABLE, "enable vclk"},
- { PCI_VCLK_DISABLE, "disable vclk"},
- };
-
- struct { u32 reg ; char * reg_name;} sst_regs [] = {
- {FBIINIT0,"fbiinit0"},
- {FBIINIT1,"fbiinit1"},
- {FBIINIT2,"fbiinit2"},
- {FBIINIT3,"fbiinit3"},
- {FBIINIT4,"fbiinit4"},
- {FBIINIT5,"fbiinit5"},
- {FBIINIT6,"fbiinit6"},
- {FBIINIT7,"fbiinit7"},
- {LFBMODE,"lfbmode"},
- {FBZMODE,"fbzmode"},
- };
- int pci_s = sizeof(pci_regs)/sizeof(*pci_regs);
- int sst_s = sizeof(sst_regs)/sizeof(*sst_regs);
- u32 pci_res[pci_s];
- u32 sst_res[sst_s];
-
- struct pci_dev * dev = sst_info->dev;
-
- int i;
-
- for (i=0; i < pci_s ; i++ ) {
- pci_read_config_dword ( dev, pci_regs[i].reg , &pci_res[i]) ;
- }
- for (i=0; i < sst_s ; i++ ) {
- sst_res[i]=sst_read(sst_regs[i].reg);
- }
-
- dprintk ("Dump regs\n");
- for (i=0; i < pci_s ; i++ ) {
- dprintk("%s = %0#10x\n", pci_regs[i].reg_name , pci_res[i]) ;
- }
- for (i=0; i < sst_s ; i++ ) {
- dprintk("%s = %0#10x\n", sst_regs[i].reg_name , sst_res[i]) ;
- }
-}
-#endif
diff --git a/drivers/video/sstfb.h b/drivers/video/sstfb.h
index f12d53177ab6..de66a85f6220 100644
--- a/drivers/video/sstfb.h
+++ b/drivers/video/sstfb.h
@@ -4,8 +4,6 @@
* Copyright (c) 2000,2001 Ghozlane Toumi <gtoumi@messel.emse.fr>
*
* Created 28 Aug 2001 by Ghozlane Toumi
- *
- * $Id: sstfb.h,v 1.8 2002/05/10 19:35:11 ghoz Exp $
*/
@@ -25,7 +23,6 @@
# undef SST_DEBUG_REG
# undef SST_DEBUG_FUNC
# undef SST_DEBUG_VAR
-# undef SST_DEBUG_IOCTL
#endif
#if (SST_DEBUG_REG > 0)
@@ -73,8 +70,6 @@
#define wprintk(X...) printk(KERN_WARNING "sstfb: " X)
#define BIT(x) (1ul<<(x))
-#define PS2KHZ(a) (1000000000UL/(a)) /* picoseconds to KHz */
-#define KHZ2PS(a) (1000000000UL/(a))
#define POW2(x) (1ul<<(x))
#ifndef ABS
@@ -114,7 +109,11 @@
# define RD_BUFF_FRONT 0 /* read buff select (front) */
# define RD_BUFF_BACK (1 << 6) /* back */
# define EN_PXL_PIPELINE BIT(8) /* pixel pipeline (clip..)*/
+# define LFB_WORD_SWIZZLE_WR BIT(11) /* enable write-wordswap (big-endian) */
+# define LFB_BYTE_SWIZZLE_WR BIT(12) /* enable write-byteswap (big-endian) */
# define LFB_INVERT_Y BIT(13) /* invert Y origin (LFB) */
+# define LFB_WORD_SWIZZLE_RD BIT(15) /* enable read-wordswap (big-endian) */
+# define LFB_BYTE_SWIZZLE_RD BIT(16) /* enable read-byteswap (big-endian) */
#define CLIP_LEFT_RIGHT 0x0118
#define CLIP_LOWY_HIGHY 0x011c
#define NOPCMD 0x0120
@@ -305,9 +304,9 @@ struct sstfb_info;
struct dac_switch {
char * name;
- int (*detect) (struct sstfb_info *sst_info);
- int (*set_pll) (struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);
- void (*set_vidmod) (struct sstfb_info *sst_info, const int bpp);
+ int (*detect) (struct fb_info *info);
+ int (*set_pll) (struct fb_info *info, const struct pll_timing *t, const int clock);
+ void (*set_vidmod) (struct fb_info *info, const int bpp);
};
struct sst_spec {
@@ -317,66 +316,21 @@ struct sst_spec {
};
struct sstfb_par {
- unsigned int bpp;
- unsigned int xDim; /* xres */
+ unsigned int yDim;
unsigned int hSyncOn; /* hsync_len */
unsigned int hSyncOff; /* left_margin + xres + right_margin */
unsigned int hBackPorch;/* left_margin */
- unsigned int yDim;
unsigned int vSyncOn;
unsigned int vSyncOff;
unsigned int vBackPorch;
- unsigned int freq; /* freq in kHz */
struct pll_timing pll;
unsigned int tiles_in_X;/* num of tiles in X res */
- unsigned int vmode; /* doublescan/interlaced */
- unsigned int sync; /* H/V sync polarity */
- unsigned int valid; /* par is correct (fool proof) */
-};
-
-struct sstfb_info {
- struct fb_info info;
- struct sstfb_par current_par;
- struct pci_dev * dev;
-
- struct {
- unsigned long base; /* physical */
- unsigned long vbase; /* virtual (CPU view) */
- unsigned long len;
- } video; /* fb memory info */
- struct {
- unsigned long base;
- unsigned long vbase;
- } mmio; /* registers memory info */
-
+ unsigned long mmio_vbase;
struct dac_switch dac_sw; /* dac specific functions */
-
+ struct pci_dev *dev;
int type;
u8 revision;
-
- /* status */
-/*XXX int configured;
- int indexed_mode;
- int vgapass;
- int clipping; */
- int gfx_clock;
-
- int currcon;
- struct display disp; /* current display */
- struct { u_int red, green, blue, transp; } palette[16];
-
- union {
-#ifdef FBCON_HAS_CFB16
- u16 cfb16[16];
-#endif
-#ifdef EN_24_32_BPP
-#if defined (FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
- u32 cfb32[16];
-#endif
-#endif
- } fbcon_cmap;
-
+ int gfx_clock; /* status */
};
-
#endif /* _SSTFB_H_ */
diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h
index 7e7e1546f6e7..d222f78cd9b4 100644
--- a/drivers/video/sticore.h
+++ b/drivers/video/sticore.h
@@ -83,8 +83,6 @@ extern struct sti_struct *sti_init_roms(void);
there's no other way for stifb to find it. */
extern struct sti_struct *default_sti;
-extern struct display_switch fbcon_sti; /* fbcon-sti.c */
-
int sti_init_graph(struct sti_struct *sti);
void sti_inq_conf(struct sti_struct *sti);
void sti_putc(struct sti_struct *sti, int c, int y, int x);
@@ -378,6 +376,9 @@ struct sti_struct {
/* PCI data structures (pg. 17ff from sti.pdf) */
struct pci_dev *pd;
u8 rm_entry[16]; /* pci region mapper array == pci config space offset */
+
+ /* pointer to the fb_info where this STI device is used */
+ struct fb_info *info;
};
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 27bf51f207bd..d64419f7fe4b 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -1,7 +1,7 @@
/*
- * linux/drivers/video/sti/stifb.c -
- * Frame buffer driver for HP workstations with STI (standard text interface)
- * video firmware.
+ * linux/drivers/video/stifb.c -
+ * Low level Frame buffer driver for HP workstations with
+ * STI (standard text interface) video firmware.
*
* Copyright (C) 2001-2002 Helge Deller <deller@gmx.de>
* Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
@@ -40,10 +40,9 @@
/* TODO:
* - remove the static fb_info to support multiple cards
- * - remove the completely untested 1bpp mode
+ * - 1bpp mode is completely untested
* - add support for h/w acceleration
* - add hardware cursor
- * -
*/
@@ -59,30 +58,23 @@
#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>
#include <linux/init.h>
-#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/pci.h>
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb32.h>
-
#include <asm/grfioctl.h> /* for HP-UX compatibility */
#include "sticore.h"
+/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
#ifdef __LP64__
-/* return virtual address */
-#define REGION_BASE(fb_info, index) \
+ #define REGION_BASE(fb_info, index) \
(fb_info->sti->glob_cfg->region_ptrs[index] | 0xffffffff00000000)
#else
-/* return virtual address */
-#define REGION_BASE(fb_info, index) \
+ #define REGION_BASE(fb_info, index) \
fb_info->sti->glob_cfg->region_ptrs[index]
#endif
@@ -117,7 +109,6 @@ struct stifb_info {
ngle_rom_t ngle_rom;
struct sti_struct *sti;
int deviceSpecificConfig;
- struct display disp;
};
static int stifb_force_bpp[MAX_STI_ROMS] = {0, };
@@ -901,7 +892,11 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
if (regno >= 256) /* no. of hw registers */
return 1;
-
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
START_IMAGE_COLORMAP_ACCESS(fb);
if (fb->info.var.grayscale) {
@@ -936,53 +931,6 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
return 0;
}
-#if 0
-static void
-stifb_loadcmap(struct stifb_info *fb)
-{
- u32 color;
- int i;
-
- if (!fb->cmap_reload)
- return;
-
- START_IMAGE_COLORMAP_ACCESS(fb);
- for (i = 0; i < 256; i++) {
- if (fb->info.var.bits_per_pixel > 8) {
- color = (i << 16) | (i << 8) | i;
- } else {
- if (fb->info.var.grayscale) {
- /* gray = 0.30*R + 0.59*G + 0.11*B */
- color = ((fb->palette[i].red * 77) +
- (fb->palette[i].green * 151) +
- (fb->palette[i].blue * 28)) >> 8;
- } else {
- color = ((fb->palette[i].red << 16) |
- (fb->palette[i].green << 8) |
- (fb->palette[i].blue));
- }
- }
- WRITE_IMAGE_COLOR(fb, i, color);
- }
- if (fb->id == S9000_ID_HCRX) {
- NgleLutBltCtl lutBltCtl;
-
- lutBltCtl = setHyperLutBltCtl(fb,
- 0, /* Offset w/i LUT */
- 256); /* Load entire LUT */
- NGLE_BINC_SET_SRCADDR(fb,
- NGLE_LONG_FB_ADDRESS(0, 0x100, 0));
- /* 0x100 is same as used in WRITE_IMAGE_COLOR() */
- START_COLORMAPLOAD(fb, lutBltCtl.all);
- SETUP_FB(fb);
- } else {
- /* cleanup colormap hardware */
- FINISH_IMAGE_COLORMAP_ACCESS(fb);
- }
- fb->cmap_reload = 0;
-}
-#endif
-
static int
stifb_blank(int blank_mode, struct fb_info *info)
{
@@ -1075,32 +1023,24 @@ stifb_init_display(struct stifb_info *fb)
static struct fb_ops stifb_ops = {
.owner = THIS_MODULE,
- .fb_set_var = gen_set_var,
- .fb_get_cmap = gen_get_cmap,
- .fb_set_cmap = gen_set_cmap,
.fb_setcolreg = stifb_setcolreg,
- /* .fb_pan_display = stifb_pan_display, */
.fb_blank = stifb_blank,
-
- /*
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- */
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
};
- /*
- * Initialization
- */
+/*
+ * Initialization
+ */
int __init
stifb_init_fb(struct sti_struct *sti, int force_bpp)
{
struct fb_fix_screeninfo *fix;
struct fb_var_screeninfo *var;
- struct display *disp;
- struct display_switch *dispsw;
struct stifb_info *fb;
struct fb_info *info;
unsigned long sti_rom_address;
@@ -1119,8 +1059,6 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
memset(fb, 0, sizeof(*fb));
fix = &info->fix;
var = &info->var;
- disp = &fb->disp;
- info->disp = &fb->disp;
fb->sti = sti;
/* store upper 32bits of the graphics id */
@@ -1234,30 +1172,22 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
case 1:
fix->type = FB_TYPE_PLANES; /* well, sort of */
fix->visual = FB_VISUAL_MONO10;
- dispsw = &fbcon_sti;
break;
-#ifdef FBCON_HAS_CFB8
case 8:
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
- dispsw = &fbcon_cfb8;
var->red.length = var->green.length = var->blue.length = 8;
break;
-#endif
-#ifdef FBCON_HAS_CFB32
case 32:
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_TRUECOLOR;
- dispsw = &fbcon_cfb32;
var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
var->blue.offset = 0;
var->green.offset = 8;
var->red.offset = 16;
var->transp.offset = 24;
break;
-#endif
default:
- dispsw = &fbcon_dummy;
break;
}
@@ -1265,22 +1195,16 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
var->yres = var->yres_virtual = yres;
var->bits_per_pixel = bpp;
- strcpy(info->modename, "stifb");
+ strcpy(fix->id, "stifb");
info->node = NODEV;
info->fbops = &stifb_ops;
info->screen_base = (void*) REGION_BASE(fb,1);
- info->disp = disp;
- info->changevar = NULL;
- info->switch_con = gen_switch;
- info->updatevar = &gen_update_var;
info->flags = FBINFO_FLAG_DEFAULT;
info->currcon = -1;
/* This has to been done !!! */
fb_alloc_cmap(&info->cmap, 256, 0);
stifb_init_display(fb);
- gen_set_disp(-1, info);
- disp->dispsw = dispsw;
if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb")) {
printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n",
@@ -1297,13 +1221,15 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
if (register_framebuffer(&fb->info) < 0)
goto out_err3;
+ sti->info = info; /* save for unregister_framebuffer() */
+
printk(KERN_INFO
"fb%d: %s %dx%d-%d frame buffer device, id: %04x, mmio: 0x%04lx\n",
minor(fb->info.node),
- fb->info.modename,
- disp->var.xres,
- disp->var.yres,
- disp->var.bits_per_pixel,
+ fix->id,
+ var->xres,
+ var->yres,
+ var->bits_per_pixel,
fb->id,
fix->mmio_start);
@@ -1315,6 +1241,7 @@ out_err3:
out_err2:
release_mem_region(fix->smem_start, fix->smem_len);
out_err1:
+ fb_dealloc_cmap(&info->cmap);
kfree(fb);
return -ENXIO;
}
@@ -1325,7 +1252,6 @@ stifb_init(void)
struct sti_struct *sti;
int i;
-
if (sti_init_roms() == NULL)
return -ENXIO; /* no STI cards available */
@@ -1346,7 +1272,17 @@ stifb_init(void)
static void __exit
stifb_cleanup(void)
{
- // unregister_framebuffer();
+ struct sti_struct *sti;
+ int i;
+
+ for (i = 0; i < MAX_STI_ROMS; i++) {
+ sti = sti_get_rom(i);
+ if (!sti)
+ break;
+ if (sti->info)
+ unregister_framebuffer(sti->info);
+ sti->info = NULL;
+ }
}
int __init
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 7a828918c948..b2437afe3455 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -166,6 +166,7 @@ static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect);
static void tdfxfb_copyarea(struct fb_info *info, struct fb_copyarea *area);
static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *image);
static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int banshee_wait_idle(struct fb_info *info);
static struct fb_ops tdfxfb_ops = {
.owner = THIS_MODULE,
@@ -318,7 +319,7 @@ static inline void banshee_make_room(struct tdfx_par *par, int size)
while((tdfx_inl(par, STATUS) & 0x1f) < size);
}
-static inline void banshee_wait_idle(struct fb_info *info)
+static int banshee_wait_idle(struct fb_info *info)
{
struct tdfx_par *par = (struct tdfx_par *) info->par;
int i = 0;
@@ -330,6 +331,7 @@ static inline void banshee_wait_idle(struct fb_info *info)
i = (tdfx_inl(par, STATUS) & STATUS_BUSY) ? 0 : i + 1;
if(i == 3) break;
}
+ return 0;
}
/*
@@ -758,7 +760,7 @@ static int tdfxfb_set_par(struct fb_info *info)
break;
}
#endif
- do_write_regs(par, &reg);
+ do_write_regs(info, &reg);
/* Now change fb_fix_screeninfo according to changes in par */
info->fix.line_length = info->var.xres * ((info->var.bits_per_pixel + 7)>>3);
@@ -1210,9 +1212,6 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
printk("fb: %s memory = %dK\n", tdfx_fix.id, tdfx_fix.smem_len >> 10);
- /* clear framebuffer memory */
- memset_io(info->screen_base, 0, tdfx_fix.smem_len);
-
tdfx_fix.ypanstep = nopan ? 0 : 1;
tdfx_fix.ywrapstep = nowrap ? 0 : 1;
@@ -1223,11 +1222,13 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
info->pseudo_palette = (void *)(default_par + 1);
info->flags = FBINFO_FLAG_DEFAULT;
+#ifndef MODULE
if (!mode_option)
mode_option = "640x480@60";
err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
if (!err || err == 4)
+#endif
info->var = tdfx_var;
size = (info->var.bits_per_pixel == 8) ? 256 : 16;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 68d91b0cc847..6d79bd1c0232 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -329,9 +329,6 @@ static int vga16fb_release(struct fb_info *info, int user)
static int vga16fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
-#ifdef FBCON_HAS_VGA
- struct display *p = (info->currcon < 0) ? info->disp : (fb_display + info->currcon);
-#endif
struct vga16fb_par *par = (struct vga16fb_par *) info->par;
u32 xres, right, hslen, left, xtotal;
u32 yres, lower, vslen, upper, ytotal;
@@ -368,20 +365,7 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var,
mode = MODE_SKIP4 | MODE_8BPP | MODE_CFB;
maxmem = 16384;
}
- }
-#ifdef FBCON_HAS_VGA
- else if (var->bits_per_pixel == 0) {
- int fh;
-
- shift = 3;
- mode = MODE_TEXT;
- fh = fontheight(p);
- if (!fh)
- fh = 16;
- maxmem = 32768 * fh;
- }
-#endif
- else
+ } else
return -EINVAL;
xres = (var->xres + 7) & ~7;
@@ -548,42 +532,6 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var,
}
#undef FAIL
-#ifdef FBCON_HAS_VGA
-static void vga16fb_load_font(struct display* p)
-{
- int chars;
- unsigned char* font;
- unsigned char* dest;
- int chars;
-
- if (!p || !p->fontdata)
- return;
- chars = 256;
- font = p->fontdata;
- dest = vga16fb.screen_base;
-
- vga_io_wseq(0x00, 0x01);
- vga_io_wseq(VGA_SEQ_PLANE_WRITE, 0x04);
- vga_io_wseq(VGA_SEQ_MEMORY_MODE, 0x07);
- vga_io_wseq(0x00, 0x03);
- vga_io_wgfx(VGA_GFX_MODE, 0x00);
- vga_io_wgfx(VGA_GFX_MISC, 0x04);
- while (chars--) {
- int i;
-
- for (i = fontheight(p); i > 0; i--)
- writeb(*font++, dest++);
- dest += 32 - fontheight(p);
- }
- vga_io_wseq(0x00, 0x01);
- vga_io_wseq(VGA_SEQ_PLANE_WRITE, 0x03);
- vga_io_wseq(VGA_SEQ_MEMORY_MODE, 0x03);
- vga_io_wseq(0x00, 0x03);
- vga_io_wgfx(VGA_GFX_MODE, 0x10);
- vga_io_wgfx(VGA_GFX_MISC, 0x06);
-}
-#endif
-
static int vga16fb_set_par(struct fb_info *info)
{
struct vga16fb_par *par = (struct vga16fb_par *) info->par;
@@ -690,10 +638,6 @@ static int vga16fb_set_par(struct fb_info *info)
vga_io_wattr(i, atc[i]);
}
-#ifdef FBCON_HAS_VGA
- if (par->mode & MODE_TEXT)
- vga16fb_load_font(p);
-#endif
/* Wait for screen to stabilize. */
mdelay(50);
@@ -1051,10 +995,6 @@ void vga16fb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
} else
vga_8planes_fillrect(info, rect);
break;
-#ifdef FBCON_HAS_VGA
- case FB_TYPE_TEXT:
- break;
-#endif
case FB_TYPE_PACKED_PIXELS:
default:
cfb_fillrect(info, rect);
@@ -1198,10 +1138,6 @@ void vga16fb_copyarea(struct fb_info *info, struct fb_copyarea *area)
} else
vga_8planes_copyarea(info, area);
break;
-#ifdef FBCON_HAS_VGA
- case FB_TYPE_TEXT:
- break;
-#endif
case FB_TYPE_PACKED_PIXELS:
default:
cfb_copyarea(info, area);
@@ -1313,10 +1249,6 @@ void vga_imageblit_expand(struct fb_info *info, struct fb_image *image)
} else
vga_8planes_imageblit(info, image);
break;
-#ifdef FBCON_HAS_VGA
- case FB_TYPE_TEXT:
- break;
-#endif
case FB_TYPE_PACKED_PIXELS:
default:
cfb_imageblit(info, image);
diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c
index 39ebe6c36823..99ffe59f60cc 100644
--- a/drivers/video/vgastate.c
+++ b/drivers/video/vgastate.c
@@ -111,7 +111,7 @@ static void save_vga_text(struct vgastate *state, caddr_t fbbase)
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8192; i++)
- saved->vga_text[i] = vga_r(fbbase + 2 * 8192, i);
+ saved->vga_text[8192+i] = vga_r(fbbase + 2 * 8192, i);
}
/* restore regs */
@@ -184,7 +184,7 @@ static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
- for (i = 0; i < 4 * 8192; i++)
+ for (i = 0; i < state->memsize; i++)
vga_w(fbbase, i, saved->vga_font1[i]);
}
@@ -204,8 +204,7 @@ static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8192; i++)
- vga_w(fbbase + 2 * 8192, i,
- saved->vga_text[i]);
+ vga_w(fbbase, i, saved->vga_text[8192+i]);
}
/* unblank screen */