diff options
| author | James Simmons <jsimmons@kozmo.(none)> | 2002-12-05 20:17:32 -0800 |
|---|---|---|
| committer | James Simmons <jsimmons@kozmo.(none)> | 2002-12-05 20:17:32 -0800 |
| commit | b4e5e606e98b5edb81079e937f341c0557cfbdba (patch) | |
| tree | 0aabc6f050790029636982efa89f0ea04c8a8b3b | |
| parent | a610260de458941d2c3e0b7b0a2a9a4989d3b02b (diff) | |
| parent | 4dcc2bc5ef2901c9a5e756976d063f0bb16a3f02 (diff) | |
Merge kozmo.(none):/usr/src/linus-2.5
into kozmo.(none):/usr/src/fbdev-2.5
179 files changed, 14328 insertions, 19700 deletions
@@ -2842,6 +2842,16 @@ S: Klosterweg 28 / i309 S: 76131 Karlsruhe S: Germany +N: James Simmons +E: jsimmons@users.sf.net +D: Frame buffer device maintainer +D: input layer developement +D: tty/console layer +D: various mipsel devices +S: 115 Carmel Avenue +S: El Cerrito CA 94530 +S: USA + N: Jaspreet Singh E: jaspreet@sangoma.com W: www.sangoma.com diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 325a9447e073..f7b088432595 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -365,7 +365,7 @@ KAO --> !Edrivers/video/fbmem.c </sect1> <sect1><title>Frame Buffer Console</title> -!Edrivers/video/fbcon.c +!Edrivers/video/console/fbcon.c </sect1> <sect1><title>Frame Buffer Colormap</title> !Edrivers/video/fbcmap.c @@ -385,7 +385,7 @@ KAO --> !Idrivers/video/macmodes.c </sect1> <sect1><title>Frame Buffer Fonts</title> -!Idrivers/video/fonts.c +!Idrivers/video/console/fonts.c </sect1> </chapter> <!-- Needs ksyms to list additional exported symbols, but no specific doc. diff --git a/Documentation/fb/internals.txt b/Documentation/fb/internals.txt index a73d721d7bba..9b2a2b2f3e57 100644 --- a/Documentation/fb/internals.txt +++ b/Documentation/fb/internals.txt @@ -3,6 +3,7 @@ This is a first start for some documentation about frame buffer device internals. Geert Uytterhoeven <geert@linux-m68k.org>, 21 July 1998 +James Simmons <jsimmons@user.sf.net>, Nov 26 2002 -------------------------------------------------------------------------------- @@ -44,10 +45,6 @@ are defined in <linux/fb.h>. Device dependent information that uniquely defines the video mode for this particular piece of hardware. - - struct display - - Interface between the frame buffer device and the console driver. - -------------------------------------------------------------------------------- diff --git a/Documentation/fb/README-sstfb.txt b/Documentation/fb/sstfb.txt index b6d9d923fbb7..b6d9d923fbb7 100644 --- a/Documentation/fb/README-sstfb.txt +++ b/Documentation/fb/sstfb.txt diff --git a/MAINTAINERS b/MAINTAINERS index b4f0efbace88..d282eb76988d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -637,6 +637,13 @@ M: kevin.curtis@farsite.co.uk W: http://www.farsite.co.uk/ S: Supported +FRAMEBUFFER LAYER +P: James Simmons, Geert Uytterhoeven +M: jsimmons@users.sf.net, geert@linux-m68k.org +L: linux-fbdev-devel@lists.sourceforge.net +W: http://www.linux-fbdev.org +S: Supported + FILE LOCKING (flock() and fcntl()/lockf()) P: Matthew Wilcox M: matthew@wil.cx diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index ac17f1cbcffb..33175c774128 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -900,39 +900,8 @@ source "drivers/media/Kconfig" source "fs/Kconfig" - -menu "Console drivers" - depends on VT - -config VGA_CONSOLE - bool "VGA text console" - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - <ftp://ibiblio.org/pub/Linux/utils/console/>. - - Say Y. - -# if [ "$CONFIG_PCI" = "y" -a "$CONFIG_VGA_CONSOLE" = "y" ]; then -# bool ' Allow VGA on any bus?' CONFIG_VGA_HOSE -# if [ "$CONFIG_VGA_HOSE" = "y" ]; then -# define_bool CONFIG_DUMMY_CONSOLE y -# fi -# fi source "drivers/video/Kconfig" -config PCI_CONSOLE - bool - depends on FB - default y - -endmenu - - menu "Sound" config SOUND diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4637eccd0d87..f887b250fee1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1047,29 +1047,8 @@ source "drivers/media/Kconfig" source "fs/Kconfig" - -menu "Console drivers" - depends on VT - -config VGA_CONSOLE - bool "VGA text console" - depends on !ARCH_ACORN && !ARCH_EBSA110 - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - <ftp://ibiblio.org/pub/Linux/utils/console/>. - - Say Y. - source "drivers/video/Kconfig" -endmenu - - menu "Sound" depends on ARCH_ACORN || ARCH_CLPS7500 || ARCH_TBOX || ARCH_SHARK || ARCH_SA1100 || PCI diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 073355b7deff..6ebd4c56faba 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -1443,63 +1443,8 @@ source "drivers/media/Kconfig" source "fs/Kconfig" - -menu "Console drivers" - depends on VT - -config VGA_CONSOLE - bool "VGA text console" - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - <ftp://ibiblio.org/pub/Linux/utils/console/>. - - Say Y. - -config VIDEO_SELECT - bool "Video mode selection support" - ---help--- - This enables support for text mode selection on kernel startup. If - you want to take advantage of some high-resolution text mode your - card's BIOS offers, but the traditional Linux utilities like - SVGATextMode don't, you can say Y here and set the mode using the - "vga=" option from your boot loader (lilo or loadlin) or set - "vga=ask" which brings up a video mode menu on kernel startup. (Try - "man bootparam" or see the documentation of your boot loader about - how to pass options to the kernel.) - - Read the file <file:Documentation/svga.txt> for more information - about the Video mode selection support. If unsure, say N. - -if EXPERIMENTAL - -config MDA_CONSOLE - tristate "MDA text console (dual-headed) (EXPERIMENTAL)" - ---help--- - Say Y here if you have an old MDA or monochrome Hercules graphics - adapter in your system acting as a second head ( = video card). You - will then be able to use two monitors with your Linux system. Do not - say Y here if your MDA card is the primary card in your system; the - normal VGA driver will handle it. - - This 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 mdacon.o. If you want to compile it as - a module, say M here and read <file:Documentation/modules.txt>. - - If unsure, say N. - source "drivers/video/Kconfig" -endif - -endmenu - - menu "Sound" config SOUND diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 7708b29a0f90..7c1bc5127807 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -729,33 +729,8 @@ source "fs/Kconfig" if !IA64_HP_SIM - -menu "Console drivers" - depends on VT - -config VGA_CONSOLE - bool "VGA text console" - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - <ftp://ibiblio.org/pub/Linux/utils/console/>. - - Say Y. - source "drivers/video/Kconfig" -config PCI_CONSOLE - bool - depends on FB - default y - -endmenu - - menu "Sound" config SOUND diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index ba138ab925ff..59e449a9187f 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -2309,15 +2309,8 @@ endmenu source "fs/Kconfig" - -menu "Console drivers" - depends on VT - source "drivers/video/Kconfig" -endmenu - - menu "Kernel hacking" config DEBUG_KERNEL diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index e199b0a322cd..333eb3c5fb98 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -672,43 +672,8 @@ source "drivers/media/Kconfig" source "fs/Kconfig" - -menu "Console drivers" - depends on VT - -config VGA_CONSOLE - bool "VGA text console" - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - <ftp://ibiblio.org/pub/Linux/utils/console/>. - - If unsure, say N. - -config VIDEO_SELECT - bool "Video mode selection support" - ---help--- - This enables support for text mode selection on kernel startup. If - you want to take advantage of some high-resolution text mode your - card's BIOS offers, but the traditional Linux utilities like - SVGATextMode don't, you can say Y here and set the mode using the - "vga=" option from your boot loader (lilo or loadlin) or set - "vga=ask" which brings up a video mode menu on kernel startup. (Try - "man bootparam" or see the documentation of your boot loader about - how to pass options to the kernel.) - - Read the file <file:Documentation/svga.txt> for more information - about the Video mode selection support. If unsure, say N. - source "drivers/video/Kconfig" -endmenu - - menu "Sound" config SOUND diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 61aefc45cc10..fb570cf0ae57 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1115,28 +1115,6 @@ config VT_CONSOLE bool "Support for console on virtual terminal" depends on VT -config SGI_NEWPORT_CONSOLE - tristate "SGI Newport Console support" - depends on VT - help - Say Y here if you want the console on the Newport aka XL graphics - card of your Indy. Most people say Y here. - -config DUMMY_CONSOLE - bool - depends on VT && SGI_NEWPORT_CONSOLE!=y - default y - -config FONT_8x16 - bool - depends on VT && SGI_NEWPORT_CONSOLE=y - default y - help - This is the "high resolution" font for the VGA frame buffer (the one - provided by the VGA text console 80x25 mode. - - If unsure, say Y. - config PSMOUSE bool "PS/2 mouse support (aka \"auxiliary device\")" ---help--- @@ -1192,48 +1170,8 @@ endmenu source "fs/Kconfig" - -menu "Console drivers" - depends on VT - -config VGA_CONSOLE - bool "VGA text console" - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - <ftp://ibiblio.org/pub/Linux/utils/console/>. - - Say Y. - -if EXPERIMENTAL - -config MDA_CONSOLE - tristate "MDA text console (dual-headed) (EXPERIMENTAL)" - ---help--- - Say Y here if you have an old MDA or monochrome Hercules graphics - adapter in your system acting as a second head ( = video card). You - will then be able to use two monitors with your Linux system. Do not - say Y here if your MDA card is the primary card in your system; the - normal VGA driver will handle it. - - This 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 mdacon.o. If you want to compile it as - a module, say M here and read <file:Documentation/modules.txt>. - - If unsure, say N. - source "drivers/video/Kconfig" -endif - -endmenu - - menu "Sound" depends on !DECSTATION diff --git a/arch/mips64/Kconfig b/arch/mips64/Kconfig index 40620ceced66..571fd0f25375 100644 --- a/arch/mips64/Kconfig +++ b/arch/mips64/Kconfig @@ -593,31 +593,8 @@ source "drivers/media/Kconfig" source "fs/Kconfig" - -menu "Console drivers" - depends on VT - source "drivers/video/Kconfig" -config SGI_NEWPORT_CONSOLE - tristate "SGI Newport Console support" - depends on SGI_IP22 - help - Say Y here if you want the console on the Newport aka XL graphics - card of your Indy. Most people say Y here. - -config DUMMY_CONSOLE - bool - depends on SGI_IP22 && SGI_NEWPORT_CONSOLE!=y - default y - -config FONT_8x16 - bool - depends on SGI_IP22 && SGI_NEWPORT_CONSOLE=y - default y - -endmenu - config KCORE_ELF bool depends on PROC_FS diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index c1a28b2e814d..3104b344cf09 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -335,38 +335,8 @@ source "drivers/media/Kconfig" source "fs/Kconfig" - -menu "Console drivers" - depends on VT - -config STI_CONSOLE - bool "STI console" - 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 give you an 8 color text console on - most of the PA-RISC systems. - Really old HP boxes may not have STI, in which case you must use the - PDC console or your primary serial port as a console. - - The text console uses a strange memory layout, and changing the - plane mask to create colored characters requires calls to the STI - routines. Because of that do not expect it to be actually very fast, - but it is sufficient for basic text console functions, including fonts. - - The alternative is to use your primary serial port as a console. - - It is safe to enable this option, so you should probably say "Y". - -config DUMMY_CONSOLE - bool - depends on STI_CONSOLE || SERIAL_8250_CONSOLE - default y - source "drivers/video/Kconfig" -endmenu - menu "Sound" config SOUND diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 431ef90e5b6c..3c55bfb40f21 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -1054,11 +1054,6 @@ config CMDLINE some command-line options at build time by entering them here. In most cases you will need to specify the root device here. -config FB_CONSOLE - bool - depends on APUS - default y - config AMIGA bool depends on APUS @@ -1467,25 +1462,8 @@ source "net/irda/Kconfig" source "drivers/isdn/Kconfig" - -menu "Console drivers" - -config VGA_CONSOLE - bool "VGA text console" - depends on !4xx && !8xx - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. This can be - useful on PReP systems and IBM RS/6000 or pSeries machines but is of - limited usefulness on Apple machines. - - Say N here if you have an Apple machine. - source "drivers/video/Kconfig" -endmenu - - menu "iSeries device drivers" depends on PPC_ISERIES diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 9cdcc3d85124..4cb9f52630f0 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -410,15 +410,8 @@ source "drivers/media/Kconfig" source "fs/Kconfig" - -menu "Console drivers" - depends on VT - source "drivers/video/Kconfig" -endmenu - - menu "Sound" config SOUND diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 367e9abb76f0..24d33e1d5734 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -1190,63 +1190,8 @@ source "fs/Kconfig" source "drivers/media/Kconfig" - -menu "Console drivers" - depends on VT - -config VGA_CONSOLE - bool "VGA text console" - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - <ftp://ibiblio.org/pub/Linux/utils/console/>. - - Say Y. - -config VIDEO_SELECT - bool "Video mode selection support" - ---help--- - This enables support for text mode selection on kernel startup. If - you want to take advantage of some high-resolution text mode your - card's BIOS offers, but the traditional Linux utilities like - SVGATextMode don't, you can say Y here and set the mode using the - "vga=" option from your boot loader (lilo or loadlin) or set - "vga=ask" which brings up a video mode menu on kernel startup. (Try - "man bootparam" or see the documentation of your boot loader about - how to pass options to the kernel.) - - Read the file <file:Documentation/svga.txt> for more information - about the Video mode selection support. If unsure, say N. - -if EXPERIMENTAL - -config MDA_CONSOLE - tristate "MDA text console (dual-headed) (EXPERIMENTAL)" - ---help--- - Say Y here if you have an old MDA or monochrome Hercules graphics - adapter in your system acting as a second head ( = video card). You - will then be able to use two monitors with your Linux system. Do not - say Y here if your MDA card is the primary card in your system; the - normal VGA driver will handle it. - - This 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 mdacon.o. If you want to compile it as - a module, say M here and read <file:Documentation/modules.txt>. - - If unsure, say N. - source "drivers/video/Kconfig" -endif - -endmenu - - menu "Sound" config SOUND diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index c50de97230f1..cc5d534ec3b1 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -417,24 +417,8 @@ config PRINTER endmenu - -menu "Console drivers" - -config PROM_CONSOLE - bool "PROM console" - help - Say Y to build a console driver for Sun machines that uses the - terminal emulation built into their console PROMS. - -config DUMMY_CONSOLE - bool - depends on !PROM_CONSOLE - default y - source "drivers/video/Kconfig" -endmenu - source "drivers/mtd/Kconfig" source "drivers/serial/Kconfig" diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index c61e098e0f56..f28c476dd5da 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -530,19 +530,8 @@ config WATCHDOG_RIO endmenu - -menu "Console drivers" - -config PROM_CONSOLE - bool "PROM console" - help - Say Y to build a console driver for Sun machines that uses the - terminal emulation built into their console PROMS. - source "drivers/video/Kconfig" -endmenu - source "drivers/serial/Kconfig" source "drivers/sbus/char/Kconfig" diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig index bdd17d8a015b..c96e55a6aebd 100644 --- a/arch/v850/Kconfig +++ b/arch/v850/Kconfig @@ -365,43 +365,8 @@ source "drivers/media/Kconfig" source "fs/Kconfig" - -menu "Console drivers" - depends on VT - -config VGA_CONSOLE - bool "VGA text console" - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - <ftp://ibiblio.org/pub/Linux/utils/console/>. - - If unsure, say N. - -config VIDEO_SELECT - bool "Video mode selection support" - ---help--- - This enables support for text mode selection on kernel startup. If - you want to take advantage of some high-resolution text mode your - card's BIOS offers, but the traditional Linux utilities like - SVGATextMode don't, you can say Y here and set the mode using the - "vga=" option from your boot loader (lilo or loadlin) or set - "vga=ask" which brings up a video mode menu on kernel startup. (Try - "man bootparam" or see the documentation of your boot loader about - how to pass options to the kernel.) - - Read the file <file:Documentation/svga.txt> for more information - about the Video mode selection support. If unsure, say N. - source "drivers/video/Kconfig" -endmenu - - menu "Sound" config SOUND diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 867d54bea665..3d5d90fddec6 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -588,63 +588,8 @@ source "drivers/media/Kconfig" source "fs/Kconfig" - -menu "Console drivers" - depends on VT - -config VGA_CONSOLE - bool "VGA text console" - help - Saying Y here will allow you to use Linux in text mode through a - display that complies with the generic VGA standard. Virtually - everyone wants that. - - The program SVGATextMode can be used to utilize SVGA video cards to - their full potential in text mode. Download it from - <ftp://ibiblio.org/pub/Linux/utils/console/>. - - Say Y. - -config VIDEO_SELECT - bool "Video mode selection support" - ---help--- - This enables support for text mode selection on kernel startup. If - you want to take advantage of some high-resolution text mode your - card's BIOS offers, but the traditional Linux utilities like - SVGATextMode don't, you can say Y here and set the mode using the - "vga=" option from your boot loader (lilo or loadlin) or set - "vga=ask" which brings up a video mode menu on kernel startup. (Try - "man bootparam" or see the documentation of your boot loader about - how to pass options to the kernel.) - - Read the file <file:Documentation/svga.txt> for more information - about the Video mode selection support. If unsure, say N. - -if EXPERIMENTAL - -config MDA_CONSOLE - tristate "MDA text console (dual-headed) (EXPERIMENTAL)" - ---help--- - Say Y here if you have an old MDA or monochrome Hercules graphics - adapter in your system acting as a second head ( = video card). You - will then be able to use two monitors with your Linux system. Do not - say Y here if your MDA card is the primary card in your system; the - normal VGA driver will handle it. - - This 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 mdacon.o. If you want to compile it as - a module, say M here and read <file:Documentation/modules.txt>. - - If unsure, say N. - source "drivers/video/Kconfig" -endif - -endmenu - - menu "Sound" config SOUND diff --git a/drivers/Makefile b/drivers/Makefile index 2d983c7d9271..b882bfe78399 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_FC4) += fc4/ obj-$(CONFIG_SCSI) += scsi/ obj-$(CONFIG_FUSION) += message/ obj-$(CONFIG_IEEE1394) += ieee1394/ -obj-y += cdrom/ +obj-y += cdrom/ video/ obj-$(CONFIG_MTD) += mtd/ obj-$(CONFIG_PCMCIA) += pcmcia/ obj-$(CONFIG_DIO) += dio/ @@ -30,7 +30,6 @@ obj-$(CONFIG_ZORRO) += zorro/ obj-$(CONFIG_ALL_PPC) += macintosh/ obj-$(CONFIG_MAC) += macintosh/ obj-$(CONFIG_SGI) += sgi/ -obj-$(CONFIG_VT) += video/ obj-$(CONFIG_PARIDE) += block/paride/ obj-$(CONFIG_TC) += tc/ obj-$(CONFIG_USB) += usb/ diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 1ac447432022..8b1b9a2a3c1c 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -12,7 +12,7 @@ obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o random.o # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. -export-objs := busmouse.o vt.o generic_serial.o ip2main.o \ +export-objs := busmouse.o vt.o generic_serial.o ip2main.o consolemap.o\ ite_gpio.o keyboard.o misc.o nvram.o random.o rtc.o \ selection.o sonypi.o sysrq.o tty_io.o tty_ioctl.o diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index bf55df922e45..72ba2932fead 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c @@ -11,6 +11,8 @@ * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998 */ +#include <linux/config.h> +#include <linux/module.h> #include <linux/kd.h> #include <linux/errno.h> #include <linux/mm.h> @@ -19,7 +21,6 @@ #include <linux/tty.h> #include <asm/uaccess.h> #include <linux/consolemap.h> -#include <linux/console_struct.h> #include <linux/vt_kern.h> static unsigned short translations[][256] = { @@ -681,3 +682,5 @@ console_map_init(void) if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc) con_set_default_unimap(i); } + +EXPORT_SYMBOL(con_copy_unimap); diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index ddb472255a6a..bc1dfea7021d 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -35,7 +35,6 @@ #include <linux/init.h> #include <linux/slab.h> -#include <linux/console_struct.h> #include <linux/kbd_kern.h> #include <linux/kbd_diacr.h> #include <linux/vt_kern.h> diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 9e888905fd27..2639b087e5f4 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -33,12 +33,6 @@ extern int i2c_init_all(void); #ifdef CONFIG_FB extern void fbmem_init(void); #endif -#ifdef CONFIG_PROM_CONSOLE -extern void prom_con_init(void); -#endif -#ifdef CONFIG_MDA_CONSOLE -extern void mda_console_init(void); -#endif #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR) extern void tapechar_init(void); #endif @@ -686,12 +680,6 @@ int __init chr_dev_init(void) #if defined (CONFIG_FB) fbmem_init(); #endif -#if defined (CONFIG_PROM_CONSOLE) - prom_con_init(); -#endif -#if defined (CONFIG_MDA_CONSOLE) - mda_console_init(); -#endif tty_init(); #ifdef CONFIG_M68K_PRINTER lp_m68k_init(); diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 3295c7d6e6d2..6aa4932e7c4a 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -22,7 +22,6 @@ #include <linux/vt_kern.h> #include <linux/consolemap.h> -#include <linux/console_struct.h> #include <linux/selection.h> #ifndef MIN diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index 21cfdd3f1417..fc93acbc6dc1 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c @@ -210,7 +210,7 @@ static int tosh_emulate_fan(SMMRegisters *regs) /* * Put the laptop into System Management Mode */ -static int tosh_smm(SMMRegisters *regs) +int tosh_smm(SMMRegisters *regs) { int eax; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index cf880e8cacae..b39feeb6a4bc 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1509,6 +1509,13 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, return -EFAULT; if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg))) return 0; +#ifdef CONFIG_VT + if (tty->driver.type == TTY_DRIVER_TYPE_CONSOLE) { + unsigned int currcons = minor(tty->device) - tty->driver.minor_start; + if (vc_resize(currcons, tmp_ws.ws_col, tmp_ws.ws_row)) + return -ENXIO; + } +#endif if (tty->pgrp > 0) kill_pg(tty->pgrp, SIGWINCH, 1); if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0)) diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index 2fe40dfbd425..9e33415f8cdc 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -32,7 +32,6 @@ #include <linux/mm.h> #include <linux/init.h> #include <linux/vt_kern.h> -#include <linux/console_struct.h> #include <linux/selection.h> #include <linux/kbd_kern.h> #include <linux/console.h> diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 7ace02f718fb..21699dc053f9 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -90,7 +90,6 @@ #include <linux/devfs_fs_kernel.h> #include <linux/vt_kern.h> #include <linux/selection.h> -#include <linux/console_struct.h> #include <linux/kbd_kern.h> #include <linux/consolemap.h> #include <linux/timer.h> @@ -127,6 +126,15 @@ const struct consw *conswitchp; extern void vcs_make_devfs (unsigned int index, int unregister); extern void console_map_init(void); +#ifdef CONFIG_PROM_CONSOLE +extern void prom_con_init(void); +#endif +#ifdef CONFIG_MDA_CONSOLE +extern void mda_console_init(void); +#endif +#ifdef CONFIG_FRAMEBUFFER_CONSOLE +extern int fb_console_init(void); +#endif static struct tty_struct *console_table[MAX_NR_CONSOLES]; static struct termios *console_termios[MAX_NR_CONSOLES]; @@ -691,106 +699,106 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ return 0; } +inline int resize_screen(int currcons, int width, int height) +{ + /* Resizes the resolution of the display adapater */ + int err = 0; + + if (vcmode != KD_GRAPHICS && sw->con_resize) + err = sw->con_resize(vc_cons[currcons].d, width, height); + return err; +} + /* * Change # of rows and columns (0 means unchanged/the size of fg_console) * [this is to be used together with some user program * like resize that changes the hardware videomode] */ -int vc_resize(unsigned int lines, unsigned int cols, - unsigned int first, unsigned int last) -{ - unsigned int cc, ll, ss, sr, todo = 0; - unsigned int currcons = fg_console, i; - unsigned short *newscreens[MAX_NR_CONSOLES]; - - cc = (cols ? cols : video_num_columns); - ll = (lines ? lines : video_num_lines); - sr = cc << 1; - ss = sr * ll; - - for (currcons = first; currcons <= last; currcons++) { - if (!vc_cons_allocated(currcons) || - (cc == video_num_columns && ll == video_num_lines)) - newscreens[currcons] = NULL; - else { - unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER); - if (!p) { - for (i = first; i < currcons; i++) - if (newscreens[i]) - kfree(newscreens[i]); - return -ENOMEM; - } - newscreens[currcons] = p; - todo++; - } - } - if (!todo) +int vc_resize(int currcons, unsigned int cols, unsigned int lines) +{ + unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; + unsigned int old_cols, old_rows, old_row_size, old_screen_size; + unsigned int new_cols, new_rows, new_row_size, new_screen_size; + unsigned short *newscreen; + + if (!vc_cons_allocated(currcons)) + return -ENXIO; + + new_cols = (cols ? cols : video_num_columns); + new_rows = (lines ? lines : video_num_lines); + new_row_size = new_cols << 1; + new_screen_size = new_row_size * new_rows; + + if (new_cols == video_num_columns && new_rows == video_num_lines) return 0; - for (currcons = first; currcons <= last; currcons++) { - unsigned int occ, oll, oss, osr; - unsigned long ol, nl, nlend, rlth, rrem; - if (!newscreens[currcons] || !vc_cons_allocated(currcons)) - continue; + newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER); + if (!newscreen) + return -ENOMEM; - oll = video_num_lines; - occ = video_num_columns; - osr = video_size_row; - oss = screenbuf_size; - - video_num_lines = ll; - video_num_columns = cc; - video_size_row = sr; - screenbuf_size = ss; - - rlth = min(osr, sr); - rrem = sr - rlth; - ol = origin; - nl = (long) newscreens[currcons]; - nlend = nl + ss; - if (ll < oll) - ol += (oll - ll) * osr; - - update_attr(currcons); - - while (ol < scr_end) { - scr_memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth); - if (rrem) - scr_memsetw((void *)(nl + rlth), video_erase_char, rrem); - ol += osr; - nl += sr; - } - if (nlend > nl) - scr_memsetw((void *) nl, video_erase_char, nlend - nl); - if (kmalloced) - kfree(screenbuf); - screenbuf = newscreens[currcons]; - kmalloced = 1; - screenbuf_size = ss; - set_origin(currcons); + old_rows = video_num_lines; + old_cols = video_num_columns; + old_row_size = video_size_row; + old_screen_size = screenbuf_size; - /* do part of a reset_terminal() */ - top = 0; - bottom = video_num_lines; - gotoxy(currcons, x, y); - save_cur(currcons); - - if (console_table[currcons]) { - struct winsize ws, *cws = &console_table[currcons]->winsize; - memset(&ws, 0, sizeof(ws)); - ws.ws_row = video_num_lines; - ws.ws_col = video_num_columns; - if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && - console_table[currcons]->pgrp > 0) - kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1); - *cws = ws; - } + video_num_lines = new_rows; + video_num_columns = new_cols; + video_size_row = new_row_size; + screenbuf_size = new_screen_size; - if (IS_VISIBLE) - update_screen(currcons); + err = resize_screen(currcons, new_cols, new_rows); + if (err) + return err; + + rlth = min(old_row_size, new_row_size); + rrem = new_row_size - rlth; + old_origin = origin; + new_origin = (long) newscreen; + new_scr_end = new_origin + new_screen_size; + if (new_rows < old_rows) + old_origin += (old_rows - new_rows) * old_row_size; + + update_attr(currcons); + + while (old_origin < scr_end) { + scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth); + if (rrem) + scr_memsetw((void *)(new_origin + rlth), video_erase_char, rrem); + old_origin += old_row_size; + new_origin += new_row_size; } + if (new_scr_end > new_origin) + scr_memsetw((void *) new_origin, video_erase_char, new_scr_end - new_origin); + if (kmalloced) + kfree(screenbuf); + screenbuf = newscreen; + kmalloced = 1; + screenbuf_size = new_screen_size; + if (IS_VISIBLE) + err = resize_screen(currcons, new_cols, new_rows); + set_origin(currcons); - return 0; + /* do part of a reset_terminal() */ + top = 0; + bottom = video_num_lines; + gotoxy(currcons, x, y); + save_cur(currcons); + + if (vc_cons[currcons].d->vc_tty) { + struct winsize ws, *cws = &vc_cons[currcons].d->vc_tty->winsize; + + memset(&ws, 0, sizeof(ws)); + ws.ws_row = video_num_lines; + ws.ws_col = video_num_columns; + if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && + vc_cons[currcons].d->vc_tty->pgrp > 0) + kill_pg(vc_cons[currcons].d->vc_tty->pgrp, SIGWINCH, 1); + *cws = ws; + } + + if (IS_VISIBLE) + update_screen(currcons); + return err; } @@ -1200,7 +1208,7 @@ static void set_mode(int currcons, int on_off) case 3: /* 80/132 mode switch unimplemented */ deccolm = on_off; #if 0 - (void) vc_resize(video_num_lines, deccolm ? 132 : 80); + (void) vc_resize(deccolm ? 132 : 80, video_num_lines); /* this alone does not suffice; some user mode utility has to change the hardware regs */ #endif @@ -2525,6 +2533,15 @@ int __init vty_init(void) kbd_init(); console_map_init(); +#ifdef CONFIG_PROM_CONSOLE + prom_con_init(); +#endif +#ifdef CONFIG_MDA_CONSOLE + mda_console_init(); +#endif +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + fb_console_init(); +#endif con_init_devfs(); vcs_init(); return 0; @@ -3021,10 +3038,15 @@ EXPORT_SYMBOL(default_grn); EXPORT_SYMBOL(default_blu); EXPORT_SYMBOL(video_font_height); EXPORT_SYMBOL(video_scan_lines); +EXPORT_SYMBOL(vc_cons_allocated); +EXPORT_SYMBOL(update_region); +EXPORT_SYMBOL(redraw_screen); EXPORT_SYMBOL(vc_resize); EXPORT_SYMBOL(fg_console); EXPORT_SYMBOL(console_blank_hook); +EXPORT_SYMBOL(console_blanked); EXPORT_SYMBOL(vt_cons); +EXPORT_SYMBOL(vc_cons); #ifndef VT_SINGLE_DRIVER EXPORT_SYMBOL(take_over_console); EXPORT_SYMBOL(give_up_console); diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index fcdb5208acea..cda2f20d8308 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -810,7 +810,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, if (get_user(ll, &vtsizes->v_rows) || get_user(cc, &vtsizes->v_cols)) return -EFAULT; - return vc_resize_all(ll, cc); + for (i = 0; i < MAX_NR_CONSOLES; i++) + vc_resize(i, cc, ll); + return 0; } case VT_RESIZEX: @@ -829,37 +831,33 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, __get_user(vcol, &vtconsize->v_vcol); __get_user(ccol, &vtconsize->v_ccol); vlin = vlin ? vlin : video_scan_lines; - if ( clin ) - { - if ( ll ) - { - if ( ll != vlin/clin ) - return -EINVAL; /* Parameters don't add up */ - } - else - ll = vlin/clin; - } - if ( vcol && ccol ) - { - if ( cc ) - { - if ( cc != vcol/ccol ) - return -EINVAL; - } - else - cc = vcol/ccol; - } - - if ( clin > 32 ) - return -EINVAL; + if (clin) { + if (ll) { + if (ll != vlin/clin) + return -EINVAL; /* Parameters don't add up */ + } else + ll = vlin/clin; + } + if (vcol && ccol) { + if (cc) { + if (cc != vcol/ccol) + return -EINVAL; + } else + cc = vcol/ccol; + } + + if (clin > 32) + return -EINVAL; - if ( vlin ) - video_scan_lines = vlin; - if ( clin ) - video_font_height = clin; - - return vc_resize_all(ll, cc); - } + if (vlin) + video_scan_lines = vlin; + if (clin) + video_font_height = clin; + + for (i = 0; i < MAX_NR_CONSOLES; i++) + vc_resize(i, cc, ll); + return 0; + } case PIO_FONT: { struct console_font_op op; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index cdac597766c1..e0f0af3145ba 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2,10 +2,10 @@ # Video configuration # -menu "Frame-buffer support" +menu "Graphics support" config FB - bool "Support for frame buffer devices (EXPERIMENTAL)" + bool "Support for frame buffer devices" ---help--- The frame buffer device provides an abstraction for the graphics hardware. It represents the frame buffer of some video hardware and @@ -38,14 +38,9 @@ config FB (e.g. an accelerated X server) and that are not frame buffer device-aware may cause unexpected results. If unsure, say N. -config DUMMY_CONSOLE - bool - depends on FB - default y - config FB_CLGEN - tristate "Cirrus Logic support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && (AMIGA || PCI) + tristate "Cirrus Logic support" + depends on FB && (AMIGA || PCI) ---help--- This enables support for Cirrus Logic GD542x/543x based boards on Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. @@ -59,8 +54,8 @@ config FB_CLGEN before you next recompile the kernel. config FB_PM2 - tristate "Permedia2 support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && (AMIGA || PCI) + tristate "Permedia2 support" + depends on FB && (AMIGA || PCI) help This is the frame buffer device driver for the Permedia2 AGP frame buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a @@ -206,8 +201,8 @@ config FB_CYBER Cybervision 64 3D card, as they use incompatible video chips. config FB_VIRGE - bool "Amiga CyberVision3D support (EXPERIMENTAL)" - depends on FB && ZORRO && EXPERIMENTAL + bool "Amiga CyberVision3D support " + depends on FB && ZORRO help This enables support for the Cybervision 64/3D graphics card from Phase5. Please note that its use is not all that intuitive (i.e. if @@ -217,16 +212,16 @@ config FB_VIRGE Cybervision 64 card, as they use incompatible video chips. config FB_RETINAZ3 - tristate "Amiga RetinaZ3 support (EXPERIMENTAL)" - depends on FB && ZORRO && EXPERIMENTAL + tristate "Amiga RetinaZ3 support" + depends on FB && ZORRO help This enables support for the Retina Z3 graphics card. Say N unless you have a Retina Z3 or plan to get one before you next recompile the kernel. config FB_FM2 - bool "Amiga FrameMaster II/Rainbow II support (EXPERIMENTAL)" - depends on FB && ZORRO && EXPERIMENTAL + bool "Amiga FrameMaster II/Rainbow II support" + depends on FB && ZORRO help This is the frame buffer device driver for the Amiga FrameMaster card from BSC (exhibited 1992 but not shipped as a CBM product). @@ -238,33 +233,6 @@ config FB_ATARI This is the frame buffer device driver for the builtin graphics chipset found in Ataris. -config FB_ATY - tristate "ATI Mach64 display support (EXPERIMENTAL)" if EXPERIMENTAL && PCI - depends on FB - help - This driver supports graphics boards with the ATI Mach64 chips. - Say Y if you have such a graphics 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 atyfb.o. If you want to compile it as a - module, say M here and read <file:Documentation/modules.txt>. - -config FB_ATY - prompt "ATI Mach64 display support" - depends on FB && (SPARC64 && PCI && FB_PCI || ATARI) - -config FB_ATY_GX - bool "Mach64 GX support (EXPERIMENTAL)" if EXPERIMENTAL && PCI - depends on FB_ATY - default y if ATARI - help - Say Y here to support use of the ATI Mach64 Graphics Expression - board (or other boards based on the Mach64 GX chipset) as a - framebuffer device. The ATI product support page for these boards - is at - <http://support.ati.com/products/pc/mach64/graphics_xpression.html>. - config FB_OF bool "Open Firmware frame buffer device support" depends on FB && PPC && ALL_PPC @@ -302,7 +270,7 @@ config FB_CT65550 config FB_IMSTT bool "IMS Twin Turbo display support" - depends on FB && PPC + depends on FB && PCI help The IMS Twin Turbo is a PCI-based frame buffer card bundled with many Macintosh and compatible computers. @@ -368,15 +336,20 @@ config FB_TGA config FB_VESA bool "VESA VGA graphics console" - depends on FB && X86 + depends on FB && (X86 || X86_64) help This is the frame buffer device driver for generic VESA 2.0 compliant graphic cards. The older VESA 1.2 cards are not supported. You will get a boot time penguin logo at no additional cost. Please read <file:Documentation/fb/vesafb.txt>. If unsure, say Y. +config VIDEO_SELECT + bool + depends on FB_VESA + default y + config FB_HGA - tristate "Hercules mono graphics console (EXPERIMENTAL)" + tristate "Hercules mono graphics console" depends on FB && X86 help Say Y here if you have a Hercules mono graphics card. @@ -486,8 +459,8 @@ config E1355_FB_BASE discussion. config FB_RIVA - tristate "nVidia Riva support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "nVidia Riva support" + depends on FB && PCI help This driver supports graphics boards with the nVidia Riva/Geforce chips. @@ -499,8 +472,8 @@ config FB_RIVA module, say M here and read <file:Documentation/modules.txt>. config FB_MATROX - tristate "Matrox acceleration (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "Matrox acceleration" + depends on FB && PCI ---help--- Say Y here if you have a Matrox Millennium, Matrox Millennium II, Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox @@ -654,19 +627,9 @@ config FB_MATROX_MULTIHEAD There is no need for enabling 'Matrox multihead support' if you have only one Matrox card in the box. -config FB_ATY_CT - bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support" if EXPERIMENTAL - depends on PCI && FB_ATY - default y if SPARC64 && FB_PCI - help - Say Y here to support use of ATI's 64-bit Rage boards (or other - boards based on the Mach64 CT, VT, GT, and LT chipsets) as a - framebuffer device. The ATI product support page for these boards - is at <http://support.ati.com/products/pc/mach64/>. - config FB_RADEON - tristate "ATI Radeon display support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "ATI Radeon display support" + depends on FB && PCI help Choose this option if you want to use an ATI Radeon graphics card as a framebuffer device. There are both PCI and AGP versions. You @@ -675,8 +638,8 @@ config FB_RADEON <http://www.ati.com/na/pages/products/pc/radeon32/index.html>. config FB_ATY128 - tristate "ATI Rage128 display support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "ATI Rage128 display support" + depends on FB && PCI help This driver supports graphics boards with the ATI Rage128 chips. Say Y if you have such a graphics board and read @@ -687,9 +650,42 @@ config FB_ATY128 module will be called aty128fb.o. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +config FB_ATY + tristate "ATI Mach64 display support" if PCI || ATARI + depends on FB + help + This driver supports graphics boards with the ATI Mach64 chips. + Say Y if you have such a graphics 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 atyfb.o. If you want to compile it as a + module, say M here and read <file:Documentation/modules.txt>. + +config FB_ATY_CT + bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support" + depends on PCI && FB_ATY + default y if SPARC64 && FB_PCI + help + Say Y here to support use of ATI's 64-bit Rage boards (or other + boards based on the Mach64 CT, VT, GT, and LT chipsets) as a + framebuffer device. The ATI product support page for these boards + is at <http://support.ati.com/products/pc/mach64/>. + +config FB_ATY_GX + bool "Mach64 GX support" if PCI + depends on FB_ATY + default y if ATARI + help + Say Y here to support use of the ATI Mach64 Graphics Expression + board (or other boards based on the Mach64 GX chipset) as a + framebuffer device. The ATI product support page for these boards + is at + <http://support.ati.com/products/pc/mach64/graphics_xpression.html>. + config FB_SIS - tristate "SIS acceleration (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "SIS acceleration" + depends on FB && PCI help This is the frame buffer device driver for the SiS 630 and 640 Super Socket 7 UMA cards. Specs available at <http://www.sis.com.tw/>. @@ -710,8 +706,8 @@ config FB_SIS_315 card. Specs available at <http://www.sis.com.tw/>. config FB_NEOMAGIC - tristate "NeoMagic display support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "NeoMagic display support" + depends on FB && PCI help This driver supports notebooks with NeoMagic PCI chips. Say Y if you have such a graphics card. @@ -722,8 +718,8 @@ config FB_NEOMAGIC module, say M here and read Documentation/modules.txt. config FB_3DFX - tristate "3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "3Dfx Banshee/Voodoo3 display support" + depends on FB && PCI help This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 chips. Say Y if you have such a graphics board. @@ -734,8 +730,8 @@ config FB_3DFX module, say M here and read <file:Documentation/modules.txt>. config FB_VOODOO1 - tristate "3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "3Dfx Voodoo Graphics (sst1) support" + depends on FB && PCI ---help--- Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or Voodoo2 (cvg) based graphics card. @@ -751,8 +747,8 @@ config FB_VOODOO1 options and other important info support. config FB_TRIDENT - tristate "Trident support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "Trident support" + depends on FB && PCI ---help--- This driver is supposed to support graphics boards with the Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops @@ -767,8 +763,8 @@ config FB_TRIDENT module, say M here and read <file:Documentation/modules.txt>. config FB_PM3 - tristate "Permedia3 support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI + tristate "Permedia3 support" + depends on FB && PCI help This is the frame buffer device driver for the 3DLabs Permedia3 chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & @@ -875,8 +871,8 @@ config FB_68328 the Motorola 68328 CPU family. config FB_VIRTUAL - tristate "Virtual Frame Buffer support (ONLY FOR TESTING!) (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL + tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" + depends on FB ---help--- This is a `virtual' frame buffer device. It operates on a chunk of unswappable kernel memory instead of on the memory of a graphics @@ -894,262 +890,7 @@ config FB_VIRTUAL If unsure, say N. -config FBCON_ADVANCED - bool "Advanced low level driver options" - depends on FB - ---help--- - The frame buffer console uses character drawing routines that are - tailored to the specific organization of pixels in the memory of - your graphics hardware. These are called the low level frame buffer - console drivers. Note that they are used for text console output - only; they are NOT needed for graphical applications. - - If you say N here, the needed low level drivers are automatically - enabled, depending on what frame buffer devices you selected above. - This is recommended for most users. - - If you say Y here, you have more fine-grained control over which low - level drivers are enabled. You can e.g. leave out low level drivers - for color depths you do not intend to use for text consoles. - - Low level frame buffer console drivers can be modules ( = code which - can be inserted and removed from the running kernel whenever you - want). The modules will be called fbcon-*.o. If you want to compile - (some of) them as modules, read <file:Documentation/modules.txt>. - - If unsure, say N. - -config FBCON_MFB - tristate "Monochrome support" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && !FB_ACORN && FB_AMIGA!=y && !FB_ATARI && FB_CYBER!=y && !FB_BWTWO && FB_RETINAZ3!=y && !FB_VIRGE && FB_CLGEN!=y && (FB_AMIGA=m || FB_CYBER=m || FB_RETINAZ3=m || FB_CLGEN=m) - default y if !FBCON_ADVANCED && (FB_ACORN || FB_AMIGA=y || FB_ATARI || FB_CYBER=y || FB_BWTWO || FB_RETINAZ3=y || FB_VIRGE || FB_CLGEN=y) - help - This is the low level frame buffer console driver for monochrome - (2 colors) packed pixels. - -config FBCON_CFB2 - tristate "2 bpp packed pixels support" if FBCON_ADVANCED - depends on FB - default y if !FBCON_ADVANCED && (FB_ACORN || FB_SA1100) - help - This is the low level frame buffer console driver for 2 bits per - pixel (4 colors) packed pixels. - -config FBCON_CFB4 - tristate "4 bpp packed pixels support" if FBCON_ADVANCED - depends on FB - default y if !FBCON_ADVANCED && (FB_ACORN || FB_SA1100) - help - This is the low level frame buffer console driver for 4 bits per - pixel (16 colors) packed pixels. - -config FBCON_CFB8 - tristate "8 bpp packed pixels support" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && !FB_ACORN && !FB_ATARI && !FB_P9100 && FB_CYBER2000!=y && FB_RADEON!=y && FB_TGA!=y && FB_SIS!=y && FB_PM3!=y && !FB_TCX && !FB_CGTHREE && !FB_CONTROL && FB_CLGEN!=y && !FB_CGFOURTEEN && FB_TRIDENT!=y && !FB_VIRGE && FB_CYBER!=y && !FB_VALKYRIE && !FB_PLATINUM && !FB_IGA && FB_MATROX!=y && !FB_CT65550 && FB_PM2!=y && !FB_SA1100 && (FB_CYBER2000=m || FB_RADEON=m || FB_TGA=m || FB_SIS=m || FB_PM3=m || FB_CLGEN=m || FB_TRIDENT=m || FB_CYBER=m || FB_MATROX=m || FB_PM2=m) - default y if !FBCON_ADVANCED && (FB_ACORN || FB_ATARI || FB_P9100 || FB_CYBER2000=y || FB_RADEON=y || FB_TGA=y || FB_SIS=y || FB_PM3=y || FB_TCX || FB_CGTHREE || FB_CONTROL || FB_CLGEN=y || FB_CGFOURTEEN || FB_TRIDENT=y || FB_VIRGE || FB_CYBER=y || FB_VALKYRIE || FB_PLATINUM || FB_IGA || FB_MATROX=y || FB_CT65550 || FB_PM2=y || FB_SA1100) - help - This is the low level frame buffer console driver for 8 bits per - pixel (256 colors) packed pixels. - -config FBCON_CFB16 - tristate "16 bpp packed pixels support" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && !FB_ATARI && FB_PM3!=y && FB_SIS!=y && FB_PVR2!=y && FB_TRIDENT!=y && !FB_TBOX && FB_VOODOO1!=y && FB_RADEON!=y && !FB_CONTROL && FB_CLGEN!=y && !FB_VIRGE && FB_CYBER!=y && !FB_VALKYRIE && !FB_PLATINUM && !FB_CT65550 && FB_MATROX!=y && FB_PM2!=y && FB_CYBER2000!=y && !FB_SA1100 && (FB_SIS=m || FB_RADEON=m || FB_PVR2=m || FB_TRIDENT=m || FB_VOODOO1=m || FB_PM3=m || FB_CLGEN=m || FB_CYBER=m || FB_MATROX=m || FB_PM2=m || FB_CYBER2000=m || FB_SA1100) - default y if !FBCON_ADVANCED && (FB_ATARI || FB_PM3=y || FB_SIS=y || FB_PVR2=y || FB_TRIDENT=y || FB_TBOX || FB_VOODOO1=y || FB_RADEON=y || FB_CONTROL || FB_CLGEN=y || FB_VIRGE || FB_CYBER=y || FB_VALKYRIE || FB_PLATINUM || FB_CT65550 || FB_MATROX=y || FB_PM2=y || FB_CYBER2000=y || FB_SA1100) - help - This is the low level frame buffer console driver for 15 or 16 bits - per pixel (32K or 64K colors, also known as `hicolor') packed - pixels. - -config FBCON_CFB24 - tristate "24 bpp packed pixels support" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && FB_ATY!=y && FB_VIRTUAL!=y && FB_CLGEN!=y && !FB_VESA && FB_MATROX!=y && FB_PM2!=y && FB_ATY128!=y && FB_RADEON!=y && FB_CYBER2000!=y && FB_PVR2!=y && FB_VOODOO1!=y && FB_NEOMAGIC!=y && (FB_ATY=m || FB_VIRTUAL=m || FB_CLGEN=m || FB_MATROX=m || FB_PM2=m || FB_ATY128=m || FB_RADEON=m || FB_CYBER2000=m || FB_PVR2=m || FB_VOODOO1=m || FB_NEOMAGIC=y) - default y if !FBCON_ADVANCED && (FB_ATY=y || FB_VIRTUAL=y || FB_CLGEN=y || FB_VESA || FB_MATROX=y || FB_PM2=y || FB_ATY128=y || FB_RADEON=y || FB_CYBER2000=y || FB_PVR2=y || FB_VOODOO1=y || FB_NEOMAGIC=y) - help - This is the low level frame buffer console driver for 24 bits per - pixel (16M colors, also known as `truecolor') packed pixels. It is - NOT for `sparse' 32 bits per pixel mode. - -config FBCON_CFB32 - tristate "32 bpp packed pixels support" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && !FB_ATARI && FB_RADEON!=y && FB_VOODOO1!=y && FB_TRIDENT!=y && !FB_CONTROL && FB_CLGEN!=y && FB_TGA!=y && !FB_PLATINUM && FB_MATROX!=y && FB_PM2!=y && FB_PVR2!=y && FB_PM3!=y && FB_SIS!=y && (FB_RADEON=m || FB_VOODOO1=m || FB_TRIDENT=m || FB_CLGEN=m || FB_TGA=m || FB_MATROX=m || FB_PM2=m || FB_SIS=m || FB_PVR2=m || FB_PM3=m) - default y if !FBCON_ADVANCED && (FB_ATARI || FB_RADEON=y || FB_VOODOO1=y || FB_TRIDENT=y || FB_CONTROL || FB_CLGEN=y || FB_TGA=y || FB_PLATINUM || FB_MATROX=y || FB_PM2=y || FB_PVR2=y || FB_PM3=y || FB_SIS=y) - help - This is the low level frame buffer console driver for 32 bits per - pixel (16M colors, also known as `truecolor') sparse packed pixels. - -config FBCON_ACCEL - tristate "Hardware acceleration support" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && FB_NEOMAGIC!=y && !FB_VESA && !FB_FM2 && FB_HIT!=y && !FB_HP300 && !FB_Q40 && !FB_ANAKIN && !FB_G364 && FB_VIRTUAL!=y && !FB_CLPS711X && !FB_PMAG_BA && !FB_PMAGB_B && FB_3DFX!=y && !FB_TX3912 && !FB_MAXINE && !FB_APOLLO && FB_ATY!=y && !FB_MAC && FB_RIVA!=y && !FB_OF && FB_SGIVW!=y && (FB_NEOMAGIC=m || FB_HIT=m || FB_VIRTUAL=m || FB_3DFX=m || FB_RIVA=m || FB_SGIVW=m) - default y if !FBCON_ADVANCED && (FB_NEOMAGIC=y || FB_VESA || FB_FM2 || FB_HIT=y || FB_HP300 || FB_Q40 || FB_ANAKIN || FB_G364 || FB_VIRTUAL=y || FB_CLPS711X || FB_PMAG_BA || FB_PMAGB_B || FB_3DFX=y || FB_TX3912 || FB_MAXINE || FB_APOLLO || FB_ATY=y || FB_MAC || FB_RIVA=y || FB_OF || FB_SGIVW=y) - -config FBCON_AFB - tristate "Amiga bitplanes support" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && FB_AMIGA=m - default y if !FBCON_ADVANCED && FB_AMIGA=y - help - This is the low level frame buffer console driver for 1 to 8 - bitplanes (2 to 256 colors) on Amiga. - -config FBCON_ILBM - tristate "Amiga interleaved bitplanes support" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && FB_AMIGA=m - default y if !FBCON_ADVANCED && FB_AMIGA=y - help - This is the low level frame buffer console driver for 1 to 8 - interleaved bitplanes (2 to 256 colors) on Amiga. - -config FBCON_IPLAN2P2 - tristate "Atari interleaved bitplanes (2 planes) support" if FBCON_ADVANCED - depends on FB - default y if !FBCON_ADVANCED && FB_ATARI - help - This is the low level frame buffer console driver for 2 interleaved - bitplanes (4 colors) on Atari. - -config FBCON_IPLAN2P4 - tristate "Atari interleaved bitplanes (4 planes) support" if FBCON_ADVANCED - depends on FB - default y if !FBCON_ADVANCED && FB_ATARI - help - This is the low level frame buffer console driver for 4 interleaved - bitplanes (16 colors) on Atari. - -config FBCON_IPLAN2P8 - tristate "Atari interleaved bitplanes (8 planes) support" if FBCON_ADVANCED - depends on FB - default y if !FBCON_ADVANCED && FB_ATARI - help - This is the low level frame buffer console driver for 8 interleaved - bitplanes (256 colors) on Atari. - -# tristate ' Atari interleaved bitplanes (16 planes) support' CONFIG_FBCON_IPLAN2P16 -config FBCON_VGA_PLANES - tristate "VGA 16-color planar support" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && FB_VGA16=m - default y if !FBCON_ADVANCED && FB_VGA16=y - help - This low level frame buffer console driver enable the kernel to use - the 16-color planar modes of the old VGA cards where the bits of - each pixel are separated into 4 planes. - - Only answer Y here if you have a (very old) VGA card that isn't VESA - 2 compatible. - -config FBCON_HGA - tristate "HGA monochrome support (EXPERIMENTAL)" if FBCON_ADVANCED - depends on FB - default m if !FBCON_ADVANCED && FB_HGA=m - default y if !FBCON_ADVANCED && FB_HGA=y - help - This is the low level frame buffer console driver for Hercules mono - graphics cards. - -# Guess what we need -config FBCON_STI - tristate - depends on !FBCON_ADVANCED && FB_STI - default y - -config FBCON_FONTWIDTH8_ONLY - bool "Support only 8 pixels wide fonts" - depends on FB - 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" - depends on FB && (!SPARC32 && !SPARC64 && FBCON_FONTS || SPARC32 || SPARC64) - help - This is the high resolution console font for Sun machines. Say Y. - -config FONT_SUN12x22 - bool "Sparc console 12x22 font (not supported by all drivers)" - depends on FB && !FBCON_FONTWIDTH8_ONLY && (!SPARC32 && !SPARC64 && FBCON_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 - standard font is unreadable for you, say Y, otherwise say N. - -config FBCON_FONTS - bool "Select other fonts" if SPARC32 || SPARC64 - depends on FB - help - Say Y here if you would like to use fonts other than the default - your frame buffer console usually use. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about foreign fonts. - - If unsure, say N (the default choices are safe). - -config FBCON_FONTS - prompt "Select compiled-in fonts" - depends on FB && !SPARC32 && !SPARC64 - -config FONT_8x8 - bool "VGA 8x8 font" if FBCON_FONTS - depends on FB - default y if !SPARC32 && !SPARC64 && !FBCON_FONTS - help - This is the "high resolution" font for the VGA frame buffer (the one - provided by the text console 80x50 (and higher) modes). - - Note that this is a poor quality font. The VGA 8x16 font is quite a - lot more readable. - - Given the resolution provided by the frame buffer device, answer N - here is safe. - -config FONT_8x16 - bool "VGA 8x16 font" if FBCON_FONTS - depends on FB - default y if !SPARC32 && !SPARC64 && !FBCON_FONTS - help - This is the "high resolution" font for the VGA frame buffer (the one - provided by the VGA text console 80x25 mode. - - If unsure, say Y. - -config FONT_6x11 - bool "Mac console 6x11 font (not supported by all drivers)" if FBCON_FONTS - depends on FB && !FBCON_FONTWIDTH8_ONLY - default y if !SPARC32 && !SPARC64 && !FBCON_FONTS && MAC - help - Small console font with Macintosh-style high-half glyphs. Some Mac - framebuffer drivers don't support this one at all. - -config FONT_PEARL_8x8 - bool "Pearl (old m68k) console 8x8 font" if FBCON_FONTS - depends on FB - default y if !SPARC32 && !SPARC64 && !FBCON_FONTS && AMIGA - help - Small console font with PC-style control-character and high-half - glyphs. - -config FONT_ACORN_8x8 - bool "Acorn console 8x8 font" if FBCON_FONTS - depends on FB - default y if !SPARC32 && !SPARC64 && !FBCON_FONTS && ARM && ARCH_ACORN - help - Small console font with PC-style control characters and high-half - glyphs. - -config FONT_MINI_4x6 - bool "Mini 4x6 font" - depends on !SPARC32 && !SPARC64 && FBCON_FONTS +source "drivers/video/console/Kconfig" endmenu diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9eb41edb4a49..21d7f402a86c 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -5,33 +5,15 @@ # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. -export-objs := fbmem.o fbcmap.o fbcon.o fbmon.o modedb.o \ - fbcon-afb.o fbcon-ilbm.o fbcon-accel.o cyber2000fb.o \ - fbcon-iplan2p2.o fbcon-iplan2p4.o fbgen.o \ - fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \ - fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \ - fbcon-cfb8.o fbcon-mfb.o fbcon-hga.o +export-objs := fbmem.o fbcmap.o fbmon.o modedb.o softcursor.o cfbfillrect.o \ + cfbcopyarea.o cfbimgblt.o cyber2000fb.o vgastate.o # Each configuration option enables a list of files. -obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o -obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o -obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o -obj-$(CONFIG_STI_CONSOLE) += sticon.o sticon-bmode.o sticore.o -obj-$(CONFIG_VGA_CONSOLE) += vgacon.o -obj-$(CONFIG_MDA_CONSOLE) += mdacon.o - -obj-$(CONFIG_FONT_SUN8x16) += font_sun8x16.o -obj-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o -obj-$(CONFIG_FONT_8x8) += font_8x8.o -obj-$(CONFIG_FONT_8x16) += font_8x16.o -obj-$(CONFIG_FONT_6x11) += font_6x11.o -obj-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o -obj-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o -obj-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.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 fbcon.o fonts.o fbgen.o +obj-$(CONFIG_FB) += fbmem.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 @@ -44,10 +26,10 @@ obj-$(CONFIG_FB_PM3) += pm3fb.o 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 +obj-$(CONFIG_FB_ATY128) += aty128fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_RADEON) += radeonfb.o obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_IGA) += igafb.o +obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblit.o obj-$(CONFIG_FB_CONTROL) += controlfb.o obj-$(CONFIG_FB_PLATINUM) += platinumfb.o obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o @@ -68,7 +50,8 @@ obj-$(CONFIG_FB_TRIDENT) += tridentfb.o obj-$(CONFIG_FB_S3TRIO) += S3triofb.o obj-$(CONFIG_FB_TGA) += tgafb.o obj-$(CONFIG_FB_VESA) += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_VGA16) += vga16fb.o fbcon-vga-planes.o +obj-$(CONFIG_FB_VGA16) += vga16fb.o cfbfillrect.o cfbcopyarea.o \ + cfbimgblt.o vgastate.o obj-$(CONFIG_FB_VIRGE) += virgefb.o obj-$(CONFIG_FB_G364) += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_FM2) += fm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o @@ -80,20 +63,21 @@ 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 sticore.o +obj-$(CONFIG_FB_STI) += stifb.o console/sticore.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 obj-$(CONFIG_FB_TX3912) += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_MATROX) += matrox/ -obj-$(CONFIG_FB_RIVA) += riva/ +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_SUN3) += sun3fb.o obj-$(CONFIG_FB_BWTWO) += bwtwofb.o -obj-$(CONFIG_FB_HGA) += hgafb.o +obj-$(CONFIG_FB_HGA) += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o @@ -101,24 +85,6 @@ obj-$(CONFIG_FB_E1355) += epson1355fb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o -# Generic Low Level Drivers - -obj-$(CONFIG_FBCON_AFB) += fbcon-afb.o -obj-$(CONFIG_FBCON_CFB2) += fbcon-cfb2.o -obj-$(CONFIG_FBCON_CFB4) += fbcon-cfb4.o -obj-$(CONFIG_FBCON_CFB8) += fbcon-cfb8.o -obj-$(CONFIG_FBCON_CFB16) += fbcon-cfb16.o -obj-$(CONFIG_FBCON_CFB24) += fbcon-cfb24.o -obj-$(CONFIG_FBCON_CFB32) += fbcon-cfb32.o -obj-$(CONFIG_FBCON_ILBM) += fbcon-ilbm.o -obj-$(CONFIG_FBCON_IPLAN2P2) += fbcon-iplan2p2.o -obj-$(CONFIG_FBCON_IPLAN2P4) += fbcon-iplan2p4.o -obj-$(CONFIG_FBCON_IPLAN2P8) += fbcon-iplan2p8.o -obj-$(CONFIG_FBCON_MFB) += fbcon-mfb.o -obj-$(CONFIG_FBCON_HGA) += fbcon-hga.o -obj-$(CONFIG_FBCON_STI) += fbcon-sti.o -obj-$(CONFIG_FBCON_ACCEL) += fbcon-accel.o - # Files generated that shall be removed upon make clean clean-files := promcon_tbl.c diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c index 0a7ea6ec1f79..07863a5ee58b 100644 --- a/drivers/video/S3triofb.c +++ b/drivers/video/S3triofb.c @@ -542,7 +542,7 @@ static void __init s3triofb_of_init(struct device_node *dp) return; printk("fb%d: S3 Trio frame buffer device on %s\n", - GET_FB_IDX(fb_info.node), dp->full_name); + minor(fb_info.node), dp->full_name); } diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 357ce2571f66..a98aa38199b8 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1771,7 +1771,7 @@ default_chipset: } printk("fb%d: %s frame buffer device, using %ldK of video memory\n", - GET_FB_IDX(fb_info.node), fb_info.modename, + minor(fb_info.node), fb_info.modename, videomemorysize>>10); return 0; diff --git a/drivers/video/anakinfb.c b/drivers/video/anakinfb.c index 340a90c23efe..90c47bb310a4 100644 --- a/drivers/video/anakinfb.c +++ b/drivers/video/anakinfb.c @@ -20,35 +20,32 @@ #include <asm/io.h> -#include <video/fbcon.h> - -static u32 colreg[16]; +static u32 colreg[17]; static struct fb_info fb_info; -static struct display display; static struct fb_var_screeninfo anakinfb_var = { - .xres = 400, - .yres = 234, - .xres_virtual = 400, - .yres_virtual = 234, - .bits_per_pixel =16, - .red = { 11, 5, 0 }, - .green = { 5, 6, 0 }, - .blue = { 0, 5, 0 }, - .activate FB_ACTIVATE_NOW, - .height -1, - .width -1, - .vmode FB_VMODE_NONINTERLACED, + .xres = 400, + .yres = 234, + .xres_virtual = 400, + .yres_virtual = 234, + .bits_per_pixel = 16, + .red = { 11, 5, 0 }, + .green = { 5, 6, 0 }, + .blue = { 0, 5, 0 }, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .vmode = FB_VMODE_NONINTERLACED, }; static struct fb_fix_screeninfo anakinfb_fix = { - .id = "AnakinFB", - .smem_start = VGA_START, - .smem_len = VGA_SIZE, - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_TRUECOLOR, - .line_length = 400*2, - .accel = FB_ACCEL_NONE, + .id = "AnakinFB", + .smem_start = VGA_START, + .smem_len = VGA_SIZE, + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .line_length = 400*2, + .accel = FB_ACCEL_NONE, }; static int @@ -58,40 +55,30 @@ anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, if (regno > 15) return 1; - colreg[regno] = (red & 0xf800) | (green & 0xfc00 >> 5) | - (blue & 0xf800 >> 11); + ((u16 *)(info->pseudo_palette))[regno] = (red & 0xf800) | (green & 0xfc00 >> 5) | (blue & 0xf800 >> 11); return 0; } static struct fb_ops anakinfb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = anakinfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; int __init anakinfb_init(void) { memset(&fb_info, 0, sizeof(struct fb_info)); - memset(&display, 0, sizeof(struct display)); - strcpy(fb_info.modename, anakinfb_fix.id); fb_info.node = NODEV; - fb_info.currcon = -1; fb_info.flags = FBINFO_FLAG_DEFAULT; fb_info.fbops = &anakinfb_ops; fb_info.var = anakinfb_var; fb_info.fix = anakinfb_fix; - fb_info.disp = &display; - strcpy(fb_info.fontname, "VGA8x16"); - fb_info.changevar = NULL; - fb_info.switch_con = gen_switch_con; - fb_info.updatevar = gen_update_var; + fb_info.psuedo_palette = colreg; if (!(request_mem_region(VGA_START, VGA_SIZE, "vga"))) return -ENOMEM; if (fb_info.screen_base = ioremap(VGA_START, VGA_SIZE)) { @@ -100,10 +87,9 @@ anakinfb_init(void) } fb_alloc_cmap(&fb_info.cmap, 16, 0); - gen_set_disp(-1, &fb_info); if (register_framebuffer(&fb_info) < 0) { - iounmap(display.screen_base); + iounmap(fb_info.screen_base); release_mem_region(VGA_START, VGA_SIZE); return -EINVAL; } diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 33ea709cefa1..fd55dbcabf6f 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -2816,7 +2816,7 @@ int __init atafb_init(void) printk(" virtual %dx%d\n", disp.var.xres_virtual, disp.var.yres_virtual); printk("fb%d: %s frame buffer device, using %dK of video memory\n", - GET_FB_IDX(fb_info.node), fb_info.modename, screen_len>>10); + minor(fb_info.node), fb_info.modename, screen_len>>10); /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index 8342386c4a47..27a6a4f2f98a 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h @@ -3,8 +3,6 @@ */ #include <linux/config.h> -#include <video/fbcon.h> - /* * Elements of the hardware specific atyfb_par structure */ @@ -59,19 +57,9 @@ union aty_pll { */ struct aty_cursor { - int enable; - int on; - int vbl_cnt; - int blink_rate; - u32 offset; - struct { - u16 x, y; - } pos, hot, size; - u32 color[2]; u8 bits[8][64]; u8 mask[8][64]; u8 *ram; - struct timer_list *timer; }; struct atyfb_par { @@ -93,8 +81,6 @@ struct atyfb_par { u8 blitter_may_be_busy; #ifdef __sparc__ struct pci_mmap_map *mmap_map; - int consolecnt; - int vtconsole; u8 mmaped; int open; #endif @@ -251,11 +237,9 @@ extern void aty_calc_pll_ct(const struct fb_info *info, */ extern struct aty_cursor *aty_init_cursor(struct fb_info *info); -extern void atyfb_cursor(struct display *p, int mode, int x, int y); +extern int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor); extern void aty_set_cursor_color(struct fb_info *info); extern void aty_set_cursor_shape(struct fb_info *info); -extern int atyfb_set_font(struct display *d, int width, int height); - /* * Hardware acceleration diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index d7e50db324ec..0f4bc997dc24 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -65,9 +65,6 @@ #include <asm/io.h> #include <asm/uaccess.h> -#include <video/fbcon.h> -#include "../fbcon-accel.h" - #include <video/mach64.h> #include "atyfb.h" @@ -149,11 +146,11 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, static int atyfb_set_par(struct fb_info *info); static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); -static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, +static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static int atyfb_blank(int blank, struct fb_info *info); static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con, struct fb_info *info); + u_long arg, struct fb_info *info); extern void atyfb_fillrect(struct fb_info *info, struct fb_fillrect *rect); extern void atyfb_copyarea(struct fb_info *info, struct fb_copyarea *area); extern void atyfb_imageblit(struct fb_info *info, struct fb_image *image); @@ -161,7 +158,7 @@ extern void atyfb_imageblit(struct fb_info *info, struct fb_image *image); static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); #endif -static int atyfb_rasterimg(struct fb_info *info, int start); +static int atyfb_sync(struct fb_info *info); /* * Internal routines @@ -198,21 +195,12 @@ int atyfb_init(void); int atyfb_setup(char *); #endif -int gen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) -{ - *var = info->var; - return 0; -} - static struct fb_ops atyfb_ops = { .owner = THIS_MODULE, .fb_open = atyfb_open, .fb_release = atyfb_release, - .fb_set_var = gen_set_var, .fb_check_var = atyfb_check_var, .fb_set_par = atyfb_set_par, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = atyfb_setcolreg, .fb_pan_display = atyfb_pan_display, .fb_blank = atyfb_blank, @@ -220,13 +208,13 @@ static struct fb_ops atyfb_ops = { .fb_fillrect = atyfb_fillrect, .fb_copyarea = atyfb_copyarea, .fb_imageblit = atyfb_imageblit, + .fb_cursor = soft_cursor, #ifdef __sparc__ .fb_mmap = atyfb_mmap, #endif - .fb_rasterimg = atyfb_rasterimg, + .fb_sync = atyfb_sync, }; -static char fontname[40] __initdata = { 0 }; static char curblink __initdata = 1; static char noaccel __initdata = 0; static u32 default_vram __initdata = 0; @@ -944,9 +932,6 @@ static int atyfb_open(struct fb_info *info, int user) if (user) { par->open++; par->mmaped = 0; - par->vtconsole = -1; - } else { - par->consolecnt++; } #endif return (0); @@ -973,9 +958,6 @@ static int atyfb_release(struct fb_info *info, int user) int was_mmaped = par->mmaped; par->mmaped = 0; - if (par->vtconsole != -1) - vt_cons[par->vtconsole]->vc_mode = KD_TEXT; - par->vtconsole = -1; if (was_mmaped) { struct fb_var_screeninfo var; @@ -1005,9 +987,7 @@ static int atyfb_release(struct fb_info *info, int user) gen_set_var(&var, -1, info); } } - } else { - par->consolecnt--; - } + } #endif return (0); } @@ -1018,7 +998,7 @@ static int atyfb_release(struct fb_info *info, int user) * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, +static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; @@ -1060,7 +1040,7 @@ struct atyclk { #endif static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con, struct fb_info *info) + u_long arg, struct fb_info *info) { #if defined(__sparc__) || (defined(DEBUG) && defined(CONFIG_FB_ATY_CT)) struct atyfb_par *par = (struct atyfb_par *) info->par; @@ -1150,7 +1130,7 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, return 0; } -static int atyfb_rasterimg(struct fb_info *info, int start) +static int atyfb_sync(struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; @@ -1228,18 +1208,8 @@ static int atyfb_mmap(struct fb_info *info, struct file *file, vma->vm_flags |= VM_IO; - if (!par->mmaped) { - int lastconsole = 0; - - if (info->display_fg) - lastconsole = info->display_fg->vc_num; + if (!par->mmaped) par->mmaped = 1; - if (par->consolecnt - && fb_display[lastconsole].fb_info == info) { - par->vtconsole = lastconsole; - vt_cons[lastconsole]->vc_mode = KD_GRAPHICS; - } - } return 0; } @@ -1562,7 +1532,6 @@ static int __init aty_init(struct fb_info *info, const char *name) const char *chipname = NULL, *ramname = NULL, *xtal; int j, pll, mclk, gtb_memsize; struct fb_var_screeninfo var; - struct display *disp; u32 chip_id, i; u16 type; u8 rev; @@ -1843,18 +1812,9 @@ static int __init aty_init(struct fb_info *info, const char *name) fb_memset((void *) info->screen_base, 0, info->fix.smem_len); - disp = info->disp; - - strcpy(info->modename, info->fix.id); info->node = NODEV; info->fbops = &atyfb_ops; - info->disp = disp; info->pseudo_palette = pseudo_palette; - info->currcon = -1; - strcpy(info->fontname, fontname); - info->changevar = NULL; - info->switch_con = gen_switch; - info->updatevar = gen_update_var; info->flags = FBINFO_FLAG_DEFAULT; #ifdef CONFIG_PMAC_BACKLIGHT @@ -1965,29 +1925,20 @@ static int __init aty_init(struct fb_info *info, const char *name) #endif #ifdef CONFIG_FB_ATY_CT - if (curblink && M64_HAS(INTEGRATED)) { + if (curblink && M64_HAS(INTEGRATED)) par->cursor = aty_init_cursor(info); - if (par->cursor) { - /* - disp->dispsw.cursor = atyfb_cursor; - disp->dispsw.set_font = atyfb_set_font; - */ - } - } #endif /* CONFIG_FB_ATY_CT */ info->var = var; fb_alloc_cmap(&info->cmap, 256, 0); - gen_set_var(&var, -1, info); - if (register_framebuffer(info) < 0) return 0; fb_list = info; printk("fb%d: %s frame buffer device on %s\n", - GET_FB_IDX(info->node), info->fix.id, name); + minor(info->node), info->fix.id, name); return 1; } @@ -2028,16 +1979,13 @@ int __init atyfb_init(void) continue; info = - kmalloc(sizeof(struct fb_info) + - sizeof(struct display), GFP_ATOMIC); + kmalloc(sizeof(struct fb_info), GFP_ATOMIC); if (!info) { printk ("atyfb_init: can't alloc fb_info\n"); return -ENXIO; } - memset(info, 0, - sizeof(struct fb_info) + - sizeof(struct display)); + memset(info, 0, sizeof(struct fb_info)); default_par = kmalloc(sizeof(struct atyfb_par), GFP_ATOMIC); @@ -2049,7 +1997,6 @@ int __init atyfb_init(void) } memset(default_par, 0, sizeof(struct atyfb_par)); - info->disp = (struct display *) (info + 1); info->fix = atyfb_fix; info->par = default_par; @@ -2460,17 +2407,7 @@ int __init atyfb_setup(char *options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { - if (!strncmp(this_opt, "font:", 5)) { - char *p; - int i; - - p = this_opt + 5; - for (i = 0; i < sizeof(fontname) - 1; i++) - if (!*p || *p == ' ' || *p == ',') - break; - memcpy(fontname, this_opt + 5, i); - fontname[i] = 0; - } else if (!strncmp(this_opt, "noblink", 7)) { + if (!strncmp(this_opt, "noblink", 7)) { curblink = 0; } else if (!strncmp(this_opt, "noaccel", 7)) { noaccel = 1; @@ -2694,12 +2631,8 @@ void cleanup_module(void) iounmap(info->cursor->ram); #endif #endif - - if (info->cursor) { - if (info->cursor->timer) - kfree(info->cursor->timer); + if (info->cursor) kfree(info->cursor); - } #ifdef __sparc__ if (par->mmap_map) kfree(par->mmap_map); diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c index 3d83d8e175d7..921b7dc0200b 100644 --- a/drivers/video/aty/mach64_ct.c +++ b/drivers/video/aty/mach64_ct.c @@ -7,8 +7,6 @@ #include <asm/io.h> -#include <video/fbcon.h> - #include <video/mach64.h> #include "atyfb.h" diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c index b67e6f90967b..985090bf8e5b 100644 --- a/drivers/video/aty/mach64_cursor.c +++ b/drivers/video/aty/mach64_cursor.c @@ -11,8 +11,6 @@ #include <asm/io.h> #include <asm/uaccess.h> -#include <video/fbcon.h> - #ifdef __sparc__ #include <asm/pbm.h> #include <asm/fbio.h> @@ -21,11 +19,6 @@ #include <video/mach64.h> #include "atyfb.h" - -#define DEFAULT_CURSOR_BLINK_RATE (20) -#define CURSOR_DRAW_DELAY (2) - - /* * Hardware Cursor support. */ @@ -51,50 +44,48 @@ void aty_set_cursor_color(struct fb_info *info) const u8 *red = cursor_color_map; const u8 *green = cursor_color_map; const u8 *blue = cursor_color_map; - int i; + u32 fg_color, bg_color; if (!c) return; #ifdef __sparc__ - if (par->mmaped && (!info->display_fg - || info->display_fg->vc_num == - par->vtconsole)) + if (par->mmaped) return; #endif + fg_color = (u32) red[0] << 24; + fg_color |= (u32) green[0] << 16; + fg_color |= (u32) blue[0] << 8; + fg_color |= (u32) pixel[0]; - for (i = 0; i < 2; i++) { - c->color[i] = (u32) red[i] << 24; - c->color[i] |= (u32) green[i] << 16; - c->color[i] |= (u32) blue[i] << 8; - c->color[i] |= (u32) pixel[i]; - } + bg_color = (u32) red[1] << 24; + bg_color |= (u32) green[1] << 16; + bg_color |= (u32) blue[1] << 8; + bg_color |= (u32) pixel[1]; wait_for_fifo(2, par); - aty_st_le32(CUR_CLR0, c->color[0], par); - aty_st_le32(CUR_CLR1, c->color[1], par); + aty_st_le32(CUR_CLR0, fg_color, par); + aty_st_le32(CUR_CLR1, bg_color, par); } void aty_set_cursor_shape(struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; + struct fb_cursor *cursor = &info->cursor; struct aty_cursor *c = par->cursor; u8 *ram, m, b; int x, y; if (!c) return; - #ifdef __sparc__ - if (par->mmaped && (!info->display_fg - || info->display_fg->vc_num == - par->vtconsole)) + if (par->mmaped) return; #endif ram = c->ram; - for (y = 0; y < c->size.y; y++) { - for (x = 0; x < c->size.x >> 2; x++) { + for (y = 0; y < cursor->image.height; y++) { + for (x = 0; x < cursor->image.width >> 2; x++) { m = c->mask[x][y]; b = c->bits[x][y]; fb_writeb(cursor_mask_lookup[m >> 4] | @@ -108,12 +99,13 @@ void aty_set_cursor_shape(struct fb_info *info) fb_writeb(0xaa, ram++); } } - fb_memset(ram, 0xaa, (64 - c->size.y) * 16); + fb_memset(ram, 0xaa, (64 - cursor->image.height) * 16); } -static void aty_set_cursor(struct fb_info *info, int on) +static void aty_set_cursor(struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; + struct fb_cursor *cursor = &info->cursor; struct aty_cursor *c = par->cursor; u16 xoff, yoff; int x, y; @@ -122,14 +114,12 @@ static void aty_set_cursor(struct fb_info *info, int on) return; #ifdef __sparc__ - if (par->mmaped && (!info->display_fg - || info->display_fg->vc_num == - par->vtconsole)) + if (par->mmaped) return; #endif - if (on) { - x = c->pos.x - c->hot.x - info->var.xoffset; + if (cursor->enable) { + x = cursor->image.dx - cursor->hot.x - info->var.xoffset; if (x < 0) { xoff = -x; x = 0; @@ -137,7 +127,7 @@ static void aty_set_cursor(struct fb_info *info, int on) xoff = 0; } - y = c->pos.y - c->hot.y - info->var.yoffset; + y = cursor->image.dy - cursor->hot.y - info->var.yoffset; if (y < 0) { yoff = -y; y = 0; @@ -146,10 +136,10 @@ static void aty_set_cursor(struct fb_info *info, int on) } wait_for_fifo(4, par); - aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), + aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par); aty_st_le32(CUR_HORZ_VERT_OFF, - ((u32) (64 - c->size.y + yoff) << 16) | xoff, + ((u32) (64 - cursor->image.height + yoff) << 16) | xoff, par); aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par); aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) @@ -164,70 +154,25 @@ static void aty_set_cursor(struct fb_info *info, int on) wait_for_idle(par); } -static void aty_cursor_timer_handler(unsigned long dev_addr) +int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor) { - struct fb_info *info = (struct fb_info *) dev_addr; - struct atyfb_par *par = (struct atyfb_par *) info->par; - - if (!par->cursor) - return; - - if (!par->cursor->enable) - goto out; - - if (par->cursor->vbl_cnt && --par->cursor->vbl_cnt == 0) { - par->cursor->on ^= 1; - aty_set_cursor(info, par->cursor->on); - par->cursor->vbl_cnt = par->cursor->blink_rate; - } - - out: - par->cursor->timer->expires = jiffies + (HZ / 50); - add_timer(par->cursor->timer); -} - -void atyfb_cursor(struct display *p, int mode, int x, int y) -{ - struct fb_info *info = p->fb_info; struct atyfb_par *par = (struct atyfb_par *) info->par; struct aty_cursor *c = par->cursor; if (!c) - return; + return -1; #ifdef __sparc__ - if (par->mmaped && (!info->display_fg - || info->display_fg->vc_num == - par->vtconsole)) + if (par->mmaped) return; #endif - x *= fontwidth(p); - y *= fontheight(p); - if (c->pos.x == x && c->pos.y == y - && (mode == CM_ERASE) == !c->enable) - return; + aty_set_cursor(info); + cursor->image.dx = info->cursor.image.dx; + cursor->image.dy = info->cursor.image.dy; - c->enable = 0; - if (c->on) - aty_set_cursor(info, 0); - c->pos.x = x; - c->pos.y = y; - - switch (mode) { - case CM_ERASE: - c->on = 0; - break; - - case CM_DRAW: - case CM_MOVE: - if (c->on) - aty_set_cursor(info, 1); - else - c->vbl_cnt = CURSOR_DRAW_DELAY; - c->enable = 1; - break; - } + aty_set_cursor(info); + return 0; } struct aty_cursor *__init aty_init_cursor(struct fb_info *info) @@ -240,47 +185,31 @@ struct aty_cursor *__init aty_init_cursor(struct fb_info *info) return 0; memset(cursor, 0, sizeof(*cursor)); - cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL); - if (!cursor->timer) { - kfree(cursor); - return 0; - } - memset(cursor->timer, 0, sizeof(*cursor->timer)); - - cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE; info->fix.smem_len -= PAGE_SIZE; - cursor->offset = info->fix.smem_len; #ifdef __sparc__ - addr = (unsigned long) info->screen_base - 0x800000 + cursor->offset; + addr = info->screen_base - 0x800000 + info->fix.smem_len; cursor->ram = (u8 *) addr; #else #ifdef __BIG_ENDIAN - addr = info->fix.smem_start - 0x800000 + cursor->offset; + addr = info->fix.smem_start - 0x800000 + info->fix.smem_len; cursor->ram = (u8 *) ioremap(addr, 1024); #else - addr = (unsigned long) info->screen_base + cursor->offset; + addr = (unsigned long) info->screen_base + info->fix.smem_len; cursor->ram = (u8 *) addr; #endif #endif - if (!cursor->ram) { kfree(cursor); return NULL; } - - init_timer(cursor->timer); - cursor->timer->expires = jiffies + (HZ / 50); - cursor->timer->data = (unsigned long) info; - cursor->timer->function = aty_cursor_timer_handler; - add_timer(cursor->timer); return cursor; } -int atyfb_set_font(struct display *d, int width, int height) +int atyfb_set_font(struct fb_info *info, int width, int height) { - struct fb_info *info = d->fb_info; struct atyfb_par *par = (struct atyfb_par *) info->par; + struct fb_cursor *cursor = &info->cursor; struct aty_cursor *c = par->cursor; int i, j; @@ -290,10 +219,10 @@ int atyfb_set_font(struct display *d, int width, int height) height = 16; } - c->hot.x = 0; - c->hot.y = 0; - c->size.x = width; - c->size.y = height; + cursor->hot.x = 0; + cursor->hot.y = 0; + cursor->image.width = width; + cursor->image.height = height; memset(c->bits, 0xff, sizeof(c->bits)); memset(c->mask, 0, sizeof(c->mask)); diff --git a/drivers/video/aty/mach64_gx.c b/drivers/video/aty/mach64_gx.c index d11e58454b29..f85f0a052784 100644 --- a/drivers/video/aty/mach64_gx.c +++ b/drivers/video/aty/mach64_gx.c @@ -9,8 +9,6 @@ #include <asm/io.h> -#include <video/fbcon.h> - #include <video/mach64.h> #include "atyfb.h" diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c index ae43cc8ea62e..69f2d8d618c3 100644 --- a/drivers/video/aty128fb.c +++ b/drivers/video/aty128fb.c @@ -7,13 +7,26 @@ * Ani Joshi / Jeff Garzik * - Code cleanup * + * Michel Dänzer <michdaen@iiic.ethz.ch> + * - 15/16 bit cleanup + * - fix panning + * + * Benjamin Herrenschmidt + * - pmac-specific PM stuff + * * Andreas Hundt <andi@convergence.de> * - FB_ACTIVATE fixes * + * Paul Mackerras <paulus@samba.org> + * - Convert to new framebuffer API, + * fix colormap setting at 16 bits/pixel (565) + * + * Paul Mundt + * - PCI hotplug + * * Based off of Geert's atyfb.c and vfb.c. * * TODO: - * - panning * - monitor sensing (DDC) * - virtual display * - other platform support (only ppc/x86 supported) @@ -49,7 +62,7 @@ #include <linux/ioport.h> #include <asm/io.h> -#ifdef CONFIG_PPC +#ifdef CONFIG_ALL_PPC #include <asm/prom.h> #include <asm/pci-bridge.h> #include <video/macmodes.h> @@ -71,12 +84,6 @@ #include <asm/btext.h> #endif /* CONFIG_BOOTX_TEXT */ -#include <video/fbcon.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-cfb24.h> -#include <video/fbcon-cfb32.h> - #ifdef CONFIG_MTRR #include <asm/mtrr.h> #endif @@ -92,27 +99,27 @@ #define DBG(fmt, args...) #endif -#ifndef CONFIG_PPC +#ifndef CONFIG_ALL_PPC /* default mode */ static struct fb_var_screeninfo default_var __initdata = { - /* 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) */ + 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 }; -#else /* CONFIG_PPC */ +#else /* CONFIG_ALL_PPC */ /* default to 1024x768 at 75Hz on PPC - this will work * on the iMac, the usual 640x480 @ 60Hz doesn't. */ static struct fb_var_screeninfo default_var = { - /* 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, 160, 32, 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) */ + 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, 160, 32, 28, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }; -#endif /* CONFIG_PPC */ +#endif /* CONFIG_ALL_PPC */ /* default modedb mode */ /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */ @@ -131,13 +138,6 @@ static struct fb_videomode defaultmode __initdata = { .vmode = FB_VMODE_NONINTERLACED }; -/* struct to hold chip description information */ -struct aty128_chip_info { - const char *name; - unsigned short device; - int chip_gen; -}; - /* Chip generations */ enum { rage_128, @@ -145,20 +145,46 @@ enum { rage_M3 }; +/* + * PCI driver prototypes + */ +static int aty128_probe(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void aty128_remove(struct pci_dev *pdev); + /* supported Rage128 chipsets */ -static struct aty128_chip_info aty128_pci_probe_list[] __initdata = -{ - {"Rage128 RE (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RE, rage_128}, - {"Rage128 RF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RF, rage_128}, - {"Rage128 RK (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RK, rage_128}, - {"Rage128 RL (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RL, rage_128}, - {"Rage128 Pro PF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_PF, rage_128_pro}, - {"Rage128 Pro PR (PCI)", PCI_DEVICE_ID_ATI_RAGE128_PR, rage_128_pro}, - {"Rage128 Pro TR (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U3, rage_128_pro}, - {"Rage Mobility M3 (PCI)", PCI_DEVICE_ID_ATI_RAGE128_LE, rage_M3}, - {"Rage Mobility M3 (AGP)", PCI_DEVICE_ID_ATI_RAGE128_LF, rage_M3}, - {NULL, 0, rage_128} - }; +static struct pci_device_id aty128_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RF, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RK, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PF, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PR, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_U3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_U1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 }, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LF, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, aty128_pci_tbl); + +static struct pci_driver aty128fb_driver = { + name: "aty128fb", + id_table: aty128_pci_tbl, + probe: aty128_probe, + remove: __devexit_p(aty128_remove), +}; /* packed BIOS settings */ #ifndef CONFIG_PPC @@ -190,241 +216,190 @@ typedef struct { /* onboard memory information */ struct aty128_meminfo { - u8 ML; - u8 MB; - u8 Trcd; - u8 Trp; - u8 Twr; - u8 CL; - u8 Tr2w; - u8 LoopLatency; - u8 DspOn; - u8 Rloop; - const char *name; + u8 ML; + u8 MB; + u8 Trcd; + u8 Trp; + u8 Twr; + u8 CL; + u8 Tr2w; + u8 LoopLatency; + u8 DspOn; + u8 Rloop; + const char *name; }; /* various memory configurations */ static const struct aty128_meminfo sdr_128 = - { 4, 4, 3, 3, 1, 3, 1, 16, 30, 16, "128-bit SDR SGRAM (1:1)" }; + { 4, 4, 3, 3, 1, 3, 1, 16, 30, 16, "128-bit SDR SGRAM (1:1)" }; static const struct aty128_meminfo sdr_64 = - { 4, 8, 3, 3, 1, 3, 1, 17, 46, 17, "64-bit SDR SGRAM (1:1)" }; + { 4, 8, 3, 3, 1, 3, 1, 17, 46, 17, "64-bit SDR SGRAM (1:1)" }; static const struct aty128_meminfo sdr_sgram = - { 4, 4, 1, 2, 1, 2, 1, 16, 24, 16, "64-bit SDR SGRAM (2:1)" }; + { 4, 4, 1, 2, 1, 2, 1, 16, 24, 16, "64-bit SDR SGRAM (2:1)" }; static const struct aty128_meminfo ddr_sgram = - { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" }; - -static const char *aty128fb_name = "ATY Rage128"; -static char fontname[40] __initdata = { 0 }; + { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" }; + +static struct fb_fix_screeninfo aty128fb_fix __initdata = { + .id = "ATY Rage128", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .xpanstep = 8, + .ypanstep = 1, + .mmio_len = 0x2000, + .accel = FB_ACCEL_ATI_RAGE128, +}; -static int noaccel __initdata = 0; #ifdef MODULE -static char *font __initdata = NULL; static char *mode __initdata = NULL; #ifdef CONFIG_MTRR static int nomtrr __initdata = 0; -#endif +#endif /* CONFIG_MTRR */ #endif /* MODULE */ static char *mode_option __initdata = NULL; -#ifdef CONFIG_PPC +#ifdef CONFIG_ALL_PPC static int default_vmode __initdata = VMODE_1024_768_60; static int default_cmode __initdata = CMODE_8; #endif +#ifdef CONFIG_PMAC_PBOOK +static int default_crt_on __initdata = 0; +static int default_lcd_on __initdata = 1; +#endif + #ifdef CONFIG_MTRR static int mtrr = 1; #endif /* PLL constants */ struct aty128_constants { - u32 dotclock; - u32 ppll_min; - u32 ppll_max; - u32 ref_divider; - u32 xclk; - u32 fifo_width; - u32 fifo_depth; + u32 dotclock; + u32 ppll_min; + u32 ppll_max; + u32 ref_divider; + u32 xclk; + u32 fifo_width; + u32 fifo_depth; }; 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; - u32 offset, offset_cntl; - u32 xoffset, yoffset; - u32 vxres, vyres; - u32 bpp; + u32 gen_cntl; + u32 ext_cntl; + u32 h_total, h_sync_strt_wid; + u32 v_total, v_sync_strt_wid; + u32 pitch; + u32 offset, offset_cntl; + u32 xoffset, yoffset; + u32 vxres, vyres; + u32 depth, bpp; }; struct aty128_pll { - u32 post_divider; - u32 feedback_divider; - u32 vclk; + u32 post_divider; + u32 feedback_divider; + u32 vclk; }; struct aty128_ddafifo { - u32 dda_config; - u32 dda_on_off; + u32 dda_config; + u32 dda_on_off; }; /* register values for a specific mode */ struct aty128fb_par { - struct aty128_crtc crtc; - struct aty128_pll pll; - struct aty128_ddafifo fifo_reg; - u32 accel_flags; -}; - -struct fb_info_aty128 { - struct fb_info fb_info; - struct fb_info_aty128 *next; - struct aty128_constants constants; /* PLL and others */ - unsigned long regbase_phys; /* physical mmio */ - void *regbase; /* remapped mmio */ - unsigned long frame_buffer_phys; /* physical fb memory */ - void *frame_buffer; /* remaped framebuffer */ - u32 vram_size; /* onboard video ram */ - int chip_gen; - const struct aty128_meminfo *mem; /* onboard mem info */ - struct aty128fb_par default_par, current_par; - struct display disp; - struct { u8 red, green, blue, pad; } palette[256]; - union { -#ifdef FBCON_HAS_CFB16 - u16 cfb16[16]; -#endif -#ifdef FBCON_HAS_CFB24 - u32 cfb24[16]; -#endif -#ifdef FBCON_HAS_CFB32 - u32 cfb32[16]; -#endif - } fbcon_cmap; -#ifdef CONFIG_PCI - struct pci_dev *pdev; -#endif + struct aty128_crtc crtc; + struct aty128_pll pll; + struct aty128_ddafifo fifo_reg; + u32 accel_flags; + struct aty128_constants constants; /* PLL and others */ + void *regbase; /* remapped mmio */ + u32 vram_size; /* onboard video ram */ + int chip_gen; + const struct aty128_meminfo *mem; /* onboard mem info */ #ifdef CONFIG_MTRR - struct { int vram; int vram_valid; } mtrr; + struct { int vram; int vram_valid; } mtrr; +#endif + int blitter_may_be_busy; + int fifo_slots; /* free slots in FIFO (64 max) */ +#ifdef CONFIG_PMAC_PBOOK + unsigned char *save_framebuffer; + int pm_reg; + int crt_on, lcd_on; #endif - int blitter_may_be_busy; - int fifo_slots; /* free slots in FIFO (64 max) */ + unsigned char red[64]; /* see comments in aty128fb_setcolreg */ + unsigned char green[64]; + unsigned char blue[64]; }; -static struct fb_info_aty128 *board_list = NULL; +#ifdef CONFIG_PMAC_PBOOK +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, +}; +#endif #define round_div(n, d) ((n+(d/2))/d) /* * Interface used by the world */ - +int aty128fb_init(void); int aty128fb_setup(char *options); -static int aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *info); -static int aty128fb_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info); -static int aty128fb_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info); -static int aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info); +static int aty128fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info); +static int aty128fb_set_par(struct fb_info *info); static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); -static int aty128fb_pan_display(struct fb_var_screeninfo *var, int con, +static int aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb); static int aty128fb_blank(int blank, struct fb_info *fb); -static int aty128fb_rasterimg(struct fb_info *info, int start); - - /* - * Interface to the low level console driver - */ - -int aty128fb_init(void); -static int aty128fbcon_switch(int con, struct fb_info *fb); +static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, struct fb_info *info); +static int aty128fb_sync(struct fb_info *info); /* * Internal routines */ -static void aty128_encode_fix(struct fb_fix_screeninfo *fix, - struct aty128fb_par *par, - const struct fb_info_aty128 *info); -static void aty128_set_dispsw(struct display *disp, - struct fb_info_aty128 *info, int bpp, int accel); -static int aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp, struct fb_info *info); static int aty128_encode_var(struct fb_var_screeninfo *var, - const struct aty128fb_par *par, - const struct fb_info_aty128 *info); + const struct aty128fb_par *par); static int aty128_decode_var(struct fb_var_screeninfo *var, - struct aty128fb_par *par, - const struct fb_info_aty128 *info); -static int aty128_pci_register(struct pci_dev *pdev, - const struct aty128_chip_info *aci); -static struct fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128 - *board_list, struct fb_info_aty128 *new_node); + struct aty128fb_par *par); #if !defined(CONFIG_PPC) && !defined(__sparc__) -static void __init aty128_get_pllinfo(struct fb_info_aty128 *info, - char *bios_seg); -static char __init *aty128find_ROM(struct fb_info_aty128 *info); -#endif -static void aty128_timings(struct fb_info_aty128 *info); -static void aty128_init_engine(const struct aty128fb_par *par, - struct fb_info_aty128 *info); -static void aty128_reset_engine(const struct fb_info_aty128 *info); -static void aty128_flush_pixel_cache(const struct fb_info_aty128 *info); -static void do_wait_for_fifo(u16 entries, struct fb_info_aty128 *info); -static void wait_for_fifo(u16 entries, struct fb_info_aty128 *info); -static void wait_for_idle(struct fb_info_aty128 *info); -static u32 bpp_to_depth(u32 bpp); - -#ifdef FBCON_HAS_CFB8 -static struct display_switch fbcon_aty128_8; -static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx); -static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, - int yy, int xx); -#endif -#ifdef FBCON_HAS_CFB16 -static struct display_switch fbcon_aty128_16; -static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx); -static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, - int yy, int xx); -#endif -#ifdef FBCON_HAS_CFB24 -static struct display_switch fbcon_aty128_24; -static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx); -static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, - int yy, int xx); -#endif -#ifdef FBCON_HAS_CFB32 -static struct display_switch fbcon_aty128_32; -static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx); -static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, - int yy, int xx); +static void __init aty128_get_pllinfo(struct aty128fb_par *par, + char *bios_seg); +static char __init *aty128find_ROM(void); #endif +static void aty128_timings(struct aty128fb_par *par); +static void aty128_init_engine(struct aty128fb_par *par); +static void aty128_reset_engine(const struct aty128fb_par *par); +static void aty128_flush_pixel_cache(const struct aty128fb_par *par); +static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par); +static void wait_for_fifo(u16 entries, struct aty128fb_par *par); +static void wait_for_idle(struct aty128fb_par *par); +static u32 depth_to_dst(u32 depth); static struct fb_ops aty128fb_ops = { - .owner = THIS_MODULE, - .fb_get_fix = aty128fb_get_fix, - .fb_get_var = aty128fb_get_var, - .fb_set_var = aty128fb_set_var, - .fb_get_cmap = aty128fb_get_cmap, - .fb_set_cmap = gen_set_cmap, - .fb_setcolreg = aty128fb_setcolreg, - .fb_pan_display =aty128fb_pan_display, - .fb_blank = aty128fb_blank, - .fb_rasterimg = aty128fb_rasterimg, + .owner = THIS_MODULE, + .fb_check_var = aty128fb_check_var, + .fb_set_par = aty128fb_set_par, + .fb_setcolreg = aty128fb_setcolreg, + .fb_pan_display = aty128fb_pan_display, + .fb_blank = aty128fb_blank, + .fb_ioctl = aty128fb_ioctl, + .fb_sync = aty128fb_sync, +#if 0 + .fb_fillrect = aty128fb_fillrect, + .fb_copyarea = aty128fb_copyarea, + .fb_imageblit = aty128fb_imageblit, +#else + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +#endif + .fb_cursor = soft_cursor, }; #ifdef CONFIG_PMAC_BACKLIGHT @@ -443,1379 +418,1208 @@ static struct backlight_controller aty128_backlight_controller = { * using the other register aperture. TODO. */ static inline u32 -_aty_ld_le32(volatile unsigned int regindex, - const struct fb_info_aty128 *info) +_aty_ld_le32(volatile unsigned int regindex, const struct aty128fb_par *par) { - u32 val; + u32 val; #if defined(__powerpc__) - asm("lwbrx %0,%1,%2;eieio" : "=r"(val) : "b"(regindex), "r"(info->regbase)); + asm("lwbrx %0,%1,%2;eieio" : "=r"(val) : "b"(regindex), "r"(par->regbase)); #else - val = readl (info->regbase + regindex); + val = readl (par->regbase + regindex); #endif - return val; + return val; } static inline void _aty_st_le32(volatile unsigned int regindex, u32 val, - const struct fb_info_aty128 *info) + const struct aty128fb_par *par) { #if defined(__powerpc__) - asm("stwbrx %0,%1,%2;eieio" : : "r"(val), "b"(regindex), - "r"(info->regbase) : "memory"); + asm("stwbrx %0,%1,%2;eieio" : : "r"(val), "b"(regindex), + "r"(par->regbase) : "memory"); #else - writel (val, info->regbase + regindex); + writel (val, par->regbase + regindex); #endif } static inline u8 -_aty_ld_8(unsigned int regindex, const struct fb_info_aty128 *info) +_aty_ld_8(unsigned int regindex, const struct aty128fb_par *par) { - return readb (info->regbase + regindex); + return readb (par->regbase + regindex); } static inline void -_aty_st_8(unsigned int regindex, u8 val, const struct fb_info_aty128 *info) +_aty_st_8(unsigned int regindex, u8 val, const struct aty128fb_par *par) { - writeb (val, info->regbase + regindex); + writeb (val, par->regbase + regindex); } -#define aty_ld_le32(regindex) _aty_ld_le32(regindex, info) -#define aty_st_le32(regindex, val) _aty_st_le32(regindex, val, info) -#define aty_ld_8(regindex) _aty_ld_8(regindex, info) -#define aty_st_8(regindex, val) _aty_st_8(regindex, val, info) +#define aty_ld_le32(regindex) _aty_ld_le32(regindex, par) +#define aty_st_le32(regindex, val) _aty_st_le32(regindex, val, par) +#define aty_ld_8(regindex) _aty_ld_8(regindex, par) +#define aty_st_8(regindex, val) _aty_st_8(regindex, val, par) /* * Functions to read from/write to the pll registers */ -#define aty_ld_pll(pll_index) _aty_ld_pll(pll_index, info) -#define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val, info) +#define aty_ld_pll(pll_index) _aty_ld_pll(pll_index, par) +#define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val, par) static u32 _aty_ld_pll(unsigned int pll_index, - const struct fb_info_aty128 *info) + const struct aty128fb_par *par) { - aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x1F); - return aty_ld_le32(CLOCK_CNTL_DATA); + aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x3F); + return aty_ld_le32(CLOCK_CNTL_DATA); } static void _aty_st_pll(unsigned int pll_index, u32 val, - const struct fb_info_aty128 *info) + const struct aty128fb_par *par) { - aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x1F) | PLL_WR_EN); - aty_st_le32(CLOCK_CNTL_DATA, val); + aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x3F) | PLL_WR_EN); + aty_st_le32(CLOCK_CNTL_DATA, val); } /* return true when the PLL has completed an atomic update */ static int -aty_pll_readupdate(const struct fb_info_aty128 *info) +aty_pll_readupdate(const struct aty128fb_par *par) { - return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); + return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); } static void -aty_pll_wait_readupdate(const struct fb_info_aty128 *info) +aty_pll_wait_readupdate(const struct aty128fb_par *par) { - unsigned long timeout = jiffies + HZ/100; // should be more than enough - int reset = 1; + unsigned long timeout = jiffies + HZ/100; // should be more than enough + int reset = 1; - while (time_before(jiffies, timeout)) - if (aty_pll_readupdate(info)) { - reset = 0; - break; - } + while (time_before(jiffies, timeout)) + if (aty_pll_readupdate(par)) { + reset = 0; + break; + } - if (reset) /* reset engine?? */ - printk(KERN_DEBUG "aty128fb: PLL write timeout!\n"); + if (reset) /* reset engine?? */ + printk(KERN_DEBUG "aty128fb: PLL write timeout!\n"); } /* tell PLL to update */ static void -aty_pll_writeupdate(const struct fb_info_aty128 *info) +aty_pll_writeupdate(const struct aty128fb_par *par) { - aty_pll_wait_readupdate(info); + aty_pll_wait_readupdate(par); - aty_st_pll(PPLL_REF_DIV, - aty_ld_pll(PPLL_REF_DIV) | PPLL_ATOMIC_UPDATE_W); + aty_st_pll(PPLL_REF_DIV, + aty_ld_pll(PPLL_REF_DIV) | PPLL_ATOMIC_UPDATE_W); } /* write to the scratch register to test r/w functionality */ static int __init -register_test(const struct fb_info_aty128 *info) +register_test(const struct aty128fb_par *par) { - u32 val; - int flag = 0; + u32 val; + int flag = 0; - val = aty_ld_le32(BIOS_0_SCRATCH); + val = aty_ld_le32(BIOS_0_SCRATCH); - aty_st_le32(BIOS_0_SCRATCH, 0x55555555); - if (aty_ld_le32(BIOS_0_SCRATCH) == 0x55555555) { - aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA); + aty_st_le32(BIOS_0_SCRATCH, 0x55555555); + if (aty_ld_le32(BIOS_0_SCRATCH) == 0x55555555) { + aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA); - if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA) - flag = 1; - } + if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA) + flag = 1; + } - aty_st_le32(BIOS_0_SCRATCH, val); // restore value - return flag; + aty_st_le32(BIOS_0_SCRATCH, val); // restore value + return flag; } - /* - * Accelerator engine functions - */ +/* + * Accelerator engine functions + */ static void -do_wait_for_fifo(u16 entries, struct fb_info_aty128 *info) +do_wait_for_fifo(u16 entries, struct aty128fb_par *par) { - int i; - - for (;;) { - for (i = 0; i < 2000000; i++) { - info->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff; - if (info->fifo_slots >= entries) - return; - } - aty128_reset_engine(info); - } + int i; + + for (;;) { + for (i = 0; i < 2000000; i++) { + par->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff; + if (par->fifo_slots >= entries) + return; + } + aty128_reset_engine(par); + } } static void -wait_for_idle(struct fb_info_aty128 *info) +wait_for_idle(struct aty128fb_par *par) { - int i; - - do_wait_for_fifo(64, info); - - for (;;) { - for (i = 0; i < 2000000; i++) { - if (!(aty_ld_le32(GUI_STAT) & (1 << 31))) { - aty128_flush_pixel_cache(info); - info->blitter_may_be_busy = 0; - return; - } - } - aty128_reset_engine(info); - } + int i; + + do_wait_for_fifo(64, par); + + for (;;) { + for (i = 0; i < 2000000; i++) { + if (!(aty_ld_le32(GUI_STAT) & (1 << 31))) { + aty128_flush_pixel_cache(par); + par->blitter_may_be_busy = 0; + return; + } + } + aty128_reset_engine(par); + } } static void -wait_for_fifo(u16 entries, struct fb_info_aty128 *info) +wait_for_fifo(u16 entries, struct aty128fb_par *par) { - if (info->fifo_slots < entries) - do_wait_for_fifo(64, info); - info->fifo_slots -= entries; + if (par->fifo_slots < entries) + do_wait_for_fifo(64, par); + par->fifo_slots -= entries; } static void -aty128_flush_pixel_cache(const struct fb_info_aty128 *info) +aty128_flush_pixel_cache(const struct aty128fb_par *par) { - int i; - u32 tmp; + int i; + u32 tmp; - tmp = aty_ld_le32(PC_NGUI_CTLSTAT); - tmp &= ~(0x00ff); - tmp |= 0x00ff; - aty_st_le32(PC_NGUI_CTLSTAT, tmp); + tmp = aty_ld_le32(PC_NGUI_CTLSTAT); + tmp &= ~(0x00ff); + tmp |= 0x00ff; + aty_st_le32(PC_NGUI_CTLSTAT, tmp); - for (i = 0; i < 2000000; i++) - if (!(aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY)) - break; + for (i = 0; i < 2000000; i++) + if (!(aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY)) + break; } static void -aty128_reset_engine(const struct fb_info_aty128 *info) +aty128_reset_engine(const struct aty128fb_par *par) { - u32 gen_reset_cntl, clock_cntl_index, mclk_cntl; + u32 gen_reset_cntl, clock_cntl_index, mclk_cntl; - aty128_flush_pixel_cache(info); + aty128_flush_pixel_cache(par); - clock_cntl_index = aty_ld_le32(CLOCK_CNTL_INDEX); - mclk_cntl = aty_ld_pll(MCLK_CNTL); + clock_cntl_index = aty_ld_le32(CLOCK_CNTL_INDEX); + mclk_cntl = aty_ld_pll(MCLK_CNTL); - aty_st_pll(MCLK_CNTL, mclk_cntl | 0x00030000); + aty_st_pll(MCLK_CNTL, mclk_cntl | 0x00030000); - gen_reset_cntl = aty_ld_le32(GEN_RESET_CNTL); - aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI); - aty_ld_le32(GEN_RESET_CNTL); - aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl & ~(SOFT_RESET_GUI)); - aty_ld_le32(GEN_RESET_CNTL); + gen_reset_cntl = aty_ld_le32(GEN_RESET_CNTL); + aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI); + aty_ld_le32(GEN_RESET_CNTL); + aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl & ~(SOFT_RESET_GUI)); + aty_ld_le32(GEN_RESET_CNTL); - aty_st_pll(MCLK_CNTL, mclk_cntl); - aty_st_le32(CLOCK_CNTL_INDEX, clock_cntl_index); - aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl); + aty_st_pll(MCLK_CNTL, mclk_cntl); + aty_st_le32(CLOCK_CNTL_INDEX, clock_cntl_index); + aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl); - /* use old pio mode */ - aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4); + /* use old pio mode */ + aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4); - DBG("engine reset"); + DBG("engine reset"); } static void -aty128_init_engine(const struct aty128fb_par *par, - struct fb_info_aty128 *info) +aty128_init_engine(struct aty128fb_par *par) { - u32 pitch_value; + u32 pitch_value; - wait_for_idle(info); + wait_for_idle(par); - /* 3D scaler not spoken here */ - wait_for_fifo(1, info); - aty_st_le32(SCALE_3D_CNTL, 0x00000000); + /* 3D scaler not spoken here */ + wait_for_fifo(1, par); + aty_st_le32(SCALE_3D_CNTL, 0x00000000); - aty128_reset_engine(info); - - pitch_value = par->crtc.pitch; - if (par->crtc.bpp == 24) { - pitch_value = pitch_value * 3; - } - - wait_for_fifo(4, info); - /* setup engine offset registers */ - aty_st_le32(DEFAULT_OFFSET, 0x00000000); - - /* setup engine pitch registers */ - aty_st_le32(DEFAULT_PITCH, pitch_value); - - /* set the default scissor register to max dimensions */ - aty_st_le32(DEFAULT_SC_BOTTOM_RIGHT, (0x1FFF << 16) | 0x1FFF); - - /* set the drawing controls registers */ - aty_st_le32(DP_GUI_MASTER_CNTL, - GMC_SRC_PITCH_OFFSET_DEFAULT | - GMC_DST_PITCH_OFFSET_DEFAULT | - GMC_SRC_CLIP_DEFAULT | - GMC_DST_CLIP_DEFAULT | - GMC_BRUSH_SOLIDCOLOR | - (bpp_to_depth(par->crtc.bpp) << 8) | - GMC_SRC_DSTCOLOR | - GMC_BYTE_ORDER_MSB_TO_LSB | - GMC_DP_CONVERSION_TEMP_6500 | - ROP3_PATCOPY | - GMC_DP_SRC_RECT | - GMC_3D_FCN_EN_CLR | - GMC_DST_CLR_CMP_FCN_CLEAR | - GMC_AUX_CLIP_CLEAR | - GMC_WRITE_MASK_SET); - - wait_for_fifo(8, info); - /* clear the line drawing registers */ - aty_st_le32(DST_BRES_ERR, 0); - aty_st_le32(DST_BRES_INC, 0); - aty_st_le32(DST_BRES_DEC, 0); - - /* set brush color registers */ - aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF); /* white */ - aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000); /* black */ - - /* set source color registers */ - aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF); /* white */ - aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000); /* black */ - - /* default write mask */ - aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF); - - /* Wait for all the writes to be completed before returning */ - wait_for_idle(info); -} + aty128_reset_engine(par); + pitch_value = par->crtc.pitch; + if (par->crtc.bpp == 24) { + pitch_value = pitch_value * 3; + } -/* convert bpp values to their register representation */ + wait_for_fifo(4, par); + /* setup engine offset registers */ + aty_st_le32(DEFAULT_OFFSET, 0x00000000); + + /* setup engine pitch registers */ + aty_st_le32(DEFAULT_PITCH, pitch_value); + + /* set the default scissor register to max dimensions */ + aty_st_le32(DEFAULT_SC_BOTTOM_RIGHT, (0x1FFF << 16) | 0x1FFF); + + /* set the drawing controls registers */ + aty_st_le32(DP_GUI_MASTER_CNTL, + GMC_SRC_PITCH_OFFSET_DEFAULT | + GMC_DST_PITCH_OFFSET_DEFAULT | + GMC_SRC_CLIP_DEFAULT | + GMC_DST_CLIP_DEFAULT | + GMC_BRUSH_SOLIDCOLOR | + (depth_to_dst(par->crtc.depth) << 8) | + GMC_SRC_DSTCOLOR | + GMC_BYTE_ORDER_MSB_TO_LSB | + GMC_DP_CONVERSION_TEMP_6500 | + ROP3_PATCOPY | + GMC_DP_SRC_RECT | + GMC_3D_FCN_EN_CLR | + GMC_DST_CLR_CMP_FCN_CLEAR | + GMC_AUX_CLIP_CLEAR | + GMC_WRITE_MASK_SET); + + wait_for_fifo(8, par); + /* clear the line drawing registers */ + aty_st_le32(DST_BRES_ERR, 0); + aty_st_le32(DST_BRES_INC, 0); + aty_st_le32(DST_BRES_DEC, 0); + + /* set brush color registers */ + aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF); /* white */ + aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000); /* black */ + + /* set source color registers */ + aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF); /* white */ + aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000); /* black */ + + /* default write mask */ + aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF); + + /* Wait for all the writes to be completed before returning */ + wait_for_idle(par); +} + + +/* convert depth values to their register representation */ static u32 -bpp_to_depth(u32 bpp) -{ - if (bpp <= 8) - return DST_8BPP; - else if (bpp <= 16) - return DST_15BPP; - else if (bpp <= 24) - return DST_24BPP; - else if (bpp <= 32) - return DST_32BPP; - - return -EINVAL; +depth_to_dst(u32 depth) +{ + if (depth <= 8) + return DST_8BPP; + else if (depth <= 15) + return DST_15BPP; + else if (depth == 16) + return DST_16BPP; + else if (depth <= 24) + return DST_24BPP; + else if (depth <= 32) + return DST_32BPP; + + return -EINVAL; } - /* +/* * CRTC programming */ /* Program the CRTC registers */ static void aty128_set_crtc(const struct aty128_crtc *crtc, - const struct fb_info_aty128 *info) + const struct aty128fb_par *par) { - aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl); - aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total); - aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid); - aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_total); - aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid); - aty_st_le32(CRTC_PITCH, crtc->pitch); - aty_st_le32(CRTC_OFFSET, crtc->offset); - aty_st_le32(CRTC_OFFSET_CNTL, crtc->offset_cntl); - /* Disable ATOMIC updating. Is this the right place? - * -- BenH: Breaks on my G4 - */ -#if 0 - aty_st_le32(PPLL_CNTL, aty_ld_le32(PPLL_CNTL) & ~(0x00030000)); -#endif + aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl); + aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total); + aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid); + aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_total); + aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid); + aty_st_le32(CRTC_PITCH, crtc->pitch); + aty_st_le32(CRTC_OFFSET, crtc->offset); + aty_st_le32(CRTC_OFFSET_CNTL, crtc->offset_cntl); + /* Disable ATOMIC updating. Is this the right place? */ + aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~(0x00030000)); } static int aty128_var_to_crtc(const struct fb_var_screeninfo *var, - struct aty128_crtc *crtc, - const struct fb_info_aty128 *info) -{ - u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp; - u32 left, right, upper, lower, hslen, vslen, sync, vmode; - u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol; - u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; - u32 depth, bytpp; - u8 hsync_strt_pix[5] = { 0, 0x12, 9, 6, 5 }; - u8 mode_bytpp[7] = { 0, 0, 1, 2, 2, 3, 4 }; - - /* input */ - xres = var->xres; - yres = var->yres; - vxres = var->xres_virtual; - vyres = var->yres_virtual; - xoffset = var->xoffset; - yoffset = var->yoffset; - bpp = var->bits_per_pixel; - left = var->left_margin; - right = var->right_margin; - upper = var->upper_margin; - lower = var->lower_margin; - hslen = var->hsync_len; - vslen = var->vsync_len; - sync = var->sync; - vmode = var->vmode; - - /* check for mode eligibility - * accept only non interlaced modes */ - if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; + struct aty128_crtc *crtc, + const struct aty128fb_par *par) +{ + u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp, dst; + u32 left, right, upper, lower, hslen, vslen, sync, vmode; + u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol; + u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; + u32 depth, bytpp; + u8 mode_bytpp[7] = { 0, 0, 1, 2, 2, 3, 4 }; + + /* input */ + xres = var->xres; + yres = var->yres; + vxres = var->xres_virtual; + vyres = var->yres_virtual; + xoffset = var->xoffset; + yoffset = var->yoffset; + bpp = var->bits_per_pixel; + left = var->left_margin; + right = var->right_margin; + upper = var->upper_margin; + lower = var->lower_margin; + hslen = var->hsync_len; + vslen = var->vsync_len; + sync = var->sync; + vmode = var->vmode; + + if (bpp != 16) + depth = bpp; + else + depth = (var->green.length == 6) ? 16 : 15; - /* convert (and round up) and validate */ - xres = (xres + 7) & ~7; - xoffset = (xoffset + 7) & ~7; + /* check for mode eligibility + * accept only non interlaced modes */ + if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) + return -EINVAL; - if (vxres < xres + xoffset) - vxres = xres + xoffset; + /* convert (and round up) and validate */ + xres = (xres + 7) & ~7; + xoffset = (xoffset + 7) & ~7; - if (vyres < yres + yoffset) - vyres = yres + yoffset; + if (vxres < xres + xoffset) + vxres = xres + xoffset; - /* convert bpp into ATI register depth */ - depth = bpp_to_depth(bpp); + if (vyres < yres + yoffset) + vyres = yres + yoffset; - /* make sure we didn't get an invalid depth */ - if (depth == -EINVAL) { - printk(KERN_ERR "aty128fb: Invalid depth\n"); - return -EINVAL; - } + /* convert depth into ATI register depth */ + dst = depth_to_dst(depth); - /* convert depth to bpp */ - bytpp = mode_bytpp[depth]; + if (dst == -EINVAL) { + printk(KERN_ERR "aty128fb: Invalid depth or RGBA\n"); + return -EINVAL; + } - /* make sure there is enough video ram for the mode */ - if ((u32)(vxres * vyres * bytpp) > info->vram_size) { - printk(KERN_ERR "aty128fb: Not enough memory for mode\n"); - return -EINVAL; - } + /* convert register depth to bytes per pixel */ + bytpp = mode_bytpp[dst]; - h_disp = (xres >> 3) - 1; - h_total = (((xres + right + hslen + left) >> 3) - 1) & 0xFFFFL; + /* make sure there is enough video ram for the mode */ + if ((u32)(vxres * vyres * bytpp) > par->vram_size) { + printk(KERN_ERR "aty128fb: Not enough memory for mode\n"); + return -EINVAL; + } - v_disp = yres - 1; - v_total = (yres + upper + vslen + lower - 1) & 0xFFFFL; + h_disp = (xres >> 3) - 1; + h_total = (((xres + right + hslen + left) >> 3) - 1) & 0xFFFFL; - /* check to make sure h_total and v_total are in range */ - if (((h_total >> 3) - 1) > 0x1ff || (v_total - 1) > 0x7FF) { - printk(KERN_ERR "aty128fb: invalid width ranges\n"); - return -EINVAL; - } + v_disp = yres - 1; + v_total = (yres + upper + vslen + lower - 1) & 0xFFFFL; - h_sync_wid = (hslen + 7) >> 3; - if (h_sync_wid == 0) - h_sync_wid = 1; - else if (h_sync_wid > 0x3f) /* 0x3f = max hwidth */ - h_sync_wid = 0x3f; + /* check to make sure h_total and v_total are in range */ + if (((h_total >> 3) - 1) > 0x1ff || (v_total - 1) > 0x7FF) { + printk(KERN_ERR "aty128fb: invalid width ranges\n"); + return -EINVAL; + } + + h_sync_wid = (hslen + 7) >> 3; + if (h_sync_wid == 0) + h_sync_wid = 1; + else if (h_sync_wid > 0x3f) /* 0x3f = max hwidth */ + h_sync_wid = 0x3f; - h_sync_strt = h_disp + (right >> 3); + h_sync_strt = (h_disp << 3) + right; - v_sync_wid = vslen; - if (v_sync_wid == 0) - v_sync_wid = 1; - else if (v_sync_wid > 0x1f) /* 0x1f = max vwidth */ - v_sync_wid = 0x1f; + v_sync_wid = vslen; + if (v_sync_wid == 0) + v_sync_wid = 1; + else if (v_sync_wid > 0x1f) /* 0x1f = max vwidth */ + v_sync_wid = 0x1f; - v_sync_strt = v_disp + lower; + v_sync_strt = v_disp + lower; - h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; - v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; + h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; + v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; - c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; + c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; - crtc->gen_cntl = 0x3000000L | c_sync | (depth << 8); + crtc->gen_cntl = 0x3000000L | c_sync | (dst << 8); - crtc->h_total = h_total | (h_disp << 16); - crtc->v_total = v_total | (v_disp << 16); + crtc->h_total = h_total | (h_disp << 16); + crtc->v_total = v_total | (v_disp << 16); - crtc->h_sync_strt_wid = hsync_strt_pix[bytpp] | (h_sync_strt << 3) | - (h_sync_wid << 16) | (h_sync_pol << 23); - crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) | + crtc->h_sync_strt_wid = h_sync_strt | (h_sync_wid << 16) | + (h_sync_pol << 23); + crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) | (v_sync_pol << 23); - crtc->pitch = vxres >> 3; + crtc->pitch = vxres >> 3; - crtc->offset = 0; + crtc->offset = 0; - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) - crtc->offset_cntl = 0x00010000; - else - crtc->offset_cntl = 0; + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) + crtc->offset_cntl = 0x00010000; + else + crtc->offset_cntl = 0; - crtc->vxres = vxres; - crtc->vyres = vyres; - crtc->xoffset = xoffset; - crtc->yoffset = yoffset; - crtc->bpp = bpp; + crtc->vxres = vxres; + crtc->vyres = vyres; + crtc->xoffset = xoffset; + crtc->yoffset = yoffset; + crtc->depth = depth; + crtc->bpp = bpp; - return 0; + return 0; } static int -aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var) +aty128_pix_width_to_var(int pix_width, struct fb_var_screeninfo *var) { - /* fill in pixel info */ - switch (pix_width) { - case CRTC_PIX_WIDTH_8BPP: - var->bits_per_pixel = 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 CRTC_PIX_WIDTH_15BPP: - case CRTC_PIX_WIDTH_16BPP: - var->bits_per_pixel = 16; - var->red.offset = 10; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 5; + /* fill in pixel info */ + var->red.msb_right = 0; + var->green.msb_right = 0; var->blue.offset = 0; - var->blue.length = 5; + var->blue.msb_right = 0; var->transp.offset = 0; var->transp.length = 0; - break; - case CRTC_PIX_WIDTH_24BPP: - var->bits_per_pixel = 24; - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - break; - case CRTC_PIX_WIDTH_32BPP: - var->bits_per_pixel = 32; - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 24; - var->transp.length = 8; - break; - default: - printk(KERN_ERR "aty128fb: Invalid pixel width\n"); - return -EINVAL; - } + var->transp.msb_right = 0; + switch (pix_width) { + case CRTC_PIX_WIDTH_8BPP: + var->bits_per_pixel = 8; + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.length = 8; + break; + case CRTC_PIX_WIDTH_15BPP: + var->bits_per_pixel = 16; + var->red.offset = 10; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.length = 5; + break; + case CRTC_PIX_WIDTH_16BPP: + var->bits_per_pixel = 16; + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.length = 5; + break; + case CRTC_PIX_WIDTH_24BPP: + var->bits_per_pixel = 24; + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.length = 8; + break; + case CRTC_PIX_WIDTH_32BPP: + var->bits_per_pixel = 32; + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + break; + default: + printk(KERN_ERR "aty128fb: Invalid pixel width\n"); + return -EINVAL; + } - return 0; + return 0; } static int aty128_crtc_to_var(const struct aty128_crtc *crtc, - struct fb_var_screeninfo *var) + struct fb_var_screeninfo *var) +{ + u32 xres, yres, left, right, upper, lower, hslen, vslen, sync; + u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; + u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; + u32 pix_width; + + /* fun with masking */ + h_total = crtc->h_total & 0x1ff; + h_disp = (crtc->h_total >> 16) & 0xff; + h_sync_strt = (crtc->h_sync_strt_wid >> 3) & 0x1ff; + h_sync_dly = crtc->h_sync_strt_wid & 0x7; + h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x3f; + h_sync_pol = (crtc->h_sync_strt_wid >> 23) & 0x1; + v_total = crtc->v_total & 0x7ff; + v_disp = (crtc->v_total >> 16) & 0x7ff; + v_sync_strt = crtc->v_sync_strt_wid & 0x7ff; + v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f; + v_sync_pol = (crtc->v_sync_strt_wid >> 23) & 0x1; + c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0; + pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK; + + /* do conversions */ + xres = (h_disp + 1) << 3; + yres = v_disp + 1; + left = ((h_total - h_sync_strt - h_sync_wid) << 3) - h_sync_dly; + right = ((h_sync_strt - h_disp) << 3) + h_sync_dly; + hslen = h_sync_wid << 3; + upper = v_total - v_sync_strt - v_sync_wid; + lower = v_sync_strt - v_disp; + vslen = v_sync_wid; + sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) | + (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | + (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); + + aty128_pix_width_to_var(pix_width, var); + + var->xres = xres; + var->yres = yres; + var->xres_virtual = crtc->vxres; + var->yres_virtual = crtc->vyres; + var->xoffset = crtc->xoffset; + var->yoffset = crtc->yoffset; + var->left_margin = left; + var->right_margin = right; + var->upper_margin = upper; + var->lower_margin = lower; + var->hsync_len = hslen; + var->vsync_len = vslen; + var->sync = sync; + var->vmode = FB_VMODE_NONINTERLACED; + + return 0; +} + +#ifdef CONFIG_PMAC_PBOOK +static void +aty128_set_crt_enable(struct aty128fb_par *par, int on) { - u32 xres, yres, left, right, upper, lower, hslen, vslen, sync; - u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; - u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; - u32 pix_width; - - /* fun with masking */ - h_total = crtc->h_total & 0x1ff; - h_disp = (crtc->h_total >> 16) & 0xff; - h_sync_strt = (crtc->h_sync_strt_wid >> 3) & 0x1ff; - h_sync_dly = crtc->h_sync_strt_wid & 0x7; - h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x3f; - h_sync_pol = (crtc->h_sync_strt_wid >> 23) & 0x1; - v_total = crtc->v_total & 0x7ff; - v_disp = (crtc->v_total >> 16) & 0x7ff; - v_sync_strt = crtc->v_sync_strt_wid & 0x7ff; - v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f; - v_sync_pol = (crtc->v_sync_strt_wid >> 23) & 0x1; - c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0; - pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK; - - /* do conversions */ - xres = (h_disp + 1) << 3; - yres = v_disp + 1; - left = ((h_total - h_sync_strt - h_sync_wid) << 3) - h_sync_dly; - right = ((h_sync_strt - h_disp) << 3) + h_sync_dly; - hslen = h_sync_wid << 3; - upper = v_total - v_sync_strt - v_sync_wid; - lower = v_sync_strt - v_disp; - vslen = v_sync_wid; - sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) | - (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | - (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); - - aty128_bpp_to_var(pix_width, var); - - var->xres = xres; - var->yres = yres; - var->xres_virtual = crtc->vxres; - var->yres_virtual = crtc->vyres; - var->xoffset = crtc->xoffset; - var->yoffset = crtc->yoffset; - var->left_margin = left; - var->right_margin = right; - var->upper_margin = upper; - var->lower_margin = lower; - var->hsync_len = hslen; - var->vsync_len = vslen; - var->sync = sync; - var->vmode = FB_VMODE_NONINTERLACED; - - return 0; + if (on) { + aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) | CRT_CRTC_ON); + aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) | DAC_PALETTE2_SNOOP_EN)); + } else + aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) & ~CRT_CRTC_ON); +} + +static void +aty128_set_lcd_enable(struct aty128fb_par *par, int on) +{ + u32 reg; + + if (on) { + reg = aty_ld_le32(LVDS_GEN_CNTL); + reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION; + reg &= ~LVDS_DISPLAY_DIS; + aty_st_le32(LVDS_GEN_CNTL, reg); +#ifdef CONFIG_PMAC_BACKLIGHT + aty128_set_backlight_enable(get_backlight_enable(), + get_backlight_level(), par); +#endif + } else { +#ifdef CONFIG_PMAC_BACKLIGHT + aty128_set_backlight_enable(0, 0, par); +#endif + reg = aty_ld_le32(LVDS_GEN_CNTL); + reg |= LVDS_DISPLAY_DIS; + aty_st_le32(LVDS_GEN_CNTL, reg); + mdelay(100); + reg &= ~(LVDS_ON /*| LVDS_EN*/); + aty_st_le32(LVDS_GEN_CNTL, reg); + } } +#endif static void -aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info) +aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par) { - u32 div3; + u32 div3; - unsigned char post_conv[] = /* register values for post dividers */ + unsigned char post_conv[] = /* register values for post dividers */ { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 }; - /* select PPLL_DIV_3 */ - aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8)); + /* select PPLL_DIV_3 */ + aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8)); - /* reset PLL */ - aty_st_pll(PPLL_CNTL, - aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN); + /* reset PLL */ + aty_st_pll(PPLL_CNTL, + aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN); - /* write the reference divider */ - aty_pll_wait_readupdate(info); - aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider & 0x3ff); - aty_pll_writeupdate(info); + /* write the reference divider */ + aty_pll_wait_readupdate(par); + aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider & 0x3ff); + aty_pll_writeupdate(par); - div3 = aty_ld_pll(PPLL_DIV_3); - div3 &= ~PPLL_FB3_DIV_MASK; - div3 |= pll->feedback_divider; - div3 &= ~PPLL_POST3_DIV_MASK; - div3 |= post_conv[pll->post_divider] << 16; + div3 = aty_ld_pll(PPLL_DIV_3); + div3 &= ~PPLL_FB3_DIV_MASK; + div3 |= pll->feedback_divider; + div3 &= ~PPLL_POST3_DIV_MASK; + div3 |= post_conv[pll->post_divider] << 16; - /* write feedback and post dividers */ - aty_pll_wait_readupdate(info); - aty_st_pll(PPLL_DIV_3, div3); - aty_pll_writeupdate(info); + /* write feedback and post dividers */ + aty_pll_wait_readupdate(par); + aty_st_pll(PPLL_DIV_3, div3); + aty_pll_writeupdate(par); - aty_pll_wait_readupdate(info); - aty_st_pll(HTOTAL_CNTL, 0); /* no horiz crtc adjustment */ - aty_pll_writeupdate(info); + aty_pll_wait_readupdate(par); + aty_st_pll(HTOTAL_CNTL, 0); /* no horiz crtc adjustment */ + aty_pll_writeupdate(par); - /* clear the reset, just in case */ - aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET); + /* clear the reset, just in case */ + aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET); } static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, - const struct fb_info_aty128 *info) -{ - const struct aty128_constants c = info->constants; - unsigned char post_dividers[] = {1,2,4,8,3,6,12}; - u32 output_freq; - u32 vclk; /* in .01 MHz */ - int i; - u32 n, d; - - vclk = 100000000 / period_in_ps; /* convert units to 10 kHz */ - - /* adjust pixel clock if necessary */ - if (vclk > c.ppll_max) - vclk = c.ppll_max; - if (vclk * 12 < c.ppll_min) - vclk = c.ppll_min/12; - - /* now, find an acceptable divider */ - for (i = 0; i < sizeof(post_dividers); i++) { - output_freq = post_dividers[i] * vclk; - if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) - break; - } + const struct aty128fb_par *par) +{ + const struct aty128_constants c = par->constants; + unsigned char post_dividers[] = {1,2,4,8,3,6,12}; + u32 output_freq; + u32 vclk; /* in .01 MHz */ + int i; + u32 n, d; + + vclk = 100000000 / period_in_ps; /* convert units to 10 kHz */ + + /* adjust pixel clock if necessary */ + if (vclk > c.ppll_max) + vclk = c.ppll_max; + if (vclk * 12 < c.ppll_min) + vclk = c.ppll_min/12; + + /* now, find an acceptable divider */ + for (i = 0; i < sizeof(post_dividers); i++) { + output_freq = post_dividers[i] * vclk; + if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) + break; + } - /* calculate feedback divider */ - n = c.ref_divider * output_freq; - d = c.dotclock; + /* calculate feedback divider */ + n = c.ref_divider * output_freq; + d = c.dotclock; - pll->post_divider = post_dividers[i]; - pll->feedback_divider = round_div(n, d); - pll->vclk = vclk; + pll->post_divider = post_dividers[i]; + pll->feedback_divider = round_div(n, d); + pll->vclk = vclk; - DBG("post %d feedback %d vlck %d output %d ref_divider %d " - "vclk_per: %d\n", pll->post_divider, - pll->feedback_divider, vclk, output_freq, - c.ref_divider, period_in_ps); + DBG("post %d feedback %d vlck %d output %d ref_divider %d " + "vclk_per: %d\n", pll->post_divider, + pll->feedback_divider, vclk, output_freq, + c.ref_divider, period_in_ps); - return 0; + return 0; } static int -aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var, - const struct fb_info_aty128 *info) +aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var) { - var->pixclock = 100000000 / pll->vclk; + var->pixclock = 100000000 / pll->vclk; - return 0; + return 0; } static void aty128_set_fifo(const struct aty128_ddafifo *dsp, - const struct fb_info_aty128 *info) + const struct aty128fb_par *par) { - aty_st_le32(DDA_CONFIG, dsp->dda_config); - aty_st_le32(DDA_ON_OFF, dsp->dda_on_off); + aty_st_le32(DDA_CONFIG, dsp->dda_config); + aty_st_le32(DDA_ON_OFF, dsp->dda_on_off); } static int aty128_ddafifo(struct aty128_ddafifo *dsp, - const struct aty128_pll *pll, - u32 bpp, - const struct fb_info_aty128 *info) -{ - const struct aty128_meminfo *m = info->mem; - u32 xclk = info->constants.xclk; - u32 fifo_width = info->constants.fifo_width; - u32 fifo_depth = info->constants.fifo_depth; - s32 x, b, p, ron, roff; - u32 n, d; - - /* 15bpp is really 16bpp */ - if (bpp == 15) - bpp = 16; - - n = xclk * fifo_width; - d = pll->vclk * bpp; - x = round_div(n, d); - - ron = 4 * m->MB + - 3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) + - 2 * m->Trp + - m->Twr + - m->CL + - m->Tr2w + - x; - - DBG("x %x\n", x); - - b = 0; - while (x) { - x >>= 1; - b++; - } - p = b + 1; + const struct aty128_pll *pll, + u32 depth, + const struct aty128fb_par *par) +{ + const struct aty128_meminfo *m = par->mem; + u32 xclk = par->constants.xclk; + u32 fifo_width = par->constants.fifo_width; + u32 fifo_depth = par->constants.fifo_depth; + s32 x, b, p, ron, roff; + u32 n, d, bpp; + + /* round up to multiple of 8 */ + bpp = (depth+7) & ~7; + + n = xclk * fifo_width; + d = pll->vclk * bpp; + x = round_div(n, d); + + ron = 4 * m->MB + + 3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) + + 2 * m->Trp + + m->Twr + + m->CL + + m->Tr2w + + x; + + DBG("x %x\n", x); + + b = 0; + while (x) { + x >>= 1; + b++; + } + p = b + 1; - ron <<= (11 - p); + ron <<= (11 - p); - n <<= (11 - p); - x = round_div(n, d); - roff = x * (fifo_depth - 4); + n <<= (11 - p); + x = round_div(n, d); + roff = x * (fifo_depth - 4); - if ((ron + m->Rloop) >= roff) { - printk(KERN_ERR "aty128fb: Mode out of range!\n"); - return -EINVAL; - } + if ((ron + m->Rloop) >= roff) { + printk(KERN_ERR "aty128fb: Mode out of range!\n"); + return -EINVAL; + } - DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n", - p, m->Rloop, x, ron, roff); + DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n", + p, m->Rloop, x, ron, roff); - dsp->dda_config = p << 16 | m->Rloop << 20 | x; - dsp->dda_on_off = ron << 16 | roff; + dsp->dda_config = p << 16 | m->Rloop << 20 | x; + dsp->dda_on_off = ron << 16 | roff; - return 0; + return 0; } /* * This actually sets the video mode. */ -static void -aty128_set_par(struct aty128fb_par *par, - struct fb_info_aty128 *info) +static int +aty128fb_set_par(struct fb_info *info) { - u32 config; - - info->current_par = *par; + struct aty128fb_par *par = info->par; + u32 config; - if (info->blitter_may_be_busy) - wait_for_idle(info); - - /* clear all registers that may interfere with mode setting */ - aty_st_le32(OVR_CLR, 0); - aty_st_le32(OVR_WID_LEFT_RIGHT, 0); - aty_st_le32(OVR_WID_TOP_BOTTOM, 0); - aty_st_le32(OV0_SCALE_CNTL, 0); - aty_st_le32(MPP_TB_CONFIG, 0); - aty_st_le32(MPP_GP_CONFIG, 0); - aty_st_le32(SUBPIC_CNTL, 0); - aty_st_le32(VIPH_CONTROL, 0); - aty_st_le32(I2C_CNTL_1, 0); /* turn off i2c */ - aty_st_le32(GEN_INT_CNTL, 0); /* turn off interrupts */ - aty_st_le32(CAP0_TRIG_CNTL, 0); - aty_st_le32(CAP1_TRIG_CNTL, 0); - - aty_st_8(CRTC_EXT_CNTL + 1, 4); /* turn video off */ - - aty128_set_crtc(&par->crtc, info); - aty128_set_pll(&par->pll, info); - aty128_set_fifo(&par->fifo_reg, info); - - config = aty_ld_le32(CONFIG_CNTL) & ~3; + if (par->blitter_may_be_busy) + wait_for_idle(par); + + /* clear all registers that may interfere with mode setting */ + aty_st_le32(OVR_CLR, 0); + aty_st_le32(OVR_WID_LEFT_RIGHT, 0); + aty_st_le32(OVR_WID_TOP_BOTTOM, 0); + aty_st_le32(OV0_SCALE_CNTL, 0); + aty_st_le32(MPP_TB_CONFIG, 0); + aty_st_le32(MPP_GP_CONFIG, 0); + aty_st_le32(SUBPIC_CNTL, 0); + aty_st_le32(VIPH_CONTROL, 0); + aty_st_le32(I2C_CNTL_1, 0); /* turn off i2c */ + aty_st_le32(GEN_INT_CNTL, 0); /* turn off interrupts */ + aty_st_le32(CAP0_TRIG_CNTL, 0); + aty_st_le32(CAP1_TRIG_CNTL, 0); + + aty_st_8(CRTC_EXT_CNTL + 1, 4); /* turn video off */ + + aty128_set_crtc(&par->crtc, par); + aty128_set_pll(&par->pll, par); + aty128_set_fifo(&par->fifo_reg, par); + + config = aty_ld_le32(CONFIG_CNTL) & ~3; #if defined(__BIG_ENDIAN) - if (par->crtc.bpp >= 24) - config |= 2; /* make aperture do 32 byte swapping */ - else if (par->crtc.bpp > 8) - config |= 1; /* make aperture do 16 byte swapping */ + if (par->crtc.bpp == 32) + config |= 2; /* make aperture do 32 bit swapping */ + else if (par->crtc.bpp == 16) + config |= 1; /* make aperture do 16 bit swapping */ #endif - aty_st_le32(CONFIG_CNTL, config); - aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */ + aty_st_le32(CONFIG_CNTL, config); + aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */ + + info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3; + info->fix.visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR + : FB_VISUAL_DIRECTCOLOR; - if (par->accel_flags & FB_ACCELF_TEXT) - aty128_init_engine(par, info); +#ifdef CONFIG_PMAC_PBOOK + if (par->chip_gen == rage_M3) { + aty128_set_crt_enable(par, par->crt_on); + aty128_set_lcd_enable(par, par->lcd_on); + } +#endif + if (par->accel_flags & FB_ACCELF_TEXT) + aty128_init_engine(par); -#if defined(CONFIG_BOOTX_TEXT) - btext_update_display(info->frame_buffer_phys, - (((par->crtc.h_total>>16) & 0xff)+1)*8, - ((par->crtc.v_total>>16) & 0x7ff)+1, - par->crtc.bpp, - par->crtc.vxres*par->crtc.bpp/8); +#ifdef CONFIG_BOOTX_TEXT + btext_update_display(info->fix.smem_start, + (((par->crtc.h_total>>16) & 0xff)+1)*8, + ((par->crtc.v_total>>16) & 0x7ff)+1, + par->crtc.bpp, + par->crtc.vxres*par->crtc.bpp/8); #endif /* CONFIG_BOOTX_TEXT */ + + return 0; } - /* - * encode/decode the User Defined Part of the Display - */ +/* + * encode/decode the User Defined Part of the Display + */ static int -aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par, - const struct fb_info_aty128 *info) +aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par) { - int err; - - if ((err = aty128_var_to_crtc(var, &par->crtc, info))) - return err; + int err; - if ((err = aty128_var_to_pll(var->pixclock, &par->pll, info))) - return err; + if ((err = aty128_var_to_crtc(var, &par->crtc, par))) + return err; - if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp, info))) - return err; + if ((err = aty128_var_to_pll(var->pixclock, &par->pll, par))) + return err; - if (var->accel_flags & FB_ACCELF_TEXT) - par->accel_flags = FB_ACCELF_TEXT; - else - par->accel_flags = 0; + if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.depth, par))) + return err; + par->accel_flags = var->accel_flags; - return 0; + return 0; } static int aty128_encode_var(struct fb_var_screeninfo *var, - const struct aty128fb_par *par, - const struct fb_info_aty128 *info) + const struct aty128fb_par *par) { - int err; - - if ((err = aty128_crtc_to_var(&par->crtc, var))) - return err; + int err; - if ((err = aty128_pll_to_var(&par->pll, var, info))) - return err; + if ((err = aty128_crtc_to_var(&par->crtc, var))) + return err; - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - var->transp.msb_right = 0; + if ((err = aty128_pll_to_var(&par->pll, var))) + return err; - var->nonstd = 0; - var->activate = 0; + var->nonstd = 0; + var->activate = 0; - var->height = -1; - var->width = -1; - var->accel_flags = par->accel_flags; + var->height = -1; + var->width = -1; + var->accel_flags = par->accel_flags; - return 0; + return 0; } - /* - * Get the User Defined Part of the Display - */ - -static int -aty128fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb) -{ - const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; - - if (con == -1) - aty128_encode_var(var, &info->default_par, info); - else - *var = fb_display[con].var; - return 0; -} - - - /* - * Set the User Defined Part of the Display - */ - static int -aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb) +aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; - struct aty128fb_par par; - struct display *display; - int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel; - int accel, err; - - display = (con >= 0) ? &fb_display[con] : fb->disp; - - /* basic (in)sanity checks */ - if (!var->xres) - var->xres = 1; - if (!var->yres) - var->yres = 1; - if (var->xres > var->xres_virtual) - var->xres_virtual = var->xres; - if (var->yres > var->yres_virtual) - var->yres_virtual = var->yres; - - switch (var->bits_per_pixel) { - case 0 ... 8: - var->bits_per_pixel = 8; - break; - case 9 ... 16: - var->bits_per_pixel = 16; - break; - case 17 ... 24: - var->bits_per_pixel = 24; - break; - case 25 ... 32: - var->bits_per_pixel = 32; - break; - default: - return -EINVAL; - } - - if ((err = aty128_decode_var(var, &par, info))) - return err; - - aty128_encode_var(var, &par, info); + struct aty128fb_par *par = info->par; + int err; - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) + if ((err = aty128_decode_var(var, par)) != 0) + return err; + aty128_encode_var(var, par); return 0; - - oldxres = display->var.xres; - oldyres = display->var.yres; - oldvxres = display->var.xres_virtual; - oldvyres = display->var.yres_virtual; - oldbpp = display->var.bits_per_pixel; - oldaccel = display->var.accel_flags; - display->var = *var; - if (oldxres != var->xres || oldyres != var->yres || - oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || - oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) { - - struct fb_fix_screeninfo fix; - - aty128_encode_fix(&fix, &par, info); - fb->screen_base = info->frame_buffer; - display->visual = fix.visual; - display->type = fix.type; - display->type_aux = fix.type_aux; - display->ypanstep = fix.ypanstep; - display->ywrapstep = fix.ywrapstep; - display->line_length = fix.line_length; - display->can_soft_blank = 1; - display->inverse = 0; - - accel = var->accel_flags & FB_ACCELF_TEXT; - aty128_set_dispsw(display, info, par.crtc.bpp, accel); - - if (accel) - display->scrollmode = SCROLL_YNOMOVE; - else - display->scrollmode = SCROLL_YREDRAW; - - if (info->fb_info.changevar) - (*info->fb_info.changevar)(con); - } - - if (!info->fb_info.display_fg || info->fb_info.display_fg->vc_num == con) - aty128_set_par(&par, info); - - if (oldbpp != var->bits_per_pixel) { - if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) - return err; - do_install_cmap(con, &info->fb_info); - } - - return 0; -} - - -static void -aty128_set_dispsw(struct display *disp, - struct fb_info_aty128 *info, int bpp, int accel) -{ - switch (bpp) { -#ifdef FBCON_HAS_CFB8 - case 8: - disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8; - break; -#endif -#ifdef FBCON_HAS_CFB16 - case 15: - case 16: - disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16; - disp->dispsw_data = info->fbcon_cmap.cfb16; - break; -#endif -#ifdef FBCON_HAS_CFB24 - case 24: - disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24; - disp->dispsw_data = info->fbcon_cmap.cfb24; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case 32: - disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32; - disp->dispsw_data = info->fbcon_cmap.cfb32; - break; -#endif - default: - disp->dispsw = &fbcon_dummy; - } -} - - -static void -aty128_encode_fix(struct fb_fix_screeninfo *fix, - struct aty128fb_par *par, - const struct fb_info_aty128 *info) -{ - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - - strcpy(fix->id, aty128fb_name); - - fix->smem_start = (unsigned long)info->frame_buffer_phys; - fix->mmio_start = (unsigned long)info->regbase_phys; - - fix->smem_len = info->vram_size; - fix->mmio_len = 0x1fff; - - fix->type = FB_TYPE_PACKED_PIXELS; - fix->type_aux = 0; - fix->line_length = (par->crtc.vxres * par->crtc.bpp) >> 3; - fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR - : FB_VISUAL_DIRECTCOLOR; - fix->ywrapstep = 0; - fix->xpanstep = 8; - fix->ypanstep = 1; - - fix->accel = FB_ACCEL_ATI_RAGE128; - - return; } - /* - * Get the Fixed Part of the Display - */ +/* + * Pan or Wrap the Display + */ static int -aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb) +aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb) { - const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; - struct aty128fb_par par; + struct aty128fb_par *par = fb->par; + u32 xoffset, yoffset; + u32 offset; + u32 xres, yres; - if (con == -1) - par = info->default_par; - else - aty128_decode_var(&fb_display[con].var, &par, info); + xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3; + yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1; - aty128_encode_fix(fix, &par, info); + xoffset = (var->xoffset +7) & ~7; + yoffset = var->yoffset; - return 0; -} + if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) + return -EINVAL; + par->crtc.xoffset = xoffset; + par->crtc.yoffset = yoffset; - /* - * Pan or Wrap the Display - * - * Not supported (yet!) - */ -static int -aty128fb_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *fb) -{ - struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; - struct aty128fb_par *par = &info->current_par; - u32 xoffset, yoffset; - u32 offset; - u32 xres, yres; - - xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3; - yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1; - - xoffset = (var->xoffset +7) & ~7; - yoffset = var->yoffset; - - if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) - return -EINVAL; + offset = ((yoffset * par->crtc.vxres + xoffset)*(par->crtc.bpp >> 3)) & ~7; - par->crtc.xoffset = xoffset; - par->crtc.yoffset = yoffset; + if (par->crtc.bpp == 24) + offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */ - offset = ((yoffset * par->crtc.vxres + xoffset) * par->crtc.bpp) >> 6; + aty_st_le32(CRTC_OFFSET, offset); - aty_st_le32(CRTC_OFFSET, offset); - - return 0; + return 0; } - /* - * Get the Colormap - */ - -static int -aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) +/* + * Helper function to store a single palette register + */ +static void +aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue, + struct aty128fb_par *par) { -#if 1 - fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2); -#else - struct fb_info_aty128 fb = (struct fb_info_aty128 *)info; - - if (con == info->currcon) /* current console? */ - return fb_get_cmap(cmap, kspc, aty128_getcolreg, info); - else 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 <= 8) ? 256 : 32; - fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); - } + if (par->chip_gen == rage_M3) { +#if 0 + /* Note: For now, on M3, we set palette on both heads, which may + * be useless. Can someone with a M3 check this ? + * + * This code would still be useful if using the second CRTC to + * do mirroring + */ + + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL); + aty_st_8(PALETTE_INDEX, regno); + aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue); #endif + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL); + } - return 0; + aty_st_8(PALETTE_INDEX, regno); + aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue); } static int -aty128fb_rasterimg(struct fb_info *info, int start) +aty128fb_sync(struct fb_info *info) { - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info; - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); + struct aty128fb_par *par = info->par; - return 0; + if (par->blitter_may_be_busy) + wait_for_idle(par); + return 0; } - int __init aty128fb_setup(char *options) { - char *this_opt; + char *this_opt; - if (!options || !*options) - return 0; + if (!options || !*options) + return 0; - while ((this_opt = strsep(&options, ",")) != NULL) { - if (!strncmp(this_opt, "font:", 5)) { - char *p; - int i; - - p = this_opt +5; - for (i = 0; i < sizeof(fontname) - 1; i++) - if (!*p || *p == ' ' || *p == ',') - break; - memcpy(fontname, this_opt + 5, i); - fontname[i] = 0; - } else if (!strncmp(this_opt, "noaccel", 7)) { - noaccel = 1; - } + while ((this_opt = strsep(&options, ",")) != NULL) { +#ifdef CONFIG_PMAC_PBOOK + if (!strncmp(this_opt, "lcd:", 4)) { + default_lcd_on = simple_strtoul(this_opt+4, NULL, 0); + } else if (!strncmp(this_opt, "crt:", 4)) { + default_crt_on = simple_strtoul(this_opt+4, NULL, 0); + } +#endif #ifdef CONFIG_MTRR - else if(!strncmp(this_opt, "nomtrr", 6)) { - mtrr = 0; - } + if(!strncmp(this_opt, "nomtrr", 6)) { + mtrr = 0; + } #endif -#ifdef CONFIG_PPC - /* vmode and cmode depreciated */ - else if (!strncmp(this_opt, "vmode:", 6)) { - unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0); - if (vmode > 0 && vmode <= VMODE_MAX) - default_vmode = vmode; - } else if (!strncmp(this_opt, "cmode:", 6)) { - unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0); - switch (cmode) { - case 0: - case 8: - default_cmode = CMODE_8; - break; - case 15: - case 16: - default_cmode = CMODE_16; - break; - case 24: - case 32: - default_cmode = CMODE_32; - break; - } - } -#endif /* CONFIG_PPC */ - else - mode_option = this_opt; - } - return 0; +#ifdef CONFIG_ALL_PPC + /* vmode and cmode depreciated */ + if (!strncmp(this_opt, "vmode:", 6)) { + unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0); + if (vmode > 0 && vmode <= VMODE_MAX) + default_vmode = vmode; + } else if (!strncmp(this_opt, "cmode:", 6)) { + unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0); + switch (cmode) { + case 0: + case 8: + default_cmode = CMODE_8; + break; + case 15: + case 16: + default_cmode = CMODE_16; + break; + case 24: + case 32: + default_cmode = CMODE_32; + break; + } + } +#endif /* CONFIG_ALL_PPC */ + else + mode_option = this_opt; + } + return 0; } - /* - * Initialisation - */ +/* + * Initialisation + */ static int __init -aty128_init(struct fb_info_aty128 *info, const char *name) -{ - struct fb_var_screeninfo var; - u32 dac; - int j, k, size; - u8 chip_rev; - const struct aty128_chip_info *aci = &aty128_pci_probe_list[0]; - char *video_card = "Rage128"; - - if (!info->vram_size) /* may have already been probed */ - info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; - - /* Get the chip revision */ - chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; - - /* put a name with the face */ - while (aci->name && info->pdev->device != aci->device) { aci++; } - video_card = (char *)aci->name; - info->chip_gen = aci->chip_gen; - - printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); - - if (info->vram_size % (1024 * 1024) == 0) - printk("%dM %s\n", info->vram_size / (1024*1024), info->mem->name); - else - printk("%dk %s\n", info->vram_size / 1024, info->mem->name); - - /* fill in info */ - strcpy(info->fb_info.modename, aty128fb_name); - info->fb_info.node = NODEV; - info->fb_info.fbops = &aty128fb_ops; - info->fb_info.disp = &info->disp; - strcpy(info->fb_info.fontname, fontname); - info->fb_info.changevar = NULL; - info->fb_info.switch_con = &aty128fbcon_switch; - info->fb_info.updatevar = NULL; - info->fb_info.flags = FBINFO_FLAG_DEFAULT; - - var = default_var; -#ifdef CONFIG_PPC - if (_machine == _MACH_Pmac) { - if (mode_option) { - if (!mac_find_mode(&var, &info->fb_info, mode_option, 8)) - var = default_var; - } else { - if (default_vmode <= 0 || default_vmode > VMODE_MAX) - default_vmode = VMODE_1024_768_60; - - /* iMacs need that resolution - * PowerMac2,1 first r128 iMacs - * PowerMac2,2 summer 2000 iMacs - * PowerMac4,1 january 2001 iMacs "flower power" - */ - if (machine_is_compatible("PowerMac2,1") || - machine_is_compatible("PowerMac2,2") || - machine_is_compatible("PowerMac4,1")) - default_vmode = VMODE_1024_768_75; - - /* iBook SE */ - if (machine_is_compatible("PowerBook2,2")) - default_vmode = VMODE_800_600_60; - - /* PowerBook Firewire (Pismo), iBook Dual USB */ - if (machine_is_compatible("PowerBook3,1") || - machine_is_compatible("PowerBook4,1")) - default_vmode = VMODE_1024_768_60; - - /* PowerBook Titanium */ - if (machine_is_compatible("PowerBook3,2")) - default_vmode = VMODE_1152_768_60; - - if (default_cmode < CMODE_8 || default_cmode > CMODE_32) - default_cmode = CMODE_8; - - if (mac_vmode_to_var(default_vmode, default_cmode, &var)) - var = default_var; - } - } else -#endif /* CONFIG_PPC */ - { - if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, - &defaultmode, 8) == 0) - var = default_var; - } - - if (noaccel) - var.accel_flags &= ~FB_ACCELF_TEXT; - else - var.accel_flags |= FB_ACCELF_TEXT; - - if (aty128_decode_var(&var, &info->default_par, info)) { - printk(KERN_ERR "aty128fb: Cannot set default mode.\n"); - return 0; - } +aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct fb_info *info = pci_get_drvdata(pdev); + struct aty128fb_par *par = info->par; + struct fb_var_screeninfo var; + char video_card[25]; + u8 chip_rev; + u32 dac; + + if (!par->vram_size) /* may have already been probed */ + par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; + + /* Get the chip revision */ + chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; + + switch (pdev->device) { + case PCI_DEVICE_ID_ATI_RAGE128_RE: + strcpy(video_card, "Rage128 RE (PCI)"); + break; + case PCI_DEVICE_ID_ATI_RAGE128_RF: + strcpy(video_card, "Rage128 RF (AGP)"); + break; + case PCI_DEVICE_ID_ATI_RAGE128_RK: + strcpy(video_card, "Rage128 RK (PCI)"); + break; + case PCI_DEVICE_ID_ATI_RAGE128_RL: + strcpy(video_card, "Rage128 RL (AGP)"); + break; + case PCI_DEVICE_ID_ATI_RAGE128_PF: + strcpy(video_card, "Rage128 Pro PF (AGP)"); + break; + case PCI_DEVICE_ID_ATI_RAGE128_PR: + strcpy(video_card, "Rage128 Pro PR (PCI)"); + break; + case PCI_DEVICE_ID_ATI_RAGE128_U3: + strcpy(video_card, "Rage128 Pro TR (AGP)"); + break; + case PCI_DEVICE_ID_ATI_RAGE128_U1: + strcpy(video_card, "Rage128 Pro TF (AGP)"); + break; + case PCI_DEVICE_ID_ATI_RAGE128_LE: + strcpy(video_card, "Rage Mobility M3 (PCI)"); + break; + case PCI_DEVICE_ID_ATI_RAGE128_LF: + strcpy(video_card, "Rage Mobility M3 (AGP)"); + break; + default: + return -ENODEV; + } - /* load up the palette with default colors */ - for (j = 0; j < 16; j++) { - k = color_table[j]; - info->palette[j].red = default_red[k]; - info->palette[j].green = default_grn[k]; - info->palette[j].blue = default_blu[k]; - } + printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); - /* setup the DAC the way we like it */ - dac = aty_ld_le32(DAC_CNTL); - dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL); - dac |= DAC_MASK; - aty_st_le32(DAC_CNTL, dac); + if (par->vram_size % (1024 * 1024) == 0) + printk("%dM %s\n", par->vram_size / (1024*1024), par->mem->name); + else + printk("%dk %s\n", par->vram_size / 1024, par->mem->name); - /* turn off bus mastering, just in case */ - aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS); + par->chip_gen = ent->driver_data; - aty128fb_set_var(&var, -1, &info->fb_info); - aty128_init_engine(&info->default_par, info); + /* fill in info */ + info->node = NODEV; + info->fbops = &aty128fb_ops; + info->flags = FBINFO_FLAG_DEFAULT; - board_list = aty128_board_list_add(board_list, info); +#ifdef CONFIG_PMAC_PBOOK + par->lcd_on = default_lcd_on; + par->crt_on = default_crt_on; +#endif - size = (var.bits_per_pixel <= 8) ? 256 : 32; - fb_alloc_cmap(&info->fb_info.cmap, size, 0); + var = default_var; +#ifdef CONFIG_ALL_PPC + if (_machine == _MACH_Pmac) { + if (mode_option) { + if (!mac_find_mode(&var, info, mode_option, 8)) + var = default_var; + } else { + if (default_vmode <= 0 || default_vmode > VMODE_MAX) + default_vmode = VMODE_1024_768_60; + + /* iMacs need that resolution + * PowerMac2,1 first r128 iMacs + * PowerMac2,2 summer 2000 iMacs + * PowerMac4,1 january 2001 iMacs "flower power" + */ + if (machine_is_compatible("PowerMac2,1") || + machine_is_compatible("PowerMac2,2") || + machine_is_compatible("PowerMac4,1")) + default_vmode = VMODE_1024_768_75; + + /* iBook SE */ + if (machine_is_compatible("PowerBook2,2")) + default_vmode = VMODE_800_600_60; + + /* PowerBook Firewire (Pismo), iBook Dual USB */ + if (machine_is_compatible("PowerBook3,1") || + machine_is_compatible("PowerBook4,1")) + default_vmode = VMODE_1024_768_60; + + /* PowerBook Titanium */ + if (machine_is_compatible("PowerBook3,2")) + default_vmode = VMODE_1152_768_60; + + if (default_cmode < CMODE_8 || default_cmode > CMODE_32) + default_cmode = CMODE_8; - if (register_framebuffer(&info->fb_info) < 0) - return 0; + if (mac_vmode_to_var(default_vmode, default_cmode, &var)) + var = default_var; + } + } else +#endif /* CONFIG_ALL_PPC */ + { + if (fb_find_mode(&var, info, mode_option, NULL, 0, + &defaultmode, 8) == 0) + var = default_var; + } -#ifdef CONFIG_PMAC_BACKLIGHT - /* Could be extended to Rage128Pro LVDS output too */ - if (info->chip_gen == rage_M3) - register_backlight_controller(&aty128_backlight_controller, info, "ati"); -#endif /* CONFIG_PMAC_BACKLIGHT */ + var.accel_flags &= ~FB_ACCELF_TEXT; +// var.accel_flags |= FB_ACCELF_TEXT;/* FIXME Will add accel later */ - printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", - GET_FB_IDX(info->fb_info.node), aty128fb_name, name); + if (aty128fb_check_var(&var, info)) { + printk(KERN_ERR "aty128fb: Cannot set default mode.\n"); + return 0; + } - return 1; /* success! */ -} + /* setup the DAC the way we like it */ + dac = aty_ld_le32(DAC_CNTL); + dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL); + dac |= DAC_MASK; + if (par->chip_gen == rage_M3) + dac |= DAC_PALETTE2_SNOOP_EN; + aty_st_le32(DAC_CNTL, dac); + /* turn off bus mastering, just in case */ + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS); -/* add a new card to the list ++ajoshi */ -static struct -fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128 *board_list, - struct fb_info_aty128 *new_node) -{ - struct fb_info_aty128 *i_p = board_list; + info->var = var; + fb_alloc_cmap(&info->cmap, 256, 0); - new_node->next = NULL; - if(board_list == NULL) - return new_node; - while(i_p->next != NULL) - i_p = i_p->next; - i_p->next = new_node; + var.activate = FB_ACTIVATE_NOW; - return board_list; -} + aty128_init_engine(par); + if (register_framebuffer(info) < 0) + return 0; -int __init -aty128fb_init(void) -{ -#ifdef CONFIG_PCI - struct pci_dev *pdev = NULL; - const struct aty128_chip_info *aci = &aty128_pci_probe_list[0]; - - while (aci->name != NULL) { - pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev); - while (pdev != NULL) { - if (aty128_pci_register(pdev, aci) == 0) - return 0; - pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev); - } - aci++; - } +#ifdef CONFIG_PMAC_BACKLIGHT + /* Could be extended to Rage128Pro LVDS output too */ + if (par->chip_gen == rage_M3) + register_backlight_controller(&aty128_backlight_controller, par, "ati"); +#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); #endif - return 0; -} + printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", + minor(info->node), info->fix.id, video_card); + return 1; /* success! */ +} #ifdef CONFIG_PCI /* register a card ++ajoshi */ static int __init -aty128_pci_register(struct pci_dev *pdev, - const struct aty128_chip_info *aci) +aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct fb_info_aty128 *info = NULL; unsigned long fb_addr, reg_addr; - int err; + struct aty128fb_par *par; + struct fb_info *info; + int err, size; #if !defined(CONFIG_PPC) && !defined(__sparc__) char *bios_seg = NULL; #endif @@ -1824,7 +1628,7 @@ aty128_pci_register(struct pci_dev *pdev, if ((err = pci_enable_device(pdev))) { printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n", err); - goto err_out; + return -ENODEV; } fb_addr = pci_resource_start(pdev, 0); @@ -1843,62 +1647,71 @@ aty128_pci_register(struct pci_dev *pdev, } /* We have the resources. Now virtualize them */ - if (!(info = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC))) { + size = sizeof(struct fb_info) + sizeof(struct aty128fb_par) + + sizeof(u32)*16; + if (!(info = kmalloc(size, GFP_ATOMIC))) { printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n"); goto err_unmap_out; } - memset(info, 0, sizeof(struct fb_info_aty128)); + memset(info, 0, size); - /* Copy PCI device info into info->pdev */ - info->pdev = pdev; + par = (struct aty128fb_par *)(info + 1); + info->pseudo_palette = (void *) (par + 1); - info->fb_info.currcon = -1; + memset(info, 0, sizeof(struct fb_info)); - /* Virtualize mmio region */ - info->regbase_phys = reg_addr; - info->regbase = ioremap(reg_addr, 0x1FFF); + info->par = par; + info->fix = aty128fb_fix; - if (!info->regbase) + /* Virtualize mmio region */ + info->fix.mmio_start = reg_addr; + par->regbase = ioremap(reg_addr, 0x2000); + if (!par->regbase) goto err_free_info; /* Grab memory size from the card */ - info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; + par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; /* Virtualize the framebuffer */ - info->frame_buffer_phys = fb_addr; - info->frame_buffer = ioremap(fb_addr, info->vram_size); - - if (!info->frame_buffer) { - iounmap((void *)info->regbase); + info->screen_base = ioremap(fb_addr, par->vram_size); + if (!info->screen_base) { + iounmap(par->regbase); goto err_free_info; } + /* Set up info->fix */ + info->fix = aty128fb_fix; + info->fix.smem_start = fb_addr; + info->fix.smem_len = par->vram_size; + info->fix.mmio_start = reg_addr; + /* If we can't test scratch registers, something is seriously wrong */ - if (!register_test(info)) { + if (!register_test(par)) { printk(KERN_ERR "aty128fb: Can't write to video register!\n"); goto err_out; } #if !defined(CONFIG_PPC) && !defined(__sparc__) - if (!(bios_seg = aty128find_ROM(info))) + if (!(bios_seg = aty128find_ROM())) printk(KERN_INFO "aty128fb: Rage128 BIOS not located. " "Guessing...\n"); else { printk(KERN_INFO "aty128fb: Rage128 BIOS located at " "segment %4.4X\n", (unsigned int)bios_seg); - aty128_get_pllinfo(info, bios_seg); + aty128_get_pllinfo(par, bios_seg); } #endif - aty128_timings(info); + aty128_timings(par); + pci_set_drvdata(pdev, info); - if (!aty128_init(info, "PCI")) + if (!aty128_init(pdev, ent)) goto err_out; #ifdef CONFIG_MTRR if (mtrr) { - info->mtrr.vram = mtrr_add(info->frame_buffer_phys, - info->vram_size, MTRR_TYPE_WRCOMB, 1); - info->mtrr.vram_valid = 1; + par->mtrr.vram = mtrr_add(info->fix.smem_start, + par->vram_size, MTRR_TYPE_WRCOMB, 1); + par->mtrr.vram_valid = 1; /* let there be speed */ printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n"); } @@ -1906,8 +1719,8 @@ aty128_pci_register(struct pci_dev *pdev, return 0; err_out: - iounmap(info->frame_buffer); - iounmap(info->regbase); + iounmap(info->screen_base); + iounmap(par->regbase); err_free_info: kfree(info); err_unmap_out: @@ -1921,21 +1734,48 @@ err_free_fb: pci_resource_len(pdev, 1)); return -ENODEV; } -#endif /* CONFIG_PCI */ +static void __devexit aty128_remove(struct pci_dev *pdev) +{ + struct fb_info *info = pci_get_drvdata(pdev); + struct aty128fb_par *par = info->par; + + if (!info) + return; + + unregister_framebuffer(info); +#ifdef CONFIG_MTRR + if (par->mtrr.vram_valid) + mtrr_del(par->mtrr.vram, info->fix.smem_start, + par->vram_size); +#endif /* CONFIG_MTRR */ + iounmap(par->regbase); + iounmap(info->screen_base); + + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + release_mem_region(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1)); + release_mem_region(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); + kfree(info); +} +#endif /* CONFIG_PCI */ /* PPC and Sparc cannot read video ROM */ #if !defined(CONFIG_PPC) && !defined(__sparc__) -static char __init -*aty128find_ROM(struct fb_info_aty128 *info) +static char * __init aty128find_ROM(void) { u32 segstart; char *rom_base; char *rom; int stage; - int i; + int i, j; char aty_rom_sig[] = "761295520"; /* ATI ROM Signature */ - char R128_sig[] = "R128"; /* Rage128 ROM identifier */ + char *R128_sig[] = { + "R128", /* Rage128 ROM identifier */ + "128b" + }; for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { stage = 1; @@ -1966,26 +1806,28 @@ static char __init /* ATI signature found. Let's see if it's a Rage128 */ for (i = 0; (i < 512) && (stage != 4); i++) { - if (R128_sig[0] == *rom) - if (strncmp(R128_sig, rom, - strlen(R128_sig)) == 0) - stage = 4; + for (j = 0; j < sizeof(R128_sig)/sizeof(char *);j++) { + if (R128_sig[j][0] == *rom) + if (strncmp(R128_sig[j], rom, + strlen(R128_sig[j])) == 0) { + stage = 4; + break; + } + } rom++; } if (stage != 4) { iounmap(rom_base); continue; } - return rom_base; } - return NULL; } static void __init -aty128_get_pllinfo(struct fb_info_aty128 *info, char *bios_seg) +aty128_get_pllinfo(struct aty128fb_par *par, char *bios_seg) { void *bios_header; void *header_ptr; @@ -2005,16 +1847,16 @@ aty128_get_pllinfo(struct fb_info_aty128 *info, char *bios_seg) memcpy_fromio(&pll, header_ptr, 50); - info->constants.ppll_max = pll.PCLK_max_freq; - info->constants.ppll_min = pll.PCLK_min_freq; - info->constants.xclk = (u32)pll.XCLK; - info->constants.ref_divider = (u32)pll.PCLK_ref_divider; - info->constants.dotclock = (u32)pll.PCLK_ref_freq; + par->constants.ppll_max = pll.PCLK_max_freq; + par->constants.ppll_min = pll.PCLK_min_freq; + par->constants.xclk = (u32)pll.XCLK; + par->constants.ref_divider = (u32)pll.PCLK_ref_divider; + par->constants.dotclock = (u32)pll.PCLK_ref_freq; DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d dotclock %d\n", - info->constants.ppll_max, info->constants.ppll_min, - info->constants.xclk, info->constants.ref_divider, - info->constants.dotclock); + par->constants.ppll_max, par->constants.ppll_min, + par->constants.xclk, par->constants.ref_divider, + par->constants.dotclock); } #endif /* !CONFIG_PPC */ @@ -2022,244 +1864,212 @@ aty128_get_pllinfo(struct fb_info_aty128 *info, char *bios_seg) /* fill in known card constants if pll_block is not available */ static void __init -aty128_timings(struct fb_info_aty128 *info) +aty128_timings(struct aty128fb_par *par) { -#ifdef CONFIG_PPC - /* instead of a table lookup, assume OF has properly - * setup the PLL registers and use their values - * to set the XCLK values and reference divider values */ - - u32 x_mpll_ref_fb_div; - u32 xclk_cntl; - u32 Nx, M; - unsigned PostDivSet[] = - { 0, 1, 2, 4, 8, 3, 6, 12 }; -#endif - - if (!info->constants.dotclock) - info->constants.dotclock = 2950; +#ifdef CONFIG_ALL_PPC + /* instead of a table lookup, assume OF has properly + * setup the PLL registers and use their values + * to set the XCLK values and reference divider values */ -#ifdef CONFIG_PPC - x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV); - xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7; - Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8; - M = x_mpll_ref_fb_div & 0x0000ff; - - info->constants.xclk = round_div((2 * Nx * - info->constants.dotclock), (M * PostDivSet[xclk_cntl])); - - info->constants.ref_divider = - aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK; + u32 x_mpll_ref_fb_div; + u32 xclk_cntl; + u32 Nx, M; + unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 }; #endif - if (!info->constants.ref_divider) { - info->constants.ref_divider = 0x3b; - - aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e); - aty_pll_writeupdate(info); - } - aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider); - aty_pll_writeupdate(info); - - /* from documentation */ - if (!info->constants.ppll_min) - info->constants.ppll_min = 12500; - if (!info->constants.ppll_max) - info->constants.ppll_max = 25000; /* 23000 on some cards? */ - if (!info->constants.xclk) - info->constants.xclk = 0x1d4d; /* same as mclk */ - - info->constants.fifo_width = 128; - info->constants.fifo_depth = 32; - - switch (aty_ld_le32(MEM_CNTL) & 0x3) { - case 0: - info->mem = &sdr_128; - break; - case 1: - info->mem = &sdr_sgram; - break; - case 2: - info->mem = &ddr_sgram; - break; - default: - info->mem = &sdr_sgram; - } -} - + if (!par->constants.dotclock) + par->constants.dotclock = 2950; -static int -aty128fbcon_switch(int con, struct fb_info *fb) -{ - struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; - struct aty128fb_par par; - - /* Do we have to save the colormap? */ - if (fb_display[fb->currcon].cmap.len) - fb_get_cmap(&fb_display[fb->currcon].cmap, 1, - aty128_getcolreg, fb); - - /* set the current console */ - fb->currcon = con; +#ifdef CONFIG_ALL_PPC + x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV); + xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7; + Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8; + M = x_mpll_ref_fb_div & 0x0000ff; - aty128_decode_var(&fb_display[con].var, &par, info); - aty128_set_par(&par, info); + par->constants.xclk = round_div((2 * Nx * par->constants.dotclock), + (M * PostDivSet[xclk_cntl])); - aty128_set_dispsw(&fb_display[con], info, par.crtc.bpp, - par.accel_flags & FB_ACCELF_TEXT); + par->constants.ref_divider = + aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK; +#endif - do_install_cmap(con, fb); + if (!par->constants.ref_divider) { + par->constants.ref_divider = 0x3b; - return 1; + aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e); + aty_pll_writeupdate(par); + } + aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider); + aty_pll_writeupdate(par); + + /* from documentation */ + if (!par->constants.ppll_min) + par->constants.ppll_min = 12500; + if (!par->constants.ppll_max) + par->constants.ppll_max = 25000; /* 23000 on some cards? */ + if (!par->constants.xclk) + par->constants.xclk = 0x1d4d; /* same as mclk */ + + par->constants.fifo_width = 128; + par->constants.fifo_depth = 32; + + switch (aty_ld_le32(MEM_CNTL) & 0x3) { + case 0: + par->mem = &sdr_128; + break; + case 1: + par->mem = &sdr_sgram; + break; + case 2: + par->mem = &ddr_sgram; + break; + default: + par->mem = &sdr_sgram; + } } /* * Blank the display. */ -static int +static int aty128fb_blank(int blank, struct fb_info *fb) { - struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; - u8 state = 0; + struct aty128fb_par *par = fb->par; + u8 state = 0; #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && blank) - set_backlight_enable(0); + if ((_machine == _MACH_Pmac) && blank) + set_backlight_enable(0); #endif /* CONFIG_PMAC_BACKLIGHT */ - if (blank & VESA_VSYNC_SUSPEND) - state |= 2; - if (blank & VESA_HSYNC_SUSPEND) - state |= 1; - if (blank & VESA_POWERDOWN) - state |= 4; + if (blank & VESA_VSYNC_SUSPEND) + state |= 2; + if (blank & VESA_HSYNC_SUSPEND) + state |= 1; + if (blank & VESA_POWERDOWN) + state |= 4; - aty_st_8(CRTC_EXT_CNTL+1, state); + aty_st_8(CRTC_EXT_CNTL+1, state); +#ifdef CONFIG_PMAC_PBOOK + if (par->chip_gen == rage_M3) { + aty128_set_crt_enable(par, par->crt_on && !blank); + aty128_set_lcd_enable(par, par->lcd_on && !blank); + } +#endif #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && !blank) - set_backlight_enable(1); + if ((_machine == _MACH_Pmac) && !blank) + set_backlight_enable(1); #endif /* CONFIG_PMAC_BACKLIGHT */ - return 0; -} - - /* - * Read a single color register and split it into - * colors/transparent. Return != 0 for invalid regno. - */ -static int -aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp, struct fb_info *fb) -{ - struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb; - - if (regno > 255) - return 1; - - *red = (info->palette[regno].red<<8) | info->palette[regno].red; - *green = (info->palette[regno].green<<8) | info->palette[regno].green; - *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue; - *transp = 0; - - return 0; + return 0; } - /* - * Set a single color register. The values supplied are already - * rounded down to the hardware's capabilities (according to the - * entries in the var structure). Return != 0 for invalid regno. - */ +/* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + */ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *fb) -{ - struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; - u32 col; - - if (regno > 255) - return 1; - - red >>= 8; - green >>= 8; - blue >>= 8; - info->palette[regno].red = red; - info->palette[regno].green = green; - info->palette[regno].blue = blue; - - /* Note: For now, on M3, we set palette on both heads, which may - * be useless. Can someone with a M3 check this ? */ - - /* initialize gamma ramp for hi-color+ */ - - if ((info->current_par.crtc.bpp > 8) && (regno == 0)) { - int i; - - if (info->chip_gen == rage_M3) - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL); + u_int transp, struct fb_info *info) +{ + struct aty128fb_par *par = info->par; + + if (regno > 255 + || (par->crtc.depth == 16 && regno > 63) + || (par->crtc.depth == 15 && regno > 31)) + return 1; + + red >>= 8; + green >>= 8; + blue >>= 8; + + if (regno < 16) { + int i; + switch (par->crtc.depth) { + case 15: + ((u16 *) (info->pseudo_palette))[regno] = + (regno << 10) | (regno << 5) | regno; + break; + case 16: + ((u16 *) (info->pseudo_palette))[regno] = + (regno << 11) | (regno << 6) | regno; + break; + case 24: + ((u32 *) (info->pseudo_palette))[regno] = + (regno << 16) | (regno << 8) | regno; + break; + case 32: + i = (regno << 8) | regno; + ((u32 *) (info->pseudo_palette))[regno] = + (i << 16) | i; + break; + } + } - for (i=16; i<256; i++) { - aty_st_8(PALETTE_INDEX, i); - col = (i << 16) | (i << 8) | i; - aty_st_le32(PALETTE_DATA, col); - } + if (par->crtc.depth == 16) { + /* + * 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. + * Thus the R and B values go in one slot but the G value + * 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) + aty128_st_pal(regno * 8, red, par->green[regno*2], + blue, par); + red = par->red[regno/2]; + blue = par->blue[regno/2]; + regno <<= 2; + } else if (par->crtc.bpp == 16) + regno <<= 3; + aty128_st_pal(regno, red, green, blue, par); - if (info->chip_gen == rage_M3) { - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL); + return 0; +} - for (i=16; i<256; i++) { - aty_st_8(PALETTE_INDEX, i); - col = (i << 16) | (i << 8) | i; - aty_st_le32(PALETTE_DATA, col); - } - } - } +#define ATY_MIRROR_LCD_ON 0x00000001 +#define ATY_MIRROR_CRT_ON 0x00000002 - /* initialize palette */ - - if (info->chip_gen == rage_M3) - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL); - - if (info->current_par.crtc.bpp == 16) - aty_st_8(PALETTE_INDEX, (regno << 3)); - else - aty_st_8(PALETTE_INDEX, regno); - col = (red << 16) | (green << 8) | blue; - aty_st_le32(PALETTE_DATA, col); - if (info->chip_gen == rage_M3) { - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL); - if (info->current_par.crtc.bpp == 16) - aty_st_8(PALETTE_INDEX, (regno << 3)); - else - aty_st_8(PALETTE_INDEX, regno); - aty_st_le32(PALETTE_DATA, col); - } +/* out param: u32* backlight value: 0 to 15 */ +#define FBIO_ATY128_GET_MIRROR _IOR('@', 1, sizeof(__u32*)) +/* in param: u32* backlight value: 0 to 15 */ +#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, sizeof(__u32*)) - if (regno < 16) - switch (info->current_par.crtc.bpp) { -#ifdef FBCON_HAS_CFB16 - case 9 ... 16: - info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | - regno; - break; -#endif -#ifdef FBCON_HAS_CFB24 - case 17 ... 24: - info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | - regno; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case 25 ... 32: { - u32 i; - - i = (regno << 8) | regno; - info->fbcon_cmap.cfb32[regno] = (i << 16) | i; - break; - } -#endif +static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, struct fb_info *info) +{ +#ifdef CONFIG_PMAC_PBOOK + struct aty128fb_par *par = info->par; + u32 value; + int rc; + + switch (cmd) { + case FBIO_ATY128_SET_MIRROR: + if (par->chip_gen != rage_M3) + return -EINVAL; + rc = get_user(value, (__u32*)arg); + if (rc) + return rc; + par->lcd_on = (value & 0x01) != 0; + par->crt_on = (value & 0x02) != 0; + if (!par->crt_on && !par->lcd_on) + par->lcd_on = 1; + aty128_set_crt_enable(par, par->crt_on); + aty128_set_lcd_enable(par, par->lcd_on); + return 0; + case FBIO_ATY128_GET_MIRROR: + if (par->chip_gen != rage_M3) + return -EINVAL; + value = (par->crt_on << 1) | par->lcd_on; + return put_user(value, (__u32*)arg); } - return 0; +#endif + return -EINVAL; } #ifdef CONFIG_PMAC_BACKLIGHT @@ -2268,21 +2078,58 @@ static int backlight_conv[] = { 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 }; +/* We turn off the LCD completely instead of just dimming the backlight. + * This provides greater power saving and the display is useless without + * backlight anyway + */ +#define BACKLIGHT_LVDS_OFF +/* That one prevents proper CRT output with LCD off */ +#undef BACKLIGHT_DAC_OFF + static int -aty128_set_backlight_enable(int on, int level, void* data) +aty128_set_backlight_enable(int on, int level, void *data) { - struct fb_info_aty128 *info = (struct fb_info_aty128 *)data; + struct aty128fb_par *par = data; unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); - + + if (!par->lcd_on) + on = 0; reg |= LVDS_BL_MOD_EN | LVDS_BLON; if (on && level > BACKLIGHT_OFF) { + reg |= LVDS_DIGION; + if (!reg & LVDS_ON) { + reg &= ~LVDS_BLON; + aty_st_le32(LVDS_GEN_CNTL, reg); + (void)aty_ld_le32(LVDS_GEN_CNTL); + mdelay(10); + reg |= LVDS_BLON; + aty_st_le32(LVDS_GEN_CNTL, reg); + } reg &= ~LVDS_BL_MOD_LEVEL_MASK; reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT); +#ifdef BACKLIGHT_LVDS_OFF + reg |= LVDS_ON | LVDS_EN; + reg &= ~LVDS_DISPLAY_DIS; +#endif + aty_st_le32(LVDS_GEN_CNTL, reg); +#ifdef BACKLIGHT_DAC_OFF + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN)); +#endif } else { reg &= ~LVDS_BL_MOD_LEVEL_MASK; reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT); +#ifdef BACKLIGHT_LVDS_OFF + reg |= LVDS_DISPLAY_DIS; + aty_st_le32(LVDS_GEN_CNTL, reg); + (void)aty_ld_le32(LVDS_GEN_CNTL); + udelay(10); + reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION); +#endif + aty_st_le32(LVDS_GEN_CNTL, reg); +#ifdef BACKLIGHT_DAC_OFF + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN); +#endif } - aty_st_le32(LVDS_GEN_CNTL, reg); return 0; } @@ -2294,6 +2141,7 @@ aty128_set_backlight_level(int level, void* data) } #endif /* CONFIG_PMAC_BACKLIGHT */ +#if 0 /* * Accelerated functions */ @@ -2301,39 +2149,39 @@ aty128_set_backlight_level(int level, void* data) static inline void aty128_rectcopy(int srcx, int srcy, int dstx, int dsty, u_int width, u_int height, - struct fb_info_aty128 *info) + struct fb_info_aty128 *par) { - u32 save_dp_datatype, save_dp_cntl, bppval; + u32 save_dp_datatype, save_dp_cntl, dstval; if (!width || !height) return; - bppval = bpp_to_depth(info->current_par.crtc.bpp); - if (bppval == DST_24BPP) { + dstval = depth_to_dst(par->current_par.crtc.depth); + if (dstval == DST_24BPP) { srcx *= 3; dstx *= 3; width *= 3; - } else if (bppval == -EINVAL) { - printk("aty128fb: invalid depth\n"); + } else if (dstval == -EINVAL) { + printk("aty128fb: invalid depth or RGBA\n"); return; } - wait_for_fifo(2, info); + wait_for_fifo(2, par); save_dp_datatype = aty_ld_le32(DP_DATATYPE); save_dp_cntl = aty_ld_le32(DP_CNTL); - wait_for_fifo(6, info); + wait_for_fifo(6, par); aty_st_le32(SRC_Y_X, (srcy << 16) | srcx); aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT); aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); - aty_st_le32(DP_DATATYPE, save_dp_datatype | bppval | SRC_DSTCOLOR); + aty_st_le32(DP_DATATYPE, save_dp_datatype | dstval | SRC_DSTCOLOR); aty_st_le32(DST_Y_X, (dsty << 16) | dstx); aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width); - info->blitter_may_be_busy = 1; + par->blitter_may_be_busy = 1; - wait_for_fifo(2, info); + wait_for_fifo(2, par); aty_st_le32(DP_DATATYPE, save_dp_datatype); aty_st_le32(DP_CNTL, save_dp_cntl); } @@ -2357,209 +2205,129 @@ fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx, aty128_rectcopy(sx, sy, dx, dy, width, height, (struct fb_info_aty128 *)p->fb_info); } +#endif /* 0 */ - -#ifdef FBCON_HAS_CFB8 -static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx) -{ - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb8_putc(conp, p, c, yy, xx); -} - - -static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, - int yy, int xx) -{ - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb8_putcs(conp, p, s, count, yy, xx); -} - - -static void fbcon_aty8_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) -{ - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb8_clear_margins(conp, p, bottom_only); -} - -static struct display_switch fbcon_aty128_8 = { - setup: fbcon_cfb8_setup, - bmove: fbcon_aty128_bmove, - clear: fbcon_cfb8_clear, - putc: fbcon_aty8_putc, - putcs: fbcon_aty8_putcs, - revc: fbcon_cfb8_revc, - clear_margins: fbcon_aty8_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; -#endif -#ifdef FBCON_HAS_CFB16 -static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx) -{ - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb16_putc(conp, p, c, yy, xx); -} - - -static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, - int yy, int xx) -{ - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb16_putcs(conp, p, s, count, yy, xx); -} - - -static void fbcon_aty16_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) -{ - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb16_clear_margins(conp, p, bottom_only); -} - -static struct display_switch fbcon_aty128_16 = { - setup: fbcon_cfb16_setup, - bmove: fbcon_aty128_bmove, - clear: fbcon_cfb16_clear, - putc: fbcon_aty16_putc, - putcs: fbcon_aty16_putcs, - revc: fbcon_cfb16_revc, - clear_margins: fbcon_aty16_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; -#endif -#ifdef FBCON_HAS_CFB24 -static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx) -{ - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb24_putc(conp, p, c, yy, xx); -} - - -static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, - int yy, int xx) -{ - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb24_putcs(conp, p, s, count, yy, xx); +#ifdef CONFIG_PMAC_PBOOK +static void +aty128_set_suspend(struct aty128fb_par *par, int suspend) +{ + u32 pmgt; + u16 pwr_command; + + if (!par->pm_reg) + return; + + /* Set the chip into the appropriate suspend mode (we use D2, + * D3 would require a complete re-initialisation of the chip, + * including PCI config registers, clocks, AGP configuration, ...) + */ + if (suspend) { + /* Make sure CRTC2 is reset. Remove that the day we decide to + * actually use CRTC2 and replace it with real code for disabling + * the CRTC2 output during sleep + */ + aty_st_le32(CRTC2_GEN_CNTL, aty_ld_le32(CRTC2_GEN_CNTL) & + ~(CRTC2_EN)); + + /* Set the power management mode to be PCI based */ + /* Use this magic value for now */ + pmgt = 0x0c005407; + aty_st_pll(POWER_MANAGEMENT, pmgt); + (void)aty_ld_pll(POWER_MANAGEMENT); + 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); + /* Switch PCI power management to D2 */ + pci_write_config_word(par->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); + } 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); + mdelay(100); + } } - -static void fbcon_aty24_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) +/* + * Save the contents of the frame buffer when we go to sleep, + * and restore it when we wake up again. + */ +int +aty128_sleep_notify(struct pmu_sleep_notifier *self, int when) { - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb24_clear_margins(conp, p, bottom_only); -} + int result = PBOOK_SLEEP_OK, nb; + struct fb_info *info = info; /* FIXME!!! How do find which framebuffer */ + struct aty128fb_par *par = info->par; -static struct display_switch fbcon_aty128_24 = { - setup: fbcon_cfb24_setup, - bmove: fbcon_aty128_bmove, - clear: fbcon_cfb24_clear, - putc: fbcon_aty24_putc, - putcs: fbcon_aty24_putcs, - revc: fbcon_cfb24_revc, - clear_margins: fbcon_aty24_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; -#endif -#ifdef FBCON_HAS_CFB32 -static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx) -{ - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); + nb = info->var.yres * info->fix.line_length; - if (fb->blitter_may_be_busy) - wait_for_idle(fb); + switch (when) { + case PBOOK_SLEEP_REQUEST: + par->save_framebuffer = vmalloc(nb); + if (par->save_framebuffer == NULL) + return PBOOK_SLEEP_REFUSE; + break; + case PBOOK_SLEEP_REJECT: + if (par->save_framebuffer) { + vfree(par->save_framebuffer); + par->save_framebuffer = 0; + } + break; + case PBOOK_SLEEP_NOW: + wait_for_idle(par); + aty128_reset_engine(par); + wait_for_idle(par); + + /* Backup fb content */ + if (par->save_framebuffer) + memcpy_fromio(par->save_framebuffer, + info->screen_base, nb); + + /* Blank display and LCD */ + aty128fb_blank(VESA_POWERDOWN, info); + + /* Sleep the chip */ + aty128_set_suspend(par, 1); - fbcon_cfb32_putc(conp, p, c, yy, xx); + break; + case PBOOK_WAKE: + /* Wake the chip */ + aty128_set_suspend(par, 0); + + aty128_reset_engine(par); + wait_for_idle(par); + + /* Restore fb content */ + if (par->save_framebuffer) { + memcpy_toio(info->screen_base, + par->save_framebuffer, nb); + vfree(par->save_framebuffer); + par->save_framebuffer = 0; + } + aty128fb_blank(0, info); + break; + } + return result; } +#endif /* CONFIG_PMAC_PBOOK */ - -static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, - int yy, int xx) +int __init aty128fb_init(void) { - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb32_putcs(conp, p, s, count, yy, xx); + return pci_module_init(&aty128fb_driver); } - -static void fbcon_aty32_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) +static void __exit aty128fb_exit(void) { - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb32_clear_margins(conp, p, bottom_only); + pci_unregister_driver(&aty128fb_driver); } -static struct display_switch fbcon_aty128_32 = { - setup: fbcon_cfb32_setup, - bmove: fbcon_aty128_bmove, - clear: fbcon_cfb32_clear, - putc: fbcon_aty32_putc, - putcs: fbcon_aty32_putcs, - revc: fbcon_cfb32_revc, - clear_margins: fbcon_aty32_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; -#endif - -#ifdef MODULE MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>"); MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards"); MODULE_LICENSE("GPL"); -MODULE_PARM(noaccel, "i"); -MODULE_PARM_DESC(noaccel, "Disable hardware acceleration (0 or 1=disabled) (default=0)"); -MODULE_PARM(font, "s"); -MODULE_PARM_DESC(font, "Specify one of the compiled-in fonts (default=none)"); MODULE_PARM(mode, "s"); MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); #ifdef CONFIG_MTRR @@ -2567,58 +2335,3 @@ MODULE_PARM(nomtrr, "i"); MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); #endif -int __init -init_module(void) -{ - if (noaccel) { - noaccel = 1; - printk(KERN_INFO "aty128fb: Parameter NOACCEL set\n"); - } - if (font) { - strncpy(fontname, font, sizeof(fontname)-1); - printk(KERN_INFO "aty128fb: Parameter FONT set to %s\n", font); - } - if (mode) { - mode_option = mode; - printk(KERN_INFO "aty128fb: Parameter MODE set to %s\n", mode); - } -#ifdef CONFIG_MTRR - if (nomtrr) { - mtrr = 0; - printk(KERN_INFO "aty128fb: Parameter NOMTRR set\n"); - } -#endif - - aty128fb_init(); - return 0; -} - -void __exit -cleanup_module(void) -{ - struct fb_info_aty128 *info = board_list; - - while (board_list) { - info = board_list; - board_list = board_list->next; - - unregister_framebuffer(&info->fb_info); -#ifdef CONFIG_MTRR - if (info->mtrr.vram_valid) - mtrr_del(info->mtrr.vram, info->frame_buffer_phys, - info->vram_size); -#endif /* CONFIG_MTRR */ - iounmap(info->regbase); - iounmap(info->frame_buffer); - - release_mem_region(pci_resource_start(info->pdev, 0), - pci_resource_len(info->pdev, 0)); - release_mem_region(pci_resource_start(info->pdev, 1), - pci_resource_len(info->pdev, 1)); - release_mem_region(pci_resource_start(info->pdev, 2), - pci_resource_len(info->pdev, 2)); - - kfree(info); - } -} -#endif /* MODULE */ diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c index a57643eb7b32..43c030ff9ad7 100644 --- a/drivers/video/cfbcopyarea.c +++ b/drivers/video/cfbcopyarea.c @@ -20,30 +20,322 @@ * the native cpu endians. I also need to deal with MSB position in the word. * */ +#include <linux/config.h> +#include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/fb.h> #include <linux/slab.h> #include <asm/types.h> #include <asm/io.h> -#include <video/fbcon.h> + +#define LONG_MASK (BITS_PER_LONG - 1) #if BITS_PER_LONG == 32 -#define FB_READ fb_readl -#define FB_WRITE fb_writel +#define FB_WRITEL fb_writel +#define FB_READL fb_readl +#define SHIFT_PER_LONG 5 +#define BYTES_PER_LONG 4 #else -#define FB_READ fb_readq -#define FB_WRITE fb_writeq +#define FB_WRITEL fb_writeq +#define FB_READL fb_readq(x) +#define SHIFT_PER_LONG 6 +#define BYTES_PER_LONG 8 #endif +static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, + int src_idx, unsigned long n) +{ + unsigned long first, last; + int shift = dst_idx-src_idx, left, right; + unsigned long d0, d1; + int m; + + if (!n) + return; + + shift = dst_idx-src_idx; + first = ~0UL >> dst_idx; + last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); + + if (!shift) { + // Same alignment for source and dest + + if (dst_idx+n <= BITS_PER_LONG) { + // Single word + if (last) + first &= last; + FB_WRITEL((*src & first) | (FB_READL(dst) & ~first), dst); + } else { + // Multiple destination words + // Leading bits + if (first) { + + FB_WRITEL((*src & first) | (FB_READL(dst) & ~first), dst); + dst++; + src++; + n -= BITS_PER_LONG-dst_idx; + } + + // Main chunk + n /= BITS_PER_LONG; + while (n >= 8) { + FB_WRITEL(*src++, dst++); + FB_WRITEL(*src++, dst++); + FB_WRITEL(*src++, dst++); + FB_WRITEL(*src++, dst++); + FB_WRITEL(*src++, dst++); + FB_WRITEL(*src++, dst++); + FB_WRITEL(*src++, dst++); + FB_WRITEL(*src++, dst++); + n -= 8; + } + while (n--) + FB_WRITEL(*src++, dst++); + // Trailing bits + if (last) + FB_WRITEL((*src & last) | (FB_READL(dst) & ~last), dst); + } + } else { + // Different alignment for source and dest + + right = shift & (BITS_PER_LONG-1); + left = -shift & (BITS_PER_LONG-1); + + if (dst_idx+n <= BITS_PER_LONG) { + // Single destination word + if (last) + first &= last; + if (shift > 0) { + // Single source word + FB_WRITEL(((*src >> right) & first) | (FB_READL(dst) & ~first), dst); + } else if (src_idx+n <= BITS_PER_LONG) { + // Single source word + FB_WRITEL(((*src << left) & first) | (FB_READL(dst) & ~first), dst); + } else { + // 2 source words + d0 = *src++; + d1 = *src; + FB_WRITEL(((d0 << left | d1 >> right) & first) | (FB_READL(dst) & ~first), dst); + } + } else { + // Multiple destination words + d0 = *src++; + // Leading bits + if (shift > 0) { + // Single source word + FB_WRITEL(((d0 >> right) & first) | (FB_READL(dst) & ~first), dst); + dst++; + n -= BITS_PER_LONG-dst_idx; + } else { + // 2 source words + d1 = *src++; + FB_WRITEL(((d0 << left | d1 >> right) & first) | (FB_READL(dst) & ~first), dst); + d0 = d1; + dst++; + n -= BITS_PER_LONG-dst_idx; + } + + // Main chunk + m = n % BITS_PER_LONG; + n /= BITS_PER_LONG; + while (n >= 4) { + d1 = *src++; + FB_WRITEL(d0 << left | d1 >> right, dst++); + d0 = d1; + d1 = *src++; + FB_WRITEL(d0 << left | d1 >> right, dst++); + d0 = d1; + d1 = *src++; + FB_WRITEL(d0 << left | d1 >> right, dst++); + d0 = d1; + d1 = *src++; + FB_WRITEL(d0 << left | d1 >> right, dst++); + d0 = d1; + n -= 4; + } + while (n--) { + d1 = *src++; + FB_WRITEL(d0 << left | d1 >> right, dst++); + d0 = d1; + } + + // Trailing bits + if (last) { + if (m <= right) { + // Single source word + FB_WRITEL(((d0 << left) & last) | (FB_READL(dst) & ~last), dst); + } else { + // 2 source words + d1 = *src; + FB_WRITEL(((d0 << left | d1 >> right) & last) | (FB_READL(dst) & ~last), dst); + } + } + } + } +} + +static void bitcpy_rev(unsigned long *dst, int dst_idx, + const unsigned long *src, int src_idx, unsigned long n) +{ + unsigned long first, last; + int shift = dst_idx-src_idx, left, right; + unsigned long d0, d1; + int m; + + if (!n) + return; + + dst += (n-1)/BITS_PER_LONG; + src += (n-1)/BITS_PER_LONG; + if ((n-1) % BITS_PER_LONG) { + dst_idx += (n-1) % BITS_PER_LONG; + dst += dst_idx >> SHIFT_PER_LONG; + dst_idx &= BITS_PER_LONG-1; + src_idx += (n-1) % BITS_PER_LONG; + src += src_idx >> SHIFT_PER_LONG; + src_idx &= BITS_PER_LONG-1; + } + + shift = dst_idx-src_idx; + first = ~0UL << (BITS_PER_LONG-1-dst_idx); + last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG))); + + if (!shift) { + // Same alignment for source and dest + + if ((unsigned long)dst_idx+1 >= n) { + // Single word + if (last) + first &= last; + FB_WRITEL((*src & first) | (FB_READL(dst) & ~first), dst); + } else { + // Multiple destination words + // Leading bits + if (first) { + FB_WRITEL((*src & first) | (FB_READL(dst) & ~first), dst); + dst--; + src--; + n -= dst_idx+1; + } + + // Main chunk + n /= BITS_PER_LONG; + while (n >= 8) { + FB_WRITEL(*src--, dst--); + FB_WRITEL(*src--, dst--); + FB_WRITEL(*src--, dst--); + FB_WRITEL(*src--, dst--); + FB_WRITEL(*src--, dst--); + FB_WRITEL(*src--, dst--); + FB_WRITEL(*src--, dst--); + FB_WRITEL(*src--, dst--); + n -= 8; + } + while (n--) + FB_WRITEL(*src--, dst--); + + // Trailing bits + if (last) + FB_WRITEL((*src & last) | (FB_READL(dst) & ~last), dst); + } + } else { + // Different alignment for source and dest + + right = shift & (BITS_PER_LONG-1); + left = -shift & (BITS_PER_LONG-1); + + if ((unsigned long)dst_idx+1 >= n) { + // Single destination word + if (last) + first &= last; + if (shift < 0) { + // Single source word + FB_WRITEL((*src << left & first) | (FB_READL(dst) & ~first), dst); + } else if (1+(unsigned long)src_idx >= n) { + // Single source word + FB_WRITEL(((*src >> right) & first) | (FB_READL(dst) & ~first), dst); + } else { + // 2 source words + d0 = *src--; + d1 = *src; + FB_WRITEL(((d0 >> right | d1 << left) & first) | (FB_READL(dst) & ~first), dst); + } + } else { + // Multiple destination words + d0 = *src--; + // Leading bits + if (shift < 0) { + // Single source word + FB_WRITEL(((d0 << left) & first) | (FB_READL(dst) & ~first), dst); + dst--; + n -= dst_idx+1; + } else { + // 2 source words + d1 = *src--; + FB_WRITEL(((d0 >> right | d1 << left) & first) | (FB_READL(dst) & ~first), dst); + d0 = d1; + dst--; + n -= dst_idx+1; + } + + // Main chunk + m = n % BITS_PER_LONG; + n /= BITS_PER_LONG; + while (n >= 4) { + d1 = *src--; + FB_WRITEL(d0 >> right | d1 << left, dst--); + d0 = d1; + d1 = *src--; + FB_WRITEL(d0 >> right | d1 << left, dst--); + d0 = d1; + d1 = *src--; + FB_WRITEL(d0 >> right | d1 << left, dst--); + d0 = d1; + d1 = *src--; + FB_WRITEL(d0 >> right | d1 << left, dst--); + d0 = d1; + n -= 4; + } + while (n--) { + d1 = *src--; + FB_WRITEL(d0 >> right | d1 << left, dst--); + d0 = d1; + } + + // Trailing bits + if (last) { + if (m <= left) { + // Single source word + FB_WRITEL(((d0 >> right) & last) | (FB_READL(dst) & ~last), dst); + } else { + // 2 source words + d1 = *src; + FB_WRITEL(((d0 >> right | d1 << left) & last) | + (FB_READL(dst) & ~last), dst); + } + } + } + } +} + void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) { - int x2, y2, lineincr, shift, shift_right, shift_left, old_dx, old_dy; - int j, linesize = p->fix.line_length, bpl = sizeof(unsigned long); - unsigned long start_index, end_index, start_mask, end_mask, last; + int x2, y2, old_dx, old_dy, vxres, vyres; + unsigned long next_line = p->fix.line_length; + int dst_idx = 0, src_idx = 0, rev_copy = 0; unsigned long *dst = NULL, *src = NULL; - char *src1, *dst1; - int tmp, height; + + /* We want rotation but lack hardware to do it for us. */ + if (!p->fbops->fb_rotate && p->var.rotate) { + } + + vxres = p->var.xres_virtual; + vyres = p->var.yres_virtual; + + if (area->dx > vxres || area->sx > vxres || + area->dy > vyres || area->sy > vyres) + return; /* clip the destination */ old_dx = area->dx; @@ -57,8 +349,8 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) y2 = area->dy + area->height; area->dx = area->dx > 0 ? area->dx : 0; area->dy = area->dy > 0 ? area->dy : 0; - x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual; - y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual; + x2 = x2 < vxres ? x2 : vxres; + y2 = y2 < vyres ? y2 : vyres; area->width = x2 - area->dx; area->height = y2 - area->dy; @@ -66,165 +358,56 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) area->sx += (area->dx - old_dx); area->sy += (area->dy - old_dy); - height = area->height; - /* the source must be completely inside the virtual screen */ if (area->sx < 0 || area->sy < 0 || - (area->sx + area->width) > p->var.xres_virtual || - (area->sy + area->height) > p->var.yres_virtual) + (area->sx + area->width) > vxres || + (area->sy + area->height) > vyres) return; + + if (area->dy > area->sy || (area->dy == area->sy && area->dx > area->sx)) { + area->dy += area->height; + area->sy += area->height; + rev_copy = 1; + } - if (area->dy < area->sy - || (area->dy == area->sy && area->dx < area->sx)) { - /* start at the top */ - src1 = p->screen_base + area->sy * linesize + - ((area->sx * p->var.bits_per_pixel) >> 3); - dst1 = p->screen_base + area->dy * linesize + - ((area->dx * p->var.bits_per_pixel) >> 3); - lineincr = linesize; + dst = src = (unsigned long *)((unsigned long)p->screen_base & ~(BYTES_PER_LONG-1)); + dst_idx = src_idx = (unsigned long)p->screen_base & (BYTES_PER_LONG-1); + dst_idx += area->dy*next_line*8 + area->dx*p->var.bits_per_pixel; + src_idx += area->sy*next_line*8 + area->sx*p->var.bits_per_pixel; + + if (rev_copy) { + while (area->height--) { + dst_idx -= next_line*8; + src_idx -= next_line*8; + dst += dst_idx >> SHIFT_PER_LONG; + dst_idx &= (BYTES_PER_LONG-1); + src += src_idx >> SHIFT_PER_LONG; + src_idx &= (BYTES_PER_LONG-1); + bitcpy_rev((unsigned long*)dst, dst_idx, (unsigned long *)src, + src_idx, area->width*p->var.bits_per_pixel); + } } else { - /* start at the bottom */ - src1 = p->screen_base + (area->sy + area->height-1) * linesize - + (((area->sx + area->width - 1) * p->var.bits_per_pixel) >> 3); - dst1 = p->screen_base + (area->dy + area->height-1) * linesize - + (((area->dx + area->width - 1) * p->var.bits_per_pixel) >> 3); - lineincr = -linesize; + while (area->height--) { + dst += dst_idx >> SHIFT_PER_LONG; + dst_idx &= (BYTES_PER_LONG-1); + src += src_idx >> SHIFT_PER_LONG; + src_idx &= (BYTES_PER_LONG-1); + bitcpy((unsigned long*)dst, dst_idx, (unsigned long *)src, + src_idx, area->width*p->var.bits_per_pixel); + dst_idx += next_line*8; + src_idx += next_line*8; + } } +} - if ((BITS_PER_LONG % p->var.bits_per_pixel) == 0) { - int ppw = BITS_PER_LONG / p->var.bits_per_pixel; - int n = ((area->width * p->var.bits_per_pixel) >> 3); - - start_index = ((unsigned long) src1 & (bpl - 1)); - end_index = ((unsigned long) (src1 + n) & (bpl - 1)); - shift = ((unsigned long) dst1 & (bpl - 1)) - - ((unsigned long) src1 & (bpl - 1)); - start_mask = end_mask = 0; +#ifdef MODULE +int init_module(void) { return 0; }; +void cleanup_module(void) {}; +#endif - if (start_index) { - start_mask = -1 >> (start_index << 3); - n -= (bpl - start_index); - } +EXPORT_SYMBOL(cfb_copyarea); - if (end_index) { - end_mask = -1 << ((bpl - end_index) << 3); - n -= end_index; - } - n /= bpl; - - if (n <= 0) { - if (start_mask) { - if (end_mask) - end_mask &= start_mask; - else - end_mask = start_mask; - start_mask = 0; - } - n = 0; - } +MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); +MODULE_DESCRIPTION("Generic software accelerated copyarea"); +MODULE_LICENSE("GPL"); - if (shift) { - if (shift > 0) { - /* dest is over to right more */ - shift_right = - shift * p->var.bits_per_pixel; - shift_left = - (ppw - shift) * p->var.bits_per_pixel; - } else { - /* source is to the right more */ - shift_right = - (ppw + shift) * p->var.bits_per_pixel; - shift_left = - -shift * p->var.bits_per_pixel; - } - /* general case, positive increment */ - if (lineincr > 0) { - if (shift < 0) - n++; - do { - dst = (unsigned long *) dst1; - src = (unsigned long *) src1; - - last = (FB_READ(src) & start_mask); - - if (shift > 0) - FB_WRITE(FB_READ(dst) | (last >> shift_right), dst); - for (j = 0; j < n; j++) { - dst++; - tmp = FB_READ(src); - src++; - FB_WRITE((last << shift_left) | (tmp >> shift_right), dst); - last = tmp; - src++; - } - FB_WRITE(FB_READ(dst) | (last << shift_left), dst); - src1 += lineincr; - dst1 += lineincr; - } while (--height); - } else { - /* general case, negative increment */ - if (shift > 0) - n++; - do { - dst = (unsigned long *) dst1; - src = (unsigned long *) src1; - - last = (FB_READ(src) & end_mask); - - if (shift < 0) - FB_WRITE(FB_READ(dst) | (last >> shift_right), dst); - for (j = 0; j < n; j++) { - dst--; - tmp = FB_READ(src); - src--; - FB_WRITE((tmp << shift_left) | (last >> shift_right), dst); - last = tmp; - src--; - } - FB_WRITE(FB_READ(dst) | (last >> shift_right), dst); - src1 += lineincr; - dst1 += lineincr; - } while (--height); - } - } else { - /* no shift needed */ - if (lineincr > 0) { - /* positive increment */ - do { - dst = (unsigned long *) (dst1 - start_index); - src = (unsigned long *) (src1 - start_index); - - if (start_mask) - FB_WRITE(FB_READ(src) | start_mask, dst); - - for (j = 0; j < n; j++) { - FB_WRITE(FB_READ(src), dst); - dst++; - src++; - } - - if (end_mask) - FB_WRITE(FB_READ(src) | end_mask, dst); - src1 += lineincr; - dst1 += lineincr; - } while (--height); - } else { - /* negative increment */ - do { - dst = (unsigned long *) dst1; - src = (unsigned long *) src1; - - if (start_mask) - FB_WRITE(FB_READ(src) | start_mask, dst); - for (j = 0; j < n; j++) { - FB_WRITE(FB_READ(src), dst); - dst--; - src--; - } - src1 += lineincr; - dst1 += lineincr; - } while (--height); - } - } - } -} diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c index d052a89bd5eb..fd272386e6c3 100644 --- a/drivers/video/cfbfillrect.c +++ b/drivers/video/cfbfillrect.c @@ -17,173 +17,439 @@ * the native cpu endians. I also need to deal with MSB position in the word. * */ +#include <linux/config.h> +#include <linux/module.h> #include <linux/string.h> #include <linux/fb.h> #include <asm/types.h> -#include <video/fbcon.h> #if BITS_PER_LONG == 32 -#define FB_READ fb_readl -#define FB_WRITE fb_writel +#define FB_WRITEL fb_writel +#define FB_READL fb_readl +#define BYTES_PER_LONG 4 +#define SHIFT_PER_LONG 5 #else -#define FB_READ fb_readq -#define FB_WRITE fb_writeq +#define FB_WRITEL fb_writeq +#define FB_READL fb_readq +#define BYTES_PER_LONG 8 +#define SHIFT_PER_LONG 6 #endif -void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) +#define EXP1(x) 0xffffffffU*x +#define EXP2(x) 0x55555555U*x +#define EXP4(x) 0x11111111U*0x ## x + +typedef u32 pixel_t; + +static const u32 bpp1tab[2] = { + EXP1(0), EXP1(1) +}; + +static const u32 bpp2tab[4] = { + EXP2(0), EXP2(1), EXP2(2), EXP2(3) +}; + +static const u32 bpp4tab[16] = { + EXP4(0), EXP4(1), EXP4(2), EXP4(3), EXP4(4), EXP4(5), EXP4(6), EXP4(7), + EXP4(8), EXP4(9), EXP4(a), EXP4(b), EXP4(c), EXP4(d), EXP4(e), EXP4(f) +}; + + /* + * Compose two values, using a bitmask as decision value + * This is equivalent to (a & mask) | (b & ~mask) + */ + +static inline unsigned long comp(unsigned long a, unsigned long b, + unsigned long mask) { - unsigned long start_index, end_index, start_mask = 0, end_mask = 0; - unsigned long height, ppw, fg, fgcolor; - int i, n, x2, y2, linesize = p->fix.line_length; - int bpl = sizeof(unsigned long); - unsigned long *dst; - char *dst1; + return ((a ^ b) & mask) ^ b; +} - if (!rect->width || !rect->height) - return; +static inline u32 pixel_to_pat32(const struct fb_info *p, pixel_t pixel) +{ + u32 pat = pixel; - /* We could use hardware clipping but on many cards you get around - * hardware clipping by writing to framebuffer directly. */ - x2 = rect->dx + rect->width; - y2 = rect->dy + rect->height; - x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual; - y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual; - rect->width = x2 - rect->dx; - height = y2 - rect->dy; + switch (p->var.bits_per_pixel) { + case 1: + pat = bpp1tab[pat]; + break; - /* Size of the scanline in bytes */ - n = (rect->width * (p->var.bits_per_pixel >> 3)); - ppw = BITS_PER_LONG / p->var.bits_per_pixel; + case 2: + pat = bpp2tab[pat]; + break; - dst1 = p->screen_base + (rect->dy * linesize) + - (rect->dx * (p->var.bits_per_pixel >> 3)); - start_index = ((unsigned long) dst1 & (bpl - 1)); - end_index = ((unsigned long) (dst1 + n) & (bpl - 1)); + case 4: + pat = bpp4tab[pat]; + break; - if (p->fix.visual == FB_VISUAL_TRUECOLOR) - fg = fgcolor = ((u32 *) (p->pseudo_palette))[rect->color]; - else - fg = fgcolor = rect->color; + case 8: + pat |= pat << 8; + // Fall through + case 16: + pat |= pat << 16; + // Fall through + case 32: + break; + } + return pat; +} + + /* + * Expand a pixel value to a generic 32/64-bit pattern and rotate it to + * the correct start position + */ + +static inline unsigned long pixel_to_pat(const struct fb_info *p, pixel_t pixel, int left) +{ + unsigned long pat = pixel; + u32 bpp = p->var.bits_per_pixel; + int i; + + /* expand pixel value */ + for (i = bpp; i < BITS_PER_LONG; i *= 2) + pat |= pat << i; - for (i = 0; i < ppw - 1; i++) { - fg <<= p->var.bits_per_pixel; - fg |= fgcolor; + /* rotate pattern to correct start position */ + pat = pat << left | pat >> (bpp-left); + return pat; +} + + /* + * Unaligned 32-bit pattern fill using 32/64-bit memory accesses + */ + +void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n) +{ + unsigned long val = pat; + unsigned long first, last; + + if (!n) + return; + +#if BITS_PER_LONG == 64 + val |= val << 32; +#endif + + first = ~0UL >> dst_idx; + last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); + + if (dst_idx+n <= BITS_PER_LONG) { + // Single word + if (last) + first &= last; + FB_WRITEL(comp(val, FB_READL(dst), first), dst); + } else { + // Multiple destination words + // Leading bits + if (first) { + FB_WRITEL(comp(val, FB_READL(dst), first), dst); + dst++; + n -= BITS_PER_LONG-dst_idx; + } + + // Main chunk + n /= BITS_PER_LONG; + while (n >= 8) { + FB_WRITEL(val, dst++); + FB_WRITEL(val, dst++); + FB_WRITEL(val, dst++); + FB_WRITEL(val, dst++); + FB_WRITEL(val, dst++); + FB_WRITEL(val, dst++); + FB_WRITEL(val, dst++); + FB_WRITEL(val, dst++); + n -= 8; + } + while (n--) + FB_WRITEL(val, dst++); + + // Trailing bits + if (last) + FB_WRITEL(comp(val, FB_READL(dst), first), dst); } +} + - if (start_index) { - start_mask = fg << (start_index << 3); - n -= (bpl - start_index); + /* + * Unaligned generic pattern fill using 32/64-bit memory accesses + * The pattern must have been expanded to a full 32/64-bit value + * Left/right are the appropriate shifts to convert to the pattern to be + * used for the next 32/64-bit word + */ + +void bitfill(unsigned long *dst, int dst_idx, unsigned long pat, int left, + int right, u32 n) +{ + unsigned long first, last; + + if (!n) + return; + + first = ~0UL >> dst_idx; + last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); + + if (dst_idx+n <= BITS_PER_LONG) { + // Single word + if (last) + first &= last; + FB_WRITEL(comp(pat, FB_READL(dst), first), dst); + } else { + // Multiple destination words + // Leading bits + if (first) { + FB_WRITEL(comp(pat, FB_READL(dst), first), dst); + dst++; + pat = pat << left | pat >> right; + n -= BITS_PER_LONG-dst_idx; + } + + // Main chunk + n /= BITS_PER_LONG; + while (n >= 4) { + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + n -= 4; + } + while (n--) { + FB_WRITEL(pat, dst++); + pat = pat << left | pat >> right; + } + + // Trailing bits + if (last) + FB_WRITEL(comp(pat, FB_READL(dst), first), dst); } +} - if (end_index) { - end_mask = fg >> ((bpl - end_index) << 3); - n -= end_index; +void bitfill32_rev(unsigned long *dst, int dst_idx, u32 pat, u32 n) +{ + unsigned long val = pat, dat; + unsigned long first, last; + + if (!n) + return; + +#if BITS_PER_LONG == 64 + val |= val << 32; +#endif + + first = ~0UL >> dst_idx; + last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); + + if (dst_idx+n <= BITS_PER_LONG) { + // Single word + if (last) + first &= last; + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ val, dat, first), dst); + } else { + // Multiple destination words + // Leading bits + if (first) { + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ val, dat, first), dst); + dst++; + n -= BITS_PER_LONG-dst_idx; + } + + // Main chunk + n /= BITS_PER_LONG; + while (n >= 8) { + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + n -= 8; + } + while (n--) { + FB_WRITEL(FB_READL(dst) ^ val, dst); + dst++; + } + // Trailing bits + if (last) { + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ val, dat, first), dst); + } } +} - n = n / bpl; - if (n <= 0) { - if (start_mask) { - if (end_mask) - end_mask &= start_mask; - else - end_mask = start_mask; - start_mask = 0; + /* + * Unaligned generic pattern fill using 32/64-bit memory accesses + * The pattern must have been expanded to a full 32/64-bit value + * Left/right are the appropriate shifts to convert to the pattern to be + * used for the next 32/64-bit word + */ + +void bitfill_rev(unsigned long *dst, int dst_idx, unsigned long pat, int left, + int right, u32 n) +{ + unsigned long first, last, dat; + + if (!n) + return; + + first = ~0UL >> dst_idx; + last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); + + if (dst_idx+n <= BITS_PER_LONG) { + // Single word + if (last) + first &= last; + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ pat, dat, first), dst); + } else { + // Multiple destination words + // Leading bits + if (first) { + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ pat, dat, first), dst); + dst++; + pat = pat << left | pat >> right; + n -= BITS_PER_LONG-dst_idx; + } + + // Main chunk + n /= BITS_PER_LONG; + while (n >= 4) { + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + n -= 4; + } + while (n--) { + FB_WRITEL(FB_READL(dst) ^ pat, dst); + dst++; + pat = pat << left | pat >> right; + } + + // Trailing bits + if (last) { + dat = FB_READL(dst); + FB_WRITEL(comp(dat ^ pat, dat, first), dst); } - n = 0; } +} - if ((BITS_PER_LONG % p->var.bits_per_pixel) == 0) { +void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) +{ + unsigned long height, fg; + unsigned long x2, y2, vxres, vyres; + unsigned long *dst; + int dst_idx, left; + u32 bpp = p->var.bits_per_pixel; + + /* We want rotation but lack hardware to do it for us. */ + if (!p->fbops->fb_rotate && p->var.rotate) { + } + + vxres = p->var.xres_virtual; + vyres = p->var.yres_virtual; + + if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres) + return; + + /* We could use hardware clipping but on many cards you get around + * hardware clipping by writing to framebuffer directly. */ + + x2 = rect->dx + rect->width; + y2 = rect->dy + rect->height; + x2 = x2 < vxres ? x2 : vxres; + y2 = y2 < vyres ? y2 : vyres; + rect->width = x2 - rect->dx; + height = y2 - rect->dy; + + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR ) + fg = ((u32 *) (p->pseudo_palette))[rect->color]; + else + fg = rect->color; + + dst = (unsigned long *)((unsigned long)p->screen_base & ~(BYTES_PER_LONG-1)); + dst_idx = ((unsigned long)p->screen_base & (BYTES_PER_LONG-1))*8; + dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; + /* FIXME For now we support 1-32 bpp only */ + left = BITS_PER_LONG % bpp; + if (!left) { + u32 pat = pixel_to_pat32(p, fg); + void (*fill_op32)(unsigned long *dst, int dst_idx, u32 pat, u32 n) = NULL; + switch (rect->rop) { - case ROP_COPY: - do { - /* Word align to increases performace :-) */ - dst = (unsigned long *) (dst1 - start_index); - - if (start_mask) { - FB_WRITE(FB_READ(dst) | - start_mask, dst); - dst++; - } - - for (i = 0; i < n; i++) { - FB_WRITE(fg, dst); - dst++; - } - - if (end_mask) - FB_WRITE(FB_READ(dst) | end_mask, - dst); - dst1 += linesize; - } while (--height); - break; case ROP_XOR: - do { - dst = (unsigned long *) (dst1 - start_index); - - if (start_mask) { - FB_WRITE(FB_READ(dst) ^ - start_mask, dst); - dst++; - } - - for (i = 0; i < n; i++) { - FB_WRITE(FB_READ(dst) ^ fg, dst); - dst++; - } - - if (end_mask) { - FB_WRITE(FB_READ(dst) ^ end_mask, - dst); - } - dst1 += linesize; - } while (--height); + fill_op32 = bitfill32_rev; break; + case ROP_COPY: + default: + fill_op32 = bitfill32; + break; + } + while (height--) { + dst += dst_idx >> SHIFT_PER_LONG; + dst_idx &= (BITS_PER_LONG-1); + fill_op32(dst, dst_idx, pat, rect->width*bpp); + dst_idx += p->fix.line_length*8; } } else { - /* Odd modes like 24 or 80 bits per pixel */ - start_mask = fg >> (start_index * p->var.bits_per_pixel); - end_mask = fg << (end_index * p->var.bits_per_pixel); - /* start_mask =& PFILL24(x1,fg); - end_mask_or = end_mask & PFILL24(x1+width-1,fg); */ - - n = (rect->width - start_index - end_index) / ppw; - + unsigned long pat = pixel_to_pat(p, fg, (left-dst_idx) % bpp); + int right = bpp-left; + int r; + void (*fill_op)(unsigned long *dst, int dst_idx, unsigned long pat, + int left, int right, u32 n) = NULL; + switch (rect->rop) { - case ROP_COPY: - do { - dst = (unsigned long *) dst1; - if (start_mask) - *dst |= start_mask; - if ((start_index + rect->width) > ppw) - dst++; - - /* XXX: slow */ - for (i = 0; i < n; i++) { - *dst++ = fg; - } - if (end_mask) - *dst |= end_mask; - dst1 += linesize; - } while (--height); - break; case ROP_XOR: - do { - dst = (unsigned long *) dst1; - if (start_mask) - *dst ^= start_mask; - if ((start_mask + rect->width) > ppw) - dst++; - - for (i = 0; i < n; i++) { - *dst++ ^= fg; /* PFILL24(fg,x1+i); */ - } - if (end_mask) - *dst ^= end_mask; - dst1 += linesize; - } while (--height); + fill_op = bitfill_rev; + break; + case ROP_COPY: + default: + fill_op = bitfill; break; } + while (height--) { + dst += dst_idx >> SHIFT_PER_LONG; + dst_idx &= (BITS_PER_LONG-1); + fill_op(dst, dst_idx, pat, left, right, rect->width*bpp); + r = (p->fix.line_length*8) % bpp; + pat = pat << (bpp-r) | pat >> r; + dst_idx += p->fix.line_length*8; + } } - return; } + +#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>"); +MODULE_DESCRIPTION("Generic software accelerated fill rectangle"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index e3f138ad21b3..11a87a694a85 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -22,17 +22,24 @@ * FIXME * The code for 24 bit is horrible. It copies byte by byte size instead of * 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_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 * the native cpu endians. I also need to deal with MSB position in the word. * */ +#include <linux/config.h> +#include <linux/module.h> #include <linux/string.h> #include <linux/fb.h> #include <asm/types.h> -#include <video/fbcon.h> - #define DEBUG #ifdef DEBUG @@ -41,91 +48,308 @@ #define DPRINTK(fmt, args...) #endif +static u32 cfb_tab8[] = { +#if defined(__BIG_ENDIAN) + 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, + 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, + 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, + 0xffff0000,0xffff00ff,0xffffff00,0xffffffff +#elif defined(__LITTLE_ENDIAN) + 0x00000000,0xff000000,0x00ff0000,0xffff0000, + 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, + 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, + 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff +#else +#error FIXME: No endianness?? +#endif +}; + +static u32 cfb_tab16[] = { +#if defined(__BIG_ENDIAN) + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff +#elif defined(__LITTLE_ENDIAN) + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff +#else +#error FIXME: No endianness?? +#endif +}; + +static u32 cfb_tab32[] = { + 0x00000000, 0xffffffff +}; + +#if BITS_PER_LONG == 32 +#define FB_WRITEL fb_writel +#define FB_READL fb_readl +#else +#define FB_WRITEL fb_writeq +#define FB_READL fb_readq +#endif + +#if defined (__BIG_ENDIAN) +#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)) +#else +#define LEFT_POS(bpp) (0) +#define NEXT_POS(pos, bpp) ((pos) += (bpp)) +#define SHIFT_HIGH(val, bits) ((val) << (bits)) +#define SHIFT_LOW(val, bits) ((val) >> (bits)) +#endif + +static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1, + unsigned long start_index, unsigned long pitch_index) +{ + /* Draw the penguin */ + int i, n; + unsigned long bitmask = SHIFT_LOW(~0UL, BITS_PER_LONG - p->var.bits_per_pixel); + unsigned long *palette = (unsigned long *) p->pseudo_palette; + unsigned long *dst, *dst2, color = 0, val, shift; + unsigned long null_bits = BITS_PER_LONG - p->var.bits_per_pixel; + u8 *src = image->data; + + dst2 = (unsigned long *) dst1; + for (i = image->height; i--; ) { + n = image->width; + dst = (unsigned long *) dst1; + shift = 0; + val = 0; + + if (start_index) { + unsigned long start_mask = ~(SHIFT_HIGH(~0UL, start_index)); + + val = FB_READL(dst) & start_mask; + shift = start_index; + } + while (n--) { + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR ) + color = palette[*src] & bitmask; + else + color = *src & bitmask; + 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_LONG - shift); + } + shift += p->var.bits_per_pixel; + shift &= (BITS_PER_LONG - 1); + src++; + } + if (shift) { + unsigned long end_mask = SHIFT_HIGH(~0UL, shift); + + FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); + } + dst1 += p->fix.line_length; + if (pitch_index) { + dst2 += p->fix.line_length; + dst1 = (char *) dst2; + (unsigned long) dst1 &= ~(sizeof(unsigned long) - 1); + + start_index += pitch_index; + start_index &= BITS_PER_LONG - 1; + } + } +} + +static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1, + unsigned long fgcolor, unsigned long bgcolor, + unsigned long start_index, unsigned long pitch_index) +{ + 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 = (unsigned long *) dst1; + + for (i = image->height; i--; ) { + shift = 0; + val = 0; + j = image->width; + dst = (unsigned long *) dst1; + + /* write leading bits */ + if (start_index) { + unsigned long start_mask = ~(SHIFT_HIGH(~0UL, start_index)); + + val = FB_READL(dst) & start_mask; + shift = start_index; + } + while (j--) { + l--; + if (*src & (1 << l)) + color = fgcolor; + else + color = bgcolor; + val |= SHIFT_HIGH(color, shift); + + /* Did the bitshift spill bits to the next long? */ + if (shift >= null_bits) { + FB_WRITEL(val, dst++); + if (shift == null_bits) + val = 0; + else + val = SHIFT_LOW(color, BITS_PER_LONG - shift); + } + shift += bpp; + shift &= (BITS_PER_LONG - 1); + if (!l) { l = 8; src++; }; + } + /* write trailing bits */ + if (shift) { + unsigned long end_mask = SHIFT_HIGH(~0UL, shift); + + FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); + } + dst1 += pitch; + + if (pitch_index) { + dst2 += pitch; + dst1 = (char *) dst2; + (unsigned long) dst1 &= ~(sizeof(unsigned long) - 1); + + start_index += pitch_index; + start_index &= BITS_PER_LONG - 1; + } + + } +} + +static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1, + unsigned long fgcolor, unsigned long bgcolor) +{ + int i, j, k, l = 8, n; + 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; + + switch (ppw) { + case 4: + tab = cfb_tab8; + break; + case 2: + tab = cfb_tab16; + break; + case 1: + tab = cfb_tab32; + break; + } + + for (i = ppw-1; i--; ) { + fgx <<= bpp; + bgx <<= bpp; + fgx |= fgcolor; + bgx |= bgcolor; + } + + n = ((image->width + 7) / 8); + pad = (n * 8) - image->width; + n = image->width % ppw; + + bit_mask = (1 << ppw) - 1; + eorx = fgx ^ bgx; + + k = image->width/ppw; + + for (i = image->height; i--; ) { + dst = (unsigned long *) dst1; + + for (j = k; j--; ) { + l -= ppw; + end_mask = tab[(*src >> l) & bit_mask]; + FB_WRITEL((end_mask & eorx)^bgx, dst++); + if (!l) { l = 8; src++; } + } + if (n) { + end_mask = 0; + ppos = LEFT_POS(bpp); + for (j = n; j > 0; j--) { + l--; + if (*src & (1 << l)) + end_mask |= tmp << ppos; + NEXT_POS(ppos, bpp); + if (!l) { l = 8; src++; } + } + FB_WRITEL((end_mask & eorx)^bgx, dst++); + } + l -= pad; + dst1 += p->fix.line_length; + } +} + void cfb_imageblit(struct fb_info *p, struct fb_image *image) { - int pad, ppw; - int x2, y2, n, i, j, k, l = 7; - unsigned long tmp = ~0 << (BITS_PER_LONG - p->var.bits_per_pixel); - unsigned long fgx, bgx, fgcolor, bgcolor, eorx; - unsigned long end_mask; - unsigned long *dst = NULL; + int x2, y2, vxres, vyres; + unsigned long fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; + unsigned long bpl = sizeof(unsigned long), bpp = p->var.bits_per_pixel; u8 *dst1; - u8 *src; + vxres = p->var.xres_virtual; + vyres = p->var.yres_virtual; /* * We could use hardware clipping but on many cards you get around hardware * clipping by writing to framebuffer directly like we are doing here. */ + if (image->dx > vxres || + image->dy > vyres) + return; + x2 = image->dx + image->width; y2 = image->dy + image->height; image->dx = image->dx > 0 ? image->dx : 0; image->dy = image->dy > 0 ? image->dy : 0; - x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual; - y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual; + x2 = x2 < vxres ? x2 : vxres; + y2 = y2 < vyres ? y2 : vyres; image->width = x2 - image->dx; image->height = y2 - image->dy; - - dst1 = p->screen_base + image->dy * p->fix.line_length + - ((image->dx * p->var.bits_per_pixel) >> 3); - - ppw = BITS_PER_LONG/p->var.bits_per_pixel; - src = image->data; + bitstart = (image->dy * p->fix.line_length * 8) + (image->dx * bpp); + start_index = bitstart & (BITS_PER_LONG - 1); + pitch_index = (p->fix.line_length & (bpl - 1)) * 8; - if (image->depth == 1) { + bitstart /= 8; + bitstart &= ~(bpl - 1); + dst1 = p->screen_base + bitstart; - if (p->fix.visual == FB_VISUAL_TRUECOLOR) { - fgx = fgcolor = ((u32 *)(p->pseudo_palette))[image->fg_color]; - bgx = bgcolor = ((u32 *)(p->pseudo_palette))[image->bg_color]; + if (image->depth == 1) { + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR) { + fgcolor = ((u32 *)(p->pseudo_palette))[image->fg_color]; + bgcolor = ((u32 *)(p->pseudo_palette))[image->bg_color]; } else { - fgx = fgcolor = image->fg_color; - bgx = bgcolor = image->bg_color; + fgcolor = image->fg_color; + bgcolor = image->bg_color; } - - for (i = 0; i < ppw-1; i++) { - fgx <<= p->var.bits_per_pixel; - bgx <<= p->var.bits_per_pixel; - fgx |= fgcolor; - bgx |= bgcolor; - } - eorx = fgx ^ bgx; - n = ((image->width + 7) >> 3); - pad = (n << 3) - image->width; - n = image->width % ppw; - - for (i = 0; i < image->height; i++) { - dst = (unsigned long *) dst1; - for (j = image->width/ppw; j > 0; j--) { - end_mask = 0; - - for (k = ppw; k > 0; k--) { - if (test_bit(l, (unsigned long *) src)) - end_mask |= (tmp >> (p->var.bits_per_pixel*(k-1))); - l--; - if (l < 0) { l = 7; src++; } - } - fb_writel((end_mask & eorx)^bgx, dst); - dst++; - } - - if (n) { - end_mask = 0; - for (j = n; j > 0; j--) { - if (test_bit(l, (unsigned long *) src)) - end_mask |= (tmp >> (p->var.bits_per_pixel*(j-1))); - l--; - if (l < 0) { l = 7; src++; } - } - fb_writel((end_mask & eorx)^bgx, dst); - dst++; - } - l -= pad; - dst1 += p->fix.line_length; - } - } else { - /* Draw the penguin */ - n = ((image->width * p->var.bits_per_pixel) >> 3); - end_mask = 0; + 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 + slow_imageblit(image, p, dst1, fgcolor, bgcolor, start_index, pitch_index); } + else if (image->depth == bpp) + 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>"); +MODULE_DESCRIPTION("Generic software accelerated imaging drawing"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 4ad4e2e30ae5..ee43294488f1 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -562,7 +562,7 @@ static void __init init_chips(struct fb_info_chips *p) } printk("fb%d: Chips 65550 frame buffer (%dK RAM detected)\n", - GET_FB_IDX(p->info.node), p->fix.smem_len / 1024); + minor(p->info.node), p->fix.smem_len / 1024); chips_hw_init(p); diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c index 14a67d332255..e54209c0728b 100644 --- a/drivers/video/clps711xfb.c +++ b/drivers/video/clps711xfb.c @@ -27,8 +27,6 @@ #include <linux/proc_fs.h> #include <linux/delay.h> -#include <video/fbcon.h> - #include <asm/hardware.h> #include <asm/mach-types.h> #include <asm/uaccess.h> @@ -216,14 +214,12 @@ static struct fb_ops clps7111fb_ops = { .owner = THIS_MODULE, .fb_check_var = clps7111fb_check_var, .fb_set_par = clps7111fb_set_par, - .fb_set_var = gen_set_var, - .fb_set_cmap = gen_set_cmap, - .fb_get_cmap = gen_get_cmap, .fb_setcolreg = clps7111fb_setcolreg, .fb_blank = clps7111fb_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; static int @@ -368,20 +364,15 @@ int __init clps711xfb_init(void) { int err = -ENOMEM; - cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL); + cfb = kmalloc(sizeof(*cfb), GFP_KERNEL); if (!cfb) goto out; - memset(cfb, 0, sizeof(*cfb) + sizeof(struct display)); + memset(cfb, 0, sizeof(*cfb)); strcpy(cfb->fix.id, "clps711x"); - cfb->currcon = -1; cfb->fbops = &clps7111fb_ops; - cfb->changevar = NULL; - cfb->switch_con = gen_switch; - cfb->updatevar = gen_update_var; cfb->flags = FBINFO_FLAG_DEFAULT; - cfb->disp = (struct display *)(cfb + 1); clps711x_guess_lcd_params(cfb); @@ -422,7 +413,6 @@ int __init clps711xfb_init(void) clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR); } - gen_set_var(&cfb->var, -1, cfb); err = register_framebuffer(cfb); out: return err; diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig new file mode 100644 index 000000000000..bf88c5c88d8d --- /dev/null +++ b/drivers/video/console/Kconfig @@ -0,0 +1,221 @@ +# +# Video configuration +# + +menu "Console display driver support" + +config VGA_CONSOLE + bool "VGA text console" + depends on !ARCH_ACORN && !ARCH_EBSA110 || !4xx && !8xx + help + Saying Y here will allow you to use Linux in text mode through a + display that complies with the generic VGA standard. Virtually + everyone wants that. + + The program SVGATextMode can be used to utilize SVGA video cards to + their full potential in text mode. Download it from + <ftp://ibiblio.org/pub/Linux/utils/console/>. + + Say Y. + +# if [ "$CONFIG_PCI" = "y" -a "$CONFIG_VGA_CONSOLE" = "y" ]; then +# bool ' Allow VGA on any bus?' CONFIG_VGA_HOSE +# if [ "$CONFIG_VGA_HOSE" = "y" ]; then +# define_bool CONFIG_DUMMY_CONSOLE y +# fi +# fi + +config VIDEO_SELECT + bool "Video mode selection support" + depends on (X86 || X86_64) && VGA_CONSOLE + ---help--- + This enables support for text mode selection on kernel startup. If + you want to take advantage of some high-resolution text mode your + card's BIOS offers, but the traditional Linux utilities like + SVGATextMode don't, you can say Y here and set the mode using the + "vga=" option from your boot loader (lilo or loadlin) or set + "vga=ask" which brings up a video mode menu on kernel startup. (Try + "man bootparam" or see the documentation of your boot loader about + how to pass options to the kernel.) + + Read the file <file:Documentation/svga.txt> for more information + about the Video mode selection support. If unsure, say N. + +config MDA_CONSOLE + tristate "MDA text console (dual-headed) (EXPERIMENTAL)" + ---help--- + Say Y here if you have an old MDA or monochrome Hercules graphics + adapter in your system acting as a second head ( = video card). You + will then be able to use two monitors with your Linux system. Do not + say Y here if your MDA card is the primary card in your system; the + normal VGA driver will handle it. + + This 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 mdacon.o. If you want to compile it as + a module, say M here and read <file:Documentation/modules.txt>. + + If unsure, say N. + +config SGI_NEWPORT_CONSOLE + tristate "SGI Newport Console support" + depends on SGI_IP22 + help + Say Y here if you want the console on the Newport aka XL graphics + card of your Indy. Most people say Y here. + +# bool 'IODC console' CONFIG_IODC_CONSOLE +config STI_CONSOLE + bool "STI console" + depends on PARISC + 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 PROM_CONSOLE + bool "PROM console" + depends on SPARC32 || SPARC64 + help + Say Y to build a console driver for Sun machines that uses the + terminal emulation built into their console PROMS. + +config DUMMY_CONSOLE + bool + depends on !PROM_CONSOLE=y || VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y || !IODC_CONSOLE && GSC_PS2 + default y + +config FRAMEBUFFER_CONSOLE + tristate "Framebuffer Console support" + depends on FB + +config PCI_CONSOLE + bool + depends on FRAMEBUFFER_CONSOLE + default y + +config FBCON_ADVANCED + bool "Advanced low level driver options" + depends on FRAMEBUFFER_CONSOLE + ---help--- + The frame buffer console uses character drawing routines that are + tailored to the specific organization of pixels in the memory of + your graphics hardware. These are called the low level frame buffer + console drivers. Note that they are used for text console output + only; they are NOT needed for graphical applications. + + If you say N here, the needed low level drivers are automatically + enabled, depending on what frame buffer devices you selected above. + This is recommended for most users. + + If you say Y here, you have more fine-grained control over which low + level drivers are enabled. You can e.g. leave out low level drivers + for color depths you do not intend to use for text consoles. + + Low level frame buffer console drivers can be modules ( = code which + can be inserted and removed from the running kernel whenever you + want). The modules will be called fbcon-*.o. If you want to compile + (some of) them as modules, read <file:Documentation/modules.txt>. + + 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" + depends on FRAMEBUFFER_CONSOLE && (!SPARC32 && !SPARC64 && FONTS || SPARC32 || SPARC64) + help + This is the high resolution console font for Sun machines. Say Y. + +config FONT_SUN12x22 + bool "Sparc console 12x22 font (not supported by all drivers)" + depends on FRAMEBUFFER_CONSOLE && !FONTWIDTH8_ONLY && (!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 + standard font is unreadable for you, say Y, otherwise say N. + +config FONTS + bool "Select other fonts" if SPARC32 || SPARC64 + depends on FRAMEBUFFER_CONSOLE + help + Say Y here if you would like to use fonts other than the default + your frame buffer console usually use. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about foreign fonts. + + If unsure, say N (the default choices are safe). + +config FONTS + prompt "Select compiled-in fonts" + depends on FRAMEBUFFER_CONSOLE && !SPARC32 && !SPARC64 + +config FONT_8x8 + bool "VGA 8x8 font" if FONTS + depends on FRAMEBUFFER_CONSOLE + default y if !SPARC32 && !SPARC64 && !FONTS + help + This is the "high resolution" font for the VGA frame buffer (the one + provided by the text console 80x50 (and higher) modes). + + Note that this is a poor quality font. The VGA 8x16 font is quite a + lot more readable. + + Given the resolution provided by the frame buffer device, answer N + here is safe. + +config FONT_8x16 + bool "VGA 8x16 font" if FONTS + depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y + default y if !SPARC32 && !SPARC64 && !FONTS + help + This is the "high resolution" font for the VGA frame buffer (the one + provided by the VGA text console 80x25 mode. + + If unsure, say Y. + +config FONT_6x11 + bool "Mac console 6x11 font (not supported by all drivers)" if FONTS + depends on FRAMEBUFFER_CONSOLE && !FONTWIDTH8_ONLY + default y if !SPARC32 && !SPARC64 && !FONTS && MAC + help + Small console font with Macintosh-style high-half glyphs. Some Mac + framebuffer drivers don't support this one at all. + +config FONT_PEARL_8x8 + bool "Pearl (old m68k) console 8x8 font" if FONTS + depends on FRAMEBUFFER_CONSOLE + default y if !SPARC32 && !SPARC64 && !FONTS && AMIGA + help + Small console font with PC-style control-character and high-half + glyphs. + +config FONT_ACORN_8x8 + bool "Acorn console 8x8 font" if FONTS + depends on FRAMEBUFFER_CONSOLE + default y if !SPARC32 && !SPARC64 && !FONTS && ARM && ARCH_ACORN + help + Small console font with PC-style control characters and high-half + glyphs. + +config FONT_MINI_4x6 + bool "Mini 4x6 font" + depends on !SPARC32 && !SPARC64 && FONTS + +endmenu + diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile new file mode 100644 index 000000000000..0e5097734e76 --- /dev/null +++ b/drivers/video/console/Makefile @@ -0,0 +1,61 @@ +# Makefile for the Linux graphics to console drivers. +# 5 Aug 1999, James Simmons, <mailto:jsimmons@users.sf.net> +# Rewritten to use lists instead of if-statements. + +# All of the (potential) objects that export symbols. +# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. + +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 + +# Each configuration option enables a list of files. + +obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o +obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o +obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o +obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o +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 + +# Files generated that shall be removed upon make clean +clean-files := promcon_tbl.c + +include $(TOPDIR)/Rules.make + +$(obj)/promcon_tbl.c: $(src)/prom.uni + $(objtree)/scripts/conmakehash $< | \ + sed -e '/#include <[^>]*>/p' -e 's/types/init/' \ + -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > $@ + diff --git a/drivers/video/dummycon.c b/drivers/video/console/dummycon.c index 82686f4b2633..ba38857c8e3e 100644 --- a/drivers/video/dummycon.c +++ b/drivers/video/console/dummycon.c @@ -9,7 +9,6 @@ #include <linux/kdev_t.h> #include <linux/tty.h> #include <linux/console.h> -#include <linux/console_struct.h> #include <linux/vt_kern.h> #include <linux/init.h> @@ -33,14 +32,14 @@ static const char *dummycon_startup(void) return "dummy device"; } -static void dummycon_init(struct vc_data *conp, int init) +static void dummycon_init(struct vc_data *vc, int init) { - conp->vc_can_do_color = 1; + vc->vc_can_do_color = 1; if (init) { - conp->vc_cols = DUMMY_COLUMNS; - conp->vc_rows = DUMMY_ROWS; + vc->vc_cols = DUMMY_COLUMNS; + vc->vc_rows = DUMMY_ROWS; } else - vc_resize_con(DUMMY_ROWS, DUMMY_COLUMNS, conp->vc_num); + vc_resize(vc->vc_num, DUMMY_COLUMNS, DUMMY_ROWS); } static int dummycon_dummy(void) diff --git a/drivers/video/fbcon-sti.c b/drivers/video/console/fbcon-sti.c index ef6b9a49d119..35015f8c5592 100644 --- a/drivers/video/fbcon-sti.c +++ b/drivers/video/console/fbcon-sti.c @@ -17,42 +17,18 @@ #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 "sti.h" - -/* Translate an address as it would be found in a 2048x2048x1 bit frame - * buffer into a logical address Artist actually expects. Addresses fed - * into Artist look like this: - * fixed Y X - * FFFF FFFF LLLL LLLL LLLC CCCC CCCC CC00 - * - * our "RAM" addresses look like this: - * - * FFFF FFFF 0000 0LLL LLLL LLLL CCCC CCCC [CCC] - * - * */ +#include "../sticore.h" static inline u32 ram2log(void * addr) { - u32 a = (unsigned long) addr; - u32 r; - -#if 0 - r = a & 0xff000000; /* fixed part */ - r += ((a & 0x000000ff) << 5); - r += ((a & 0x00ffff00) << 3); -#else - r = a & 0xff000000; /* fixed part */ - r += ((a & 0x000000ff) << 5); - r += ((a & 0x0007ff00) << 5); -#endif - - return r; + return (unsigned long) addr; } /* All those functions need better names. */ @@ -74,30 +50,6 @@ memcpy_fromhp_tohp(void *dest, void *src, int count) } } -static void -memcpy_tohp(void *dest, void *src, int count) -{ - unsigned long d = (unsigned long) dest; - u32 *s = (u32 *)src; - - count += 3; - count &= ~3; /* XXX */ - - d = ram2log(dest); - - while(count) { - count--; - gsc_writel(*s++, d); - d += 32*4; - } -} - -static void -memcopy_fromhp(void *dest, void *src, int count) -{ - /* FIXME */ - printk("uhm ...\n"); -} static void memset_tohp(void *dest, u32 word, int count) @@ -139,10 +91,11 @@ writeb_hp(u8 b, void *dst) static void fbcon_sti_setup(struct display *p) { - if (p->line_length) - p->next_line = p->line_length; - else + /* 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; } @@ -152,7 +105,7 @@ fbcon_sti_bmove(struct display *p, int sy, int sx, int height, int width) { #if 0 /* Unfortunately, still broken */ - sti_bmove(&default_sti /* FIXME */, sy, sx, dy, dx, height, width); + sti_bmove(default_sti /* FIXME */, sy, sx, dy, dx, height, width); #else u8 *src, *dest; u_int rows; @@ -285,7 +238,6 @@ static void fbcon_sti_revc(struct display *p, 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); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c new file mode 100644 index 000000000000..c00f5d395afb --- /dev/null +++ b/drivers/video/console/fbcon.c @@ -0,0 +1,2843 @@ +/* + * linux/drivers/video/fbcon.c -- Low level frame buffer based console driver + * + * Copyright (C) 1995 Geert Uytterhoeven + * + * + * This file is based on the original Amiga console driver (amicon.c): + * + * Copyright (C) 1993 Hamish Macdonald + * Greg Harp + * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] + * + * with work by William Rucklidge (wjr@cs.cornell.edu) + * Geert Uytterhoeven + * Jes Sorensen (jds@kom.auc.dk) + * Martin Apel + * + * and on the original Atari console driver (atacon.c): + * + * Copyright (C) 1993 Bjoern Brauel + * Roman Hodek + * + * with work by Guenther Kelleter + * Martin Schaller + * Andreas Schwab + * + * Hardware cursor support added by Emmanuel Marty (core@ggi-project.org) + * Smart redraw scrolling, arbitrary font width support, 512char font support + * and software scrollback added by + * Jakub Jelinek (jj@ultra.linux.cz) + * + * Random hacking by Martin Mares <mj@ucw.cz> + * + * 2001 - Documented with DocBook + * - Brad Douglas <brad@neruo.com> + * + * The low level operations for the various display memory organizations are + * now in separate source files. + * + * Currently the following organizations are supported: + * + * o afb Amiga bitplanes + * o cfb{2,4,8,16,24,32} Packed pixels + * o ilbm Amiga interleaved bitplanes + * o iplan2p[248] Atari interleaved bitplanes + * o mfb Monochrome + * o vga VGA characters/attributes + * + * To do: + * + * - Implement 16 plane mode (iplan2p16) + * + * + * 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. + */ + +#undef FBCONDEBUG + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/delay.h> /* MSch: for IRQ probe */ +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/string.h> +#include <linux/kd.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/vt_kern.h> +#include <linux/selection.h> +#include <linux/smp.h> +#include <linux/init.h> + +#include <asm/irq.h> +#include <asm/system.h> +#include <asm/uaccess.h> +#ifdef CONFIG_AMIGA +#include <asm/amigahw.h> +#include <asm/amigaints.h> +#endif /* CONFIG_AMIGA */ +#ifdef CONFIG_ATARI +#include <asm/atariints.h> +#endif +#ifdef CONFIG_MAC +#include <asm/macints.h> +#endif +#if defined(__mc68000__) || defined(CONFIG_APUS) +#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) +#else +# define DPRINTK(fmt, args...) +#endif + +#define LOGO_H 80 +#define LOGO_W 80 +#define LOGO_LINE (LOGO_W/8) + +struct display fb_display[MAX_NR_CONSOLES]; +char con2fb_map[MAX_NR_CONSOLES]; +static int logo_lines; +static int logo_shown = -1; +/* Software scrollback */ +int fbcon_softback_size = 32768; +static unsigned long softback_buf, softback_curr; +static unsigned long softback_in; +static unsigned long softback_top, softback_end; +static int softback_lines; +/* console mappings */ +static int first_fb_vc; +static int last_fb_vc = MAX_NR_CONSOLES - 1; +static int fbcon_is_default = 1; + +#define REFCOUNT(fd) (((int *)(fd))[-1]) +#define FNTSIZE(fd) (((int *)(fd))[-2]) +#define FNTCHARCNT(fd) (((int *)(fd))[-3]) +#define FNTSUM(fd) (((int *)(fd))[-4]) +#define FONT_EXTRA_WORDS 4 + +#define CM_SOFTBACK (8) + +#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row) + +static void fbcon_free_font(struct display *); +static int fbcon_set_origin(struct vc_data *); +static int cursor_drawn; + +#define CURSOR_DRAW_DELAY (1) + +/* # VBL ints between cursor state changes */ +#define ARM_CURSOR_BLINK_RATE (10) +#define AMIGA_CURSOR_BLINK_RATE (20) +#define ATARI_CURSOR_BLINK_RATE (42) +#define MAC_CURSOR_BLINK_RATE (32) +#define DEFAULT_CURSOR_BLINK_RATE (20) + +static int vbl_cursor_cnt; +static int cursor_on; +static int cursor_blink_rate; + +static inline void cursor_undrawn(void) +{ + vbl_cursor_cnt = 0; + cursor_drawn = 0; +} + +#define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1) + +/* + * Interface used by the world + */ + +static const char *fbcon_startup(void); +static void fbcon_init(struct vc_data *vc, int init); +static void fbcon_deinit(struct vc_data *vc); +static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, + int width); +static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos); +static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, + int count, int ypos, int xpos); +static void fbcon_cursor(struct vc_data *vc, int mode); +static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, + int count); +static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, + int height, int width); +static int fbcon_switch(struct vc_data *vc); +static int fbcon_blank(struct vc_data *vc, int blank); +static int fbcon_font_op(struct vc_data *vc, struct console_font_op *op); +static int fbcon_set_palette(struct vc_data *vc, unsigned char *table); +static int fbcon_scrolldelta(struct vc_data *vc, int lines); + + +/* + * Internal routines + */ + +static int fbcon_changevar(int con); +static void fbcon_set_display(int con, int init, int logo); +static __inline__ int real_y(struct display *p, int ypos); +static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp); +static __inline__ void updatescrollmode(struct display *p, struct vc_data *vc); +static __inline__ void ywrap_up(struct display *p, struct vc_data *vc, + int count); +static __inline__ void ywrap_down(struct display *p, struct vc_data *vc, + int count); +static __inline__ void ypan_up(struct display *p, struct vc_data *vc, + int count); +static __inline__ void ypan_down(struct display *p, struct vc_data *vc, + int count); +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 + */ +static int vbl_detected; + +static void fbcon_vbl_detect(int irq, void *dummy, struct pt_regs *fp) +{ + vbl_detected++; +} +#endif + +static void cursor_timer_handler(unsigned long dev_addr); + +static struct timer_list cursor_timer = + TIMER_INITIALIZER(cursor_timer_handler, 0, 0); + +static void cursor_timer_handler(unsigned long dev_addr) +{ + fbcon_vbl_handler(0, NULL, NULL); + cursor_timer.expires = jiffies + HZ / 50; + add_timer(&cursor_timer); +} + +int __init fb_console_setup(char *this_opt) +{ + int unit, i, j; + char *options; + + if (!this_opt || !*this_opt) + return 0; + + while ((options = strsep(&this_opt, ",")) != NULL) { + if (!strncmp(options, "font:", 5)) { + for (unit = 0; unit < MAX_NR_CONSOLES; unit++) + strcpy(fb_display[unit].fontname, + options + 5); + } + + if (!strncmp(options, "scrollback:", 11)) { + options += 11; + if (*options) { + fbcon_softback_size = simple_strtoul(options, &options, 0); + if (*options == 'k' || *options == 'K') { + fbcon_softback_size *= 1024; + options++; + } + if (*options != ',') + return 0; + options++; + } else + return 0; + } + + if (!strncmp(options, "map:", 4)) { + options += 4; + if (*options) + for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) { + if (!options[j]) + j = 0; + con2fb_map[i] = (options[j++]-'0') % FB_MAX; + } + return 0; + } + + if (!strncmp(options, "vc:", 3)) { + options += 3; + if (*options) + first_fb_vc = simple_strtoul(options, &options, 10) - 1; + if (first_fb_vc < 0) + first_fb_vc = 0; + if (*options++ == '-') + last_fb_vc = simple_strtoul(options, &options, 10) - 1; + fbcon_is_default = 0; + } + } + return 0; +} + +__setup("fbcon=", fb_console_setup); + +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; + fbcon_changevar(con); + return; +} + +/** + * set_con2fb_map - map console to frame buffer device + * @unit: virtual console number to map + * @newidx: frame buffer index to map virtual console to + * + * Maps a virtual console @unit to a frame buffer device + * @newidx. + * + */ + +void set_con2fb_map(int unit, int newidx) +{ + int oldidx = con2fb_map[unit]; + struct fb_info *oldfb, *newfb; + struct vc_data *vc; + char *fontdata; + int userfont; + + if (newidx != con2fb_map[unit]) { + oldfb = registered_fb[oldidx]; + newfb = registered_fb[newidx]; + if (!try_module_get(newfb->fbops->owner)) + return; + if (newfb->fbops->fb_open + && newfb->fbops->fb_open(newfb, 0)) { + module_put(newfb->fbops->owner); + return; + } + if (oldfb->fbops->fb_release) + oldfb->fbops->fb_release(oldfb, 0); + module_put(oldfb->fbops->owner); + vc = fb_display[unit].conp; + fontdata = fb_display[unit].fontdata; + userfont = fb_display[unit].userfont; + con2fb_map[unit] = newidx; + + fb_display[unit].conp = vc; + fb_display[unit].fontdata = fontdata; + fb_display[unit].userfont = userfont; + fb_display[unit].fb_info = newfb; + gen_set_disp(unit, newfb); + /* tell console var has changed */ + fbcon_changevar(unit); + } +} + +/* + * Accelerated handlers. + */ +void accel_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + struct fb_info *info = p->fb_info; + struct vc_data *vc = p->conp; + struct fb_copyarea area; + + area.sx = sx * vc->vc_font.width; + area.sy = sy * vc->vc_font.height; + area.dx = dx * vc->vc_font.width; + area.dy = dy * vc->vc_font.height; + area.height = height * vc->vc_font.height; + area.width = width * vc->vc_font.height; + + info->fbops->fb_copyarea(info, &area); +} + +void accel_clear(struct vc_data *vc, struct display *p, int sy, + int sx, int height, int width) +{ + struct fb_info *info = p->fb_info; + struct fb_fillrect region; + + region.color = attr_bgcol_ec(p, vc); + region.dx = sx * vc->vc_font.width; + region.dy = sy * vc->vc_font.height; + region.width = width * vc->vc_font.width; + region.height = height * vc->vc_font.height; + region.rop = ROP_COPY; + + info->fbops->fb_fillrect(info, ®ion); +} + +void accel_putcs(struct vc_data *vc, struct display *p, + const unsigned short *s, int count, int yy, int xx) +{ + struct fb_info *info = p->fb_info; + unsigned short charmask = p->charmask; + unsigned int width = ((vc->vc_font.width + 7)/8); + unsigned int cellsize = vc->vc_font.height * width; + struct fb_image image; + u16 c = scr_readw(s); + static u8 pixmap[8192]; + + image.fg_color = attr_fgcol(p, c); + image.bg_color = attr_bgcol(p, c); + image.dx = xx * vc->vc_font.width; + image.dy = yy * vc->vc_font.height; + image.height = vc->vc_font.height; + image.depth = 1; + +/* pixmap = kmalloc((info->var.bits_per_pixel + 7) >> 3 * + vc->vc_font.height, GFP_KERNEL); +*/ + + if (!(vc->vc_font.width & 7) && pixmap != NULL) { + unsigned int pitch = width * count, i, j; + char *src, *dst, *dst0; + + dst0 = pixmap; + image.width = vc->vc_font.width * count; + image.data = pixmap; + while (count--) { + src = p->fontdata + (scr_readw(s++) & charmask) * cellsize; + dst = dst0; + for (i = image.height; i--; ) { + for (j = 0; j < width; j++) + dst[j] = *src++; + dst += pitch; + } + dst0 += width; + } + info->fbops->fb_imageblit(info, &image); + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + } else { + image.width = vc->vc_font.width; + while (count--) { + image.data = p->fontdata + + (scr_readw(s++) & charmask) * vc->vc_font.height * width; + info->fbops->fb_imageblit(info, &image); + image.dx += vc->vc_font.width; + } + } + /* + if (pixmap); + kfree(pixmap); + */ +} + +void accel_clear_margins(struct vc_data *vc, struct display *p, + int bottom_only) +{ + struct fb_info *info = p->fb_info; + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.xres % cw; + unsigned int bh = info->var.yres % ch; + unsigned int rs = info->var.xres - rw; + unsigned int bs = info->var.yres - bh; + struct fb_fillrect region; + + region.color = attr_bgcol_ec(p, vc); + region.rop = ROP_COPY; + + if (rw & !bottom_only) { + region.dx = info->var.xoffset + rs; + region.dy = 0; + region.width = rw; + region.height = info->var.yres_virtual; + info->fbops->fb_fillrect(info, ®ion); + } + + if (bh) { + region.dx = info->var.xoffset; + region.dy = info->var.yoffset + bs; + region.width = rs; + region.height = bh; + info->fbops->fb_fillrect(info, ®ion); + } +} + +void accel_cursor(struct display *p, int flags, int xx, int yy) +{ + static char mask[64], image[64], *dest; + struct vc_data *vc = p->conp; + static int fgcolor, bgcolor, shape, width, height; + struct fb_info *info = p->fb_info; + struct fb_cursor cursor; + char *font; + int c; + + cursor.set = FB_CUR_SETPOS; + + if (width != vc->vc_font.width || height != vc->vc_font.height) { + width = vc->vc_font.width; + height = vc->vc_font.height; + cursor.set |= FB_CUR_SETSIZE; + } + + if ((vc->vc_cursor_type & 0x0f) != shape) { + shape = vc->vc_cursor_type & 0x0f; + cursor.set |= FB_CUR_SETSHAPE; + } + + c = scr_readw((u16 *) vc->vc_pos); + + if (fgcolor != (int) attr_fgcol(p, c) || + bgcolor != (int) attr_bgcol(p, c)) { + fgcolor = (int) attr_fgcol(p, c); + bgcolor = (int) attr_bgcol(p, c); + cursor.set |= FB_CUR_SETCMAP; + } + c &= p->charmask; + font = p->fontdata + (c * ((width + 7) / 8) * height); + if (font != dest) { + dest = font; + cursor.set |= FB_CUR_SETDEST; + } + + if (flags & FB_CUR_SETCUR) + cursor.enable = 1; + else + cursor.enable = 0; + + if (cursor.set & FB_CUR_SETSIZE) { + memset(image, 0xff, 64); + cursor.set |= FB_CUR_SETSHAPE; + } + + if (cursor.set & FB_CUR_SETSHAPE) { + int w, cur_height, size, i = 0; + + w = (width + 7) / 8; + + switch (shape) { + case CUR_NONE: + cur_height = 0; + break; + case CUR_UNDERLINE: + cur_height = (height < 10) ? 1 : 2; + break; + case CUR_LOWER_THIRD: + cur_height = height/3; + break; + case CUR_LOWER_HALF: + cur_height = height/2; + break; + case CUR_TWO_THIRDS: + cur_height = (height * 2)/3; + break; + case CUR_BLOCK: + default: + cur_height = height; + break; + } + + size = (height - cur_height) * w; + while (size--) + mask[i++] = 0; + size = cur_height * w; + while (size--) + mask[i++] = 0xff; + } + + cursor.image.width = width; + cursor.image.height = height; + cursor.image.dx = xx * width; + cursor.image.dy = yy * height; + cursor.image.depth = 1; + cursor.image.data = image; + cursor.image.bg_color = bgcolor; + cursor.image.fg_color = fgcolor; + cursor.mask = mask; + cursor.dest = dest; + cursor.rop = ROP_XOR; + + if (info->fbops->fb_cursor) + info->fbops->fb_cursor(info, &cursor); +} + +/* + * Low Level Operations + */ +/* NOTE: fbcon cannot be __init: it may be called from take_over_console later */ + +static const char *fbcon_startup(void) +{ + const char *display_desc = "frame buffer device"; + struct font_desc *font = NULL; + struct module *owner; + struct fb_info *info; + struct vc_data *vc; + static int done = 0; + int irqres = 1; + + /* + * If num_registered_fb is zero, this is a call for the dummy part. + * The frame buffer devices weren't initialized yet. + */ + if (!num_registered_fb || done) + return display_desc; + done = 1; + + info = registered_fb[num_registered_fb-1]; + if (!info) return NULL; + info->currcon = -1; + + owner = info->fbops->owner; + if (!try_module_get(owner)) + return NULL; + if (info->fbops->fb_open && info->fbops->fb_open(info, 0)) + module_put(owner); + + if (info->fix.type != FB_TYPE_TEXT) { + if (fbcon_softback_size) { + if (!softback_buf) { + softback_buf = + (unsigned long) + kmalloc(fbcon_softback_size, + GFP_KERNEL); + if (!softback_buf) { + fbcon_softback_size = 0; + softback_top = 0; + } + } + } else { + if (softback_buf) { + kfree((void *) softback_buf); + softback_buf = 0; + softback_top = 0; + } + } + if (softback_buf) + softback_in = softback_top = softback_curr = + softback_buf; + softback_lines = 0; + } + + font = get_default_font(info->var.xres, info->var.yres); + + vc = (struct vc_data *) kmalloc(sizeof(struct vc_data), GFP_ATOMIC); + + /* Setup default font */ + vc->vc_font.data = font->data; + vc->vc_font.width = font->width; + vc->vc_font.height = font->height; + vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ + + vc->vc_cols = info->var.xres/vc->vc_font.width; + vc->vc_rows = info->var.yres/vc->vc_font.height; + + /* We trust the mode the driver supplies. */ + if (info->fbops->fb_set_par) + info->fbops->fb_set_par(info); + + DPRINTK("mode: %s\n", info->fix.id); + DPRINTK("visual: %d\n", info->fix.visual); + DPRINTK("res: %dx%d-%d\n", info->var.xres, + info->var.yres, + info->var.bits_per_pixel); + + info->display_fg = vc; + +#ifdef CONFIG_AMIGA + if (MACH_IS_AMIGA) { + cursor_blink_rate = AMIGA_CURSOR_BLINK_RATE; + irqres = request_irq(IRQ_AMIGA_VERTB, fbcon_vbl_handler, 0, + "console/cursor", fbcon_vbl_handler); + } +#endif /* CONFIG_AMIGA */ +#ifdef CONFIG_ATARI + if (MACH_IS_ATARI) { + cursor_blink_rate = ATARI_CURSOR_BLINK_RATE; + irqres = + request_irq(IRQ_AUTO_4, fbcon_vbl_handler, + IRQ_TYPE_PRIO, "console/cursor", + fbcon_vbl_handler); + } +#endif /* CONFIG_ATARI */ + +#ifdef CONFIG_MAC + /* + * On a Macintoy, the VBL interrupt may or may not be active. + * As interrupt based cursor is more reliable and race free, we + * probe for VBL interrupts. + */ + if (MACH_IS_MAC) { + int ct = 0; + /* + * Probe for VBL: set temp. handler ... + */ + irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_detect, 0, + "console/cursor", fbcon_vbl_detect); + vbl_detected = 0; + + /* + * ... and spin for 20 ms ... + */ + while (!vbl_detected && ++ct < 1000) + udelay(20); + + if (ct == 1000) + printk + ("fbcon_startup: No VBL detected, using timer based cursor.\n"); + + free_irq(IRQ_MAC_VBL, fbcon_vbl_detect); + + if (vbl_detected) { + /* + * interrupt based cursor ok + */ + cursor_blink_rate = MAC_CURSOR_BLINK_RATE; + irqres = + request_irq(IRQ_MAC_VBL, fbcon_vbl_handler, 0, + "console/cursor", + fbcon_vbl_handler); + } else { + /* + * VBL not detected: fall through, use timer based cursor + */ + irqres = 1; + } + } +#endif /* CONFIG_MAC */ + +#if defined(__arm__) && defined(IRQ_VSYNCPULSE) + cursor_blink_rate = ARM_CURSOR_BLINK_RATE; + irqres = request_irq(IRQ_VSYNCPULSE, fbcon_vbl_handler, SA_SHIRQ, + "console/cursor", fbcon_vbl_handler); +#endif + + if (irqres) { + cursor_blink_rate = DEFAULT_CURSOR_BLINK_RATE; + cursor_timer.expires = jiffies + HZ / 50; + add_timer(&cursor_timer); + } + return display_desc; +} + +static void fbcon_init(struct vc_data *vc, int init) +{ + int unit = vc->vc_num; + struct fb_info *info; + + /* on which frame buffer will we open this console? */ + info = registered_fb[(int) con2fb_map[unit]]; + + gen_set_disp(unit, info); + fb_display[unit].conp = vc; + fb_display[unit].fb_info = info; + + fbcon_set_display(unit, init, !init); +} + + +static void fbcon_deinit(struct vc_data *vc) +{ + int unit = vc->vc_num; + struct display *p = &fb_display[unit]; + + fbcon_free_font(p); + p->conp = 0; +} + +#define fontwidthvalid(p,w) ((p)->fontwidthmask & FONTWIDTH(w)) + +static int fbcon_changevar(int con) +{ + if (fb_display[con].conp) { + struct display *p = &fb_display[con]; + struct fb_info *info = p->fb_info; + struct vc_data *vc = p->conp; + int nr_rows, nr_cols; + int old_rows, old_cols; + unsigned short *save = NULL, *q; + int i, charcnt = 256; + struct font_desc *font; + + info->var.xoffset = info->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ + + for (i = 0; i < MAX_NR_CONSOLES; i++) + if (i != con && fb_display[i].fb_info == info && + fb_display[i].conp && fb_display[i].fontdata) + break; + + fbcon_free_font(p); + if (i < MAX_NR_CONSOLES) { + struct display *q = &fb_display[i]; + struct vc_data *tmp = vc_cons[i].d; + + 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; + p->fontdata = q->fontdata; + p->userfont = q->userfont; + if (p->userfont) { + REFCOUNT(p->fontdata)++; + charcnt = FNTCHARCNT(p->fontdata); + } + con_copy_unimap(con, i); + } + } + + if (!p->fontdata) { + if (!p->fontname[0] || !(font = find_font(p->fontname))) + font = get_default_font(info->var.xres, + info->var.yres); + vc->vc_font.width = font->width; + vc->vc_font.height = font->height; + 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; + old_rows = vc->vc_rows; + + nr_cols = info->var.xres / vc->vc_font.width; + nr_rows = info->var.yres / vc->vc_font.height; + + /* + * ++guenther: console.c:vc_allocate() relies on initializing + * vc_{cols,rows}, but we must not set those if we are only + * resizing the console. + */ + p->vrows = info->var.yres_virtual / vc->vc_font.height; + if ((info->var.yres % vc->vc_font.height) && + (info->var.yres_virtual % vc->vc_font.height < + info->var.yres % vc->vc_font.height)) + p->vrows--; + vc->vc_can_do_color = info->var.bits_per_pixel != 1; + vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; + if (charcnt == 256) { + vc->vc_hi_font_mask = 0; + p->fgshift = 8; + p->bgshift = 12; + p->charmask = 0xff; + } else { + vc->vc_hi_font_mask = 0x100; + if (vc->vc_can_do_color) + vc->vc_complement_mask <<= 1; + p->fgshift = 9; + p->bgshift = 13; + p->charmask = 0x1ff; + } + + if (vc->vc_cols != nr_cols || vc->vc_rows != nr_rows) + vc_resize(con, nr_cols, nr_rows); + else if (CON_IS_VISIBLE(vc) && + vt_cons[vc->vc_num]->vc_mode == KD_TEXT) { + accel_clear_margins(vc, p, 0); + update_screen(con); + } + if (save) { + q = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * + old_rows); + scr_memcpyw(q, save, logo_lines * nr_cols * 2); + vc->vc_y += logo_lines; + vc->vc_pos += logo_lines * vc->vc_size_row; + kfree(save); + } + + if (con == fg_console && softback_buf) { + int l = fbcon_softback_size / vc->vc_size_row; + if (l > 5) + softback_end = softback_buf + l * vc->vc_size_row; + else { + /* Smaller scrollback makes no sense, and 0 would screw + the operation totally */ + softback_top = 0; + } + } + } + return 0; +} + +static __inline__ void updatescrollmode(struct display *p, struct vc_data *vc) +{ + struct fb_info *info = p->fb_info; + + int m; + if (p->scrollmode & __SCROLL_YFIXED) + return; + if (divides(info->fix.ywrapstep, vc->vc_font.height) && + divides(vc->vc_font.height, info->var.yres_virtual)) + m = __SCROLL_YWRAP; + else if (divides(info->fix.ypanstep, vc->vc_font.height) && + info->var.yres_virtual >= info->var.yres + vc->vc_font.height) + m = __SCROLL_YPAN; + else if (p->scrollmode & __SCROLL_YNOMOVE) + m = __SCROLL_YREDRAW; + else + m = __SCROLL_YMOVE; + p->scrollmode = (p->scrollmode & ~__SCROLL_YMASK) | m; +} + +static void fbcon_set_display(int con, int init, int logo) +{ + struct display *p = &fb_display[con]; + struct fb_info *info = p->fb_info; + struct vc_data *vc = p->conp; + int nr_rows, nr_cols; + int old_rows, old_cols; + unsigned short *save = NULL, *r, *q; + int i, charcnt = 256; + struct font_desc *font; + + if (con != fg_console || (info->flags & FBINFO_FLAG_MODULE) || + info->fix.type == FB_TYPE_TEXT) + logo = 0; + + info->var.xoffset = info->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ + + for (i = 0; i < MAX_NR_CONSOLES; i++) + if (i != con && fb_display[i].fb_info == info && + fb_display[i].conp && fb_display[i].fontdata) + break; + + fbcon_free_font(p); + if (i < MAX_NR_CONSOLES) { + struct display *q = &fb_display[i]; + struct vc_data *tmp = vc_cons[i].d; + + 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; + p->fontdata = q->fontdata; + p->userfont = q->userfont; + if (p->userfont) { + REFCOUNT(p->fontdata)++; + charcnt = FNTCHARCNT(p->fontdata); + } + con_copy_unimap(con, i); + } + } + + if (!p->fontdata) { + if (!p->fontname[0] || !(font = find_font(p->fontname))) + font = get_default_font(info->var.xres, + info->var.yres); + vc->vc_font.width = font->width; + vc->vc_font.height = font->height; + 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; + old_rows = vc->vc_rows; + + nr_cols = info->var.xres / vc->vc_font.width; + nr_rows = info->var.yres / vc->vc_font.height; + + if (logo) { + /* Need to make room for the logo */ + int cnt; + int step; + + logo_lines = (LOGO_H + vc->vc_font.height - 1) / vc->vc_font.height; + q = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * old_rows); + step = logo_lines * old_cols; + for (r = q - logo_lines * old_cols; r < q; r++) + if (scr_readw(r) != vc->vc_video_erase_char) + break; + if (r != q && nr_rows >= old_rows + logo_lines) { + save = + kmalloc(logo_lines * nr_cols * 2, GFP_KERNEL); + if (save) { + int i = + old_cols < + nr_cols ? old_cols : nr_cols; + scr_memsetw(save, vc->vc_video_erase_char, + logo_lines * nr_cols * 2); + r = q - step; + for (cnt = 0; cnt < logo_lines; + cnt++, r += i) + scr_memcpyw(save + cnt * nr_cols, + r, 2 * i); + r = q; + } + } + if (r == q) { + /* We can scroll screen down */ + r = q - step - old_cols; + for (cnt = old_rows - logo_lines; cnt > 0; cnt--) { + scr_memcpyw(r + step, r, vc->vc_size_row); + r -= old_cols; + } + if (!save) { + vc->vc_y += logo_lines; + vc->vc_pos += logo_lines * vc->vc_size_row; + } + } + scr_memsetw((unsigned short *) vc->vc_origin, + vc->vc_video_erase_char, + vc->vc_size_row * logo_lines); + } + + /* + * ++guenther: console.c:vc_allocate() relies on initializing + * vc_{cols,rows}, but we must not set those if we are only + * resizing the console. + */ + if (init) { + vc->vc_cols = nr_cols; + vc->vc_rows = nr_rows; + } + p->vrows = info->var.yres_virtual / vc->vc_font.height; + if ((info->var.yres % vc->vc_font.height) && + (info->var.yres_virtual % vc->vc_font.height < + info->var.yres % vc->vc_font.height)) + p->vrows--; + vc->vc_can_do_color = info->var.bits_per_pixel != 1; + vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; + if (charcnt == 256) { + vc->vc_hi_font_mask = 0; + p->fgshift = 8; + p->bgshift = 12; + p->charmask = 0xff; + } else { + vc->vc_hi_font_mask = 0x100; + if (vc->vc_can_do_color) + vc->vc_complement_mask <<= 1; + p->fgshift = 9; + p->bgshift = 13; + p->charmask = 0x1ff; + } + + if (!init) { + if (vc->vc_cols != nr_cols || vc->vc_rows != nr_rows) + vc_resize(con, nr_cols, nr_rows); + else if (CON_IS_VISIBLE(vc) && + vt_cons[vc->vc_num]->vc_mode == KD_TEXT) { + accel_clear_margins(vc, p, 0); + update_screen(con); + } + if (save) { + q = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * + old_rows); + scr_memcpyw(q, save, logo_lines * nr_cols * 2); + vc->vc_y += logo_lines; + vc->vc_pos += logo_lines * vc->vc_size_row; + kfree(save); + } + } + + if (logo) { + if (logo_lines > vc->vc_bottom) { + logo_shown = -1; + printk(KERN_INFO + "fbcon_startup: disable boot-logo (boot-logo bigger than screen).\n"); + } else { + logo_shown = -2; + vc->vc_top = logo_lines; + } + } + + if (con == fg_console && softback_buf) { + int l = fbcon_softback_size / vc->vc_size_row; + if (l > 5) + softback_end = softback_buf + l * vc->vc_size_row; + else { + /* Smaller scrollback makes no sense, and 0 would screw + the operation totally */ + softback_top = 0; + } + } +} + + +/* ====================================================================== */ + +/* fbcon_XXX routines - interface used by the world + * + * This system is now divided into two levels because of complications + * caused by hardware scrolling. Top level functions: + * + * fbcon_bmove(), fbcon_clear(), fbcon_putc() + * + * handles y values in range [0, scr_height-1] that correspond to real + * screen positions. y_wrap shift means that first line of bitmap may be + * anywhere on this display. These functions convert lineoffsets to + * bitmap offsets and deal with the wrap-around case by splitting blits. + * + * fbcon_bmove_physical_8() -- These functions fast implementations + * fbcon_clear_physical_8() -- of original fbcon_XXX fns. + * fbcon_putc_physical_8() -- (fontwidth != 8) may be added later + * + * WARNING: + * + * At the moment fbcon_putc() cannot blit across vertical wrap boundary + * Implies should only really hardware scroll in rows. Only reason for + * restriction is simplicity & efficiency at the moment. + */ + +static __inline__ int real_y(struct display *p, int ypos) +{ + int rows = p->vrows; + + ypos += p->yscroll; + return ypos < rows ? ypos : ypos - rows; +} + + +static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, + int width) +{ + int unit = vc->vc_num; + struct display *p = &fb_display[unit]; + u_int y_break; + int redraw_cursor = 0; + + if (!p->can_soft_blank && console_blanked) + return; + + if (!height || !width) + return; + + if ((sy <= p->cursor_y) && (p->cursor_y < sy + height) && + (sx <= p->cursor_x) && (p->cursor_x < sx + width)) { + cursor_undrawn(); + redraw_cursor = 1; + } + + /* Split blits that cross physical y_wrap boundary */ + + y_break = p->vrows - p->yscroll; + if (sy < y_break && sy + height - 1 >= y_break) { + u_int b = y_break - sy; + accel_clear(vc, p, real_y(p, sy), sx, b, width); + accel_clear(vc, p, real_y(p, sy + b), sx, height - b, + width); + } else + accel_clear(vc, p, real_y(p, sy), sx, height, width); + + if (redraw_cursor) + vbl_cursor_cnt = CURSOR_DRAW_DELAY; +} + + +static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos) +{ + struct display *p = &fb_display[vc->vc_num]; + struct fb_info *info = p->fb_info; + unsigned short charmask = p->charmask; + unsigned int width = ((vc->vc_font.width + 7) >> 3); + struct fb_image image; + int redraw_cursor = 0; + + if (!p->can_soft_blank && console_blanked) + return; + + if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT) + return; + + if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) { + cursor_undrawn(); + redraw_cursor = 1; + } + + image.fg_color = attr_fgcol(p, c); + image.bg_color = attr_bgcol(p, c); + image.dx = xpos * vc->vc_font.width; + image.dy = real_y(p, ypos) * vc->vc_font.height; + image.width = vc->vc_font.width; + image.height = vc->vc_font.height; + image.depth = 1; + image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width; + + info->fbops->fb_imageblit(info, &image); + + if (redraw_cursor) + vbl_cursor_cnt = CURSOR_DRAW_DELAY; +} + + +static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, + int count, int ypos, int xpos) +{ + int unit = vc->vc_num; + struct display *p = &fb_display[unit]; + int redraw_cursor = 0; + + if (!p->can_soft_blank && console_blanked) + return; + + if (vt_cons[unit]->vc_mode != KD_TEXT) + return; + + if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) && + (p->cursor_x < (xpos + count))) { + cursor_undrawn(); + redraw_cursor = 1; + } + accel_putcs(vc, p, s, count, real_y(p, ypos), xpos); + if (redraw_cursor) + vbl_cursor_cnt = CURSOR_DRAW_DELAY; +} + +static void fbcon_cursor(struct vc_data *vc, int mode) +{ + struct display *p = &fb_display[vc->vc_num]; + int y = vc->vc_y; + + if (mode & CM_SOFTBACK) { + mode &= ~CM_SOFTBACK; + if (softback_lines) { + if (y + softback_lines >= vc->vc_rows) + mode = CM_ERASE; + else + y += softback_lines; + } + } else if (softback_lines) + fbcon_set_origin(vc); + + /* Avoid flickering if there's no real change. */ + if (p->cursor_x == vc->vc_x && p->cursor_y == y && + (mode == CM_ERASE) == !cursor_on) + return; + + cursor_on = 0; + if (cursor_drawn) + accel_cursor(p, 0, p->cursor_x, + real_y(p, p->cursor_y)); + + p->cursor_x = vc->vc_x; + p->cursor_y = y; + p->cursor_pos = vc->vc_pos; + + switch (mode) { + case CM_ERASE: + cursor_drawn = 0; + break; + case CM_MOVE: + case CM_DRAW: + if (cursor_drawn) + accel_cursor(p, FB_CUR_SETCUR, p->cursor_x, + real_y(p, p->cursor_y)); + vbl_cursor_cnt = CURSOR_DRAW_DELAY; + cursor_on = 1; + break; + } + +} + +static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp) +{ + struct display *p; + + if (!cursor_on) + return; + + if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) { + int flag; + + p = &fb_display[fg_console]; + flag = 0; + if (!cursor_drawn) + flag = FB_CUR_SETCUR; + accel_cursor(p, flag, p->cursor_x, + real_y(p, p->cursor_y)); + cursor_drawn ^= 1; + vbl_cursor_cnt = cursor_blink_rate; + } +} + +static int scrollback_phys_max = 0; +static int scrollback_max = 0; +static int scrollback_current = 0; + +int update_var(int con, struct fb_info *info) +{ + int err; + + if (con == info->currcon) { + if (info->fbops->fb_pan_display) { + if ((err = + info->fbops->fb_pan_display(&info->var, + info))) + return err; + } + } + return 0; +} + +static __inline__ void ywrap_up(struct display *p, struct vc_data *vc, + int count) +{ + struct fb_info *info = p->fb_info; + + p->yscroll += count; + if (p->yscroll >= p->vrows) /* Deal with wrap */ + p->yscroll -= p->vrows; + info->var.xoffset = 0; + info->var.yoffset = p->yscroll * vc->vc_font.height; + info->var.vmode |= FB_VMODE_YWRAP; + update_var(vc->vc_num, info); + scrollback_max += count; + if (scrollback_max > scrollback_phys_max) + scrollback_max = scrollback_phys_max; + scrollback_current = 0; +} + +static __inline__ void ywrap_down(struct display *p, struct vc_data *vc, + int count) +{ + struct fb_info *info = p->fb_info; + + p->yscroll -= count; + if (p->yscroll < 0) /* Deal with wrap */ + p->yscroll += p->vrows; + info->var.xoffset = 0; + info->var.yoffset = p->yscroll * vc->vc_font.height; + info->var.vmode |= FB_VMODE_YWRAP; + update_var(vc->vc_num, info); + scrollback_max -= count; + if (scrollback_max < 0) + scrollback_max = 0; + scrollback_current = 0; +} + +static __inline__ void ypan_up(struct display *p, struct vc_data *vc, + int count) +{ + struct fb_info *info = p->fb_info; + + p->yscroll += count; + if (p->yscroll > p->vrows - vc->vc_rows) { + accel_bmove(p, p->vrows - vc->vc_rows, 0, 0, 0, + vc->vc_rows, vc->vc_cols); + p->yscroll -= p->vrows - vc->vc_rows; + } + info->var.xoffset = 0; + info->var.yoffset = p->yscroll * vc->vc_font.height; + info->var.vmode &= ~FB_VMODE_YWRAP; + update_var(vc->vc_num, info); + accel_clear_margins(vc, p, 1); + scrollback_max += count; + if (scrollback_max > scrollback_phys_max) + scrollback_max = scrollback_phys_max; + scrollback_current = 0; +} + + +static __inline__ void ypan_down(struct display *p, struct vc_data *vc, + int count) +{ + struct fb_info *info = p->fb_info; + + p->yscroll -= count; + if (p->yscroll < 0) { + accel_bmove(p, 0, 0, p->vrows - vc->vc_rows, 0, + vc->vc_rows, vc->vc_cols); + p->yscroll += p->vrows - vc->vc_rows; + } + info->var.xoffset = 0; + info->var.yoffset = p->yscroll * vc->vc_font.height; + info->var.vmode &= ~FB_VMODE_YWRAP; + update_var(vc->vc_num, info); + accel_clear_margins(vc, p, 1); + scrollback_max -= count; + if (scrollback_max < 0) + scrollback_max = 0; + scrollback_current = 0; +} + +static void fbcon_redraw_softback(struct vc_data *vc, struct display *p, + long delta) +{ + unsigned short *d, *s; + unsigned long n; + int line = 0; + int count = vc->vc_rows; + + d = (u16 *) softback_curr; + if (d == (u16 *) softback_in) + d = (u16 *) vc->vc_origin; + n = softback_curr + delta * vc->vc_size_row; + softback_lines -= delta; + if (delta < 0) { + if (softback_curr < softback_top && n < softback_buf) { + n += softback_end - softback_buf; + if (n < softback_top) { + softback_lines -= + (softback_top - n) / vc->vc_size_row; + n = softback_top; + } + } else if (softback_curr >= softback_top + && n < softback_top) { + softback_lines -= + (softback_top - n) / vc->vc_size_row; + n = softback_top; + } + } else { + if (softback_curr > softback_in && n >= softback_end) { + n += softback_buf - softback_end; + if (n > softback_in) { + n = softback_in; + softback_lines = 0; + } + } else if (softback_curr <= softback_in && n > softback_in) { + n = softback_in; + softback_lines = 0; + } + } + if (n == softback_curr) + return; + softback_curr = n; + s = (u16 *) softback_curr; + if (s == (u16 *) softback_in) + s = (u16 *) vc->vc_origin; + while (count--) { + unsigned short *start; + unsigned short *le; + unsigned short c; + int x = 0; + unsigned short attr = 1; + + start = s; + le = advance_row(s, 1); + do { + c = scr_readw(s); + if (attr != (c & 0xff00)) { + attr = c & 0xff00; + if (s > start) { + accel_putcs(vc, p, start, + s - start, + real_y(p, line), + x); + x += s - start; + start = s; + } + } + if (c == scr_readw(d)) { + if (s > start) { + accel_putcs(vc, p, start, + s - start, + real_y(p, line), + x); + x += s - start + 1; + start = s + 1; + } else { + x++; + start++; + } + } + s++; + d++; + } while (s < le); + if (s > start) + accel_putcs(vc, p, start, s - start, + real_y(p, line), x); + line++; + if (d == (u16 *) softback_end) + d = (u16 *) softback_buf; + if (d == (u16 *) softback_in) + d = (u16 *) vc->vc_origin; + if (s == (u16 *) softback_end) + s = (u16 *) softback_buf; + if (s == (u16 *) softback_in) + s = (u16 *) vc->vc_origin; + } +} + +static void fbcon_redraw(struct vc_data *vc, struct display *p, + int line, int count, int offset) +{ + unsigned short *d = (unsigned short *) + (vc->vc_origin + vc->vc_size_row * line); + unsigned short *s = d + offset; + + while (count--) { + unsigned short *start = s; + unsigned short *le = advance_row(s, 1); + unsigned short c; + int x = 0; + unsigned short attr = 1; + + do { + c = scr_readw(s); + if (attr != (c & 0xff00)) { + attr = c & 0xff00; + if (s > start) { + accel_putcs(vc, p, start, + s - start, + real_y(p, line), + x); + x += s - start; + start = s; + } + } + if (c == scr_readw(d)) { + if (s > start) { + accel_putcs(vc, p, start, + s - start, + real_y(p, line), + x); + x += s - start + 1; + start = s + 1; + } else { + x++; + start++; + } + } + scr_writew(c, d); + console_conditional_schedule(); + s++; + d++; + } while (s < le); + if (s > start) + accel_putcs(vc, p, start, s - start, + real_y(p, line), x); + console_conditional_schedule(); + if (offset > 0) + line++; + else { + line--; + /* NOTE: We subtract two lines from these pointers */ + s -= vc->vc_size_row; + d -= vc->vc_size_row; + } + } +} + +/** + * fbcon_redraw_clear - clear area of the screen + * @vc: stucture pointing to current active virtual console + * @p: display structure + * @sy: starting Y coordinate + * @sx: starting X coordinate + * @height: height of area to clear + * @width: width of area to clear + * + * Clears a specified area of the screen. All dimensions are in + * pixels. + * + */ + +void fbcon_redraw_clear(struct vc_data *vc, struct display *p, int sy, + int sx, int height, int width) +{ + int x, y; + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + fbcon_putc(vc, ' ', sy + y, sx + x); +} + + +/** + * fbcon_redraw_bmove - copy area of screen to another area + * @p: display structure + * @sy: origin Y coordinate + * @sx: origin X coordinate + * @dy: destination Y coordinate + * @dx: destination X coordinate + * @h: height of area to copy + * @w: width of area to copy + * + * Copies an area of the screen to another area of the same screen. + * All dimensions are in pixels. + * + * Note that this function cannot be used together with ypan or + * ywrap. + * + */ + +void fbcon_redraw_bmove(struct vc_data *vc, struct display *p, int sy, int sx, int dy, int dx, + int h, int w) +{ + if (sy != dy) + panic("fbcon_redraw_bmove width sy != dy"); + /* h will be always 1, but it does not matter if we are more generic */ + + while (h-- > 0) { + unsigned short *d = (unsigned short *) + (vc->vc_origin + vc->vc_size_row * dy + dx * 2); + unsigned short *s = d + (dx - sx); + unsigned short *start = d; + unsigned short *ls = d; + unsigned short *le = d + w; + unsigned short c; + int x = dx; + unsigned short attr = 1; + + do { + c = scr_readw(d); + if (attr != (c & 0xff00)) { + attr = c & 0xff00; + if (d > start) { + accel_putcs(vc, p, start, + d - start, dy, x); + x += d - start; + start = d; + } + } + if (s >= ls && s < le && c == scr_readw(s)) { + if (d > start) { + accel_putcs(vc, p, start, + d - start, dy, x); + x += d - start + 1; + start = d + 1; + } else { + x++; + start++; + } + } + s++; + d++; + } while (d < le); + if (d > start) + accel_putcs(vc, p, start, d - start, dy, x); + sy++; + dy++; + } +} + +static inline void fbcon_softback_note(struct vc_data *vc, int t, + int count) +{ + unsigned short *p; + + if (vc->vc_num != fg_console) + return; + p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row); + + while (count) { + scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row); + count--; + p = advance_row(p, 1); + softback_in += vc->vc_size_row; + if (softback_in == softback_end) + softback_in = softback_buf; + if (softback_in == softback_top) { + softback_top += vc->vc_size_row; + if (softback_top == softback_end) + softback_top = softback_buf; + } + } + softback_curr = softback_in; +} + +static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, + int count) +{ + int unit = vc->vc_num; + struct display *p = &fb_display[unit]; + int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL); + + if (!p->can_soft_blank && console_blanked) + return 0; + + if (!count || vt_cons[unit]->vc_mode != KD_TEXT) + return 0; + + fbcon_cursor(vc, CM_ERASE); + + /* + * ++Geert: Only use ywrap/ypan if the console is in text mode + * ++Andrew: Only use ypan on hardware text mode when scrolling the + * whole screen (prevents flicker). + */ + + switch (dir) { + case SM_UP: + if (count > vc->vc_rows) /* Maximum realistic size */ + count = vc->vc_rows; + if (softback_top) + fbcon_softback_note(vc, t, count); + if (logo_shown >= 0) + goto redraw_up; + switch (p->scrollmode & __SCROLL_YMASK) { + case __SCROLL_YMOVE: + accel_bmove(p, t + count, 0, t, 0, + b - t - count, vc->vc_cols); + accel_clear(vc, p, b - count, 0, count, + vc->vc_cols); + break; + + case __SCROLL_YWRAP: + if (b - t - count > 3 * vc->vc_rows >> 2) { + if (t > 0) + fbcon_bmove(vc, 0, 0, count, 0, t, + vc->vc_cols); + ywrap_up(p, vc, count); + if (vc->vc_rows - b > 0) + fbcon_bmove(vc, b - count, 0, b, 0, + vc->vc_rows - b, + vc->vc_cols); + } else if (p->scrollmode & __SCROLL_YPANREDRAW) + goto redraw_up; + else + fbcon_bmove(vc, t + count, 0, t, 0, + b - t - count, vc->vc_cols); + fbcon_clear(vc, b - count, 0, count, vc->vc_cols); + break; + + case __SCROLL_YPAN: + if ((p->yscroll + count <= + 2 * (p->vrows - vc->vc_rows)) + && ((!scroll_partial && (b - t == vc->vc_rows)) + || (scroll_partial + && (b - t - count > + 3 * vc->vc_rows >> 2)))) { + if (t > 0) + fbcon_bmove(vc, 0, 0, count, 0, t, + vc->vc_cols); + ypan_up(p, vc, count); + if (vc->vc_rows - b > 0) + fbcon_bmove(vc, b - count, 0, b, 0, + vc->vc_rows - b, + vc->vc_cols); + } else if (p->scrollmode & __SCROLL_YPANREDRAW) + goto redraw_up; + else + fbcon_bmove(vc, t + count, 0, t, 0, + b - t - count, vc->vc_cols); + fbcon_clear(vc, b - count, 0, count, vc->vc_cols); + break; + + case __SCROLL_YREDRAW: + redraw_up: + fbcon_redraw(vc, p, t, b - t - count, + count * vc->vc_cols); + accel_clear(vc, p, real_y(p, b - count), 0, + count, vc->vc_cols); + scr_memsetw((unsigned short *) (vc->vc_origin + + vc->vc_size_row * + (b - count)), + vc->vc_video_erase_char, + vc->vc_size_row * count); + return 1; + } + break; + + case SM_DOWN: + if (count > vc->vc_rows) /* Maximum realistic size */ + count = vc->vc_rows; + switch (p->scrollmode & __SCROLL_YMASK) { + case __SCROLL_YMOVE: + accel_bmove(p, t, 0, t + count, 0, + b - t - count, vc->vc_cols); + accel_clear(vc, p, t, 0, count, vc->vc_cols); + break; + + case __SCROLL_YWRAP: + if (b - t - count > 3 * vc->vc_rows >> 2) { + if (vc->vc_rows - b > 0) + fbcon_bmove(vc, b, 0, b - count, 0, + vc->vc_rows - b, + vc->vc_cols); + ywrap_down(p, vc, count); + if (t > 0) + fbcon_bmove(vc, count, 0, 0, 0, t, + vc->vc_cols); + } else if (p->scrollmode & __SCROLL_YPANREDRAW) + goto redraw_down; + else + fbcon_bmove(vc, t, 0, t + count, 0, + b - t - count, vc->vc_cols); + fbcon_clear(vc, t, 0, count, vc->vc_cols); + break; + + case __SCROLL_YPAN: + if ((count - p->yscroll <= p->vrows - vc->vc_rows) + && ((!scroll_partial && (b - t == vc->vc_rows)) + || (scroll_partial + && (b - t - count > + 3 * vc->vc_rows >> 2)))) { + if (vc->vc_rows - b > 0) + fbcon_bmove(vc, b, 0, b - count, 0, + vc->vc_rows - b, + vc->vc_cols); + ypan_down(p, vc, count); + if (t > 0) + fbcon_bmove(vc, count, 0, 0, 0, t, + vc->vc_cols); + } else if (p->scrollmode & __SCROLL_YPANREDRAW) + goto redraw_down; + else + fbcon_bmove(vc, t, 0, t + count, 0, + b - t - count, vc->vc_cols); + fbcon_clear(vc, t, 0, count, vc->vc_cols); + break; + + case __SCROLL_YREDRAW: + redraw_down: + fbcon_redraw(vc, p, b - 1, b - t - count, + -count * vc->vc_cols); + accel_clear(vc, p, real_y(p, t), 0, count, + vc->vc_cols); + scr_memsetw((unsigned short *) (vc->vc_origin + + vc->vc_size_row * + t), + vc->vc_video_erase_char, + vc->vc_size_row * count); + return 1; + } + } + return 0; +} + + +static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, + int height, int width) +{ + int unit = vc->vc_num; + struct display *p = &fb_display[unit]; + + if (!p->can_soft_blank && console_blanked) + return; + + if (!width || !height) + return; + + 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))) + fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK); + + /* Split blits that cross physical y_wrap case. + * Pathological case involves 4 blits, better to use recursive + * code rather than unrolled case + * + * Recursive invocations don't need to erase the cursor over and + * over again, so we use fbcon_bmove_rec() + */ + fbcon_bmove_rec(p, sy, sx, dy, dx, height, width, + p->vrows - p->yscroll); +} + +static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, + int dx, int height, int width, u_int y_break) +{ + u_int b; + + if (sy < y_break && sy + height > y_break) { + b = y_break - sy; + if (dy < sy) { /* Avoid trashing self */ + fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, + y_break); + fbcon_bmove_rec(p, sy + b, sx, dy + b, dx, + height - b, width, y_break); + } else { + fbcon_bmove_rec(p, sy + b, sx, dy + b, dx, + height - b, width, y_break); + fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, + y_break); + } + return; + } + + if (dy < y_break && dy + height > y_break) { + b = y_break - dy; + if (dy < sy) { /* Avoid trashing self */ + fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, + y_break); + fbcon_bmove_rec(p, sy + b, sx, dy + b, dx, + height - b, width, y_break); + } else { + fbcon_bmove_rec(p, sy + b, sx, dy + b, dx, + height - b, width, y_break); + fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, + y_break); + } + return; + } + accel_bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, + width); +} + + +static int fbcon_switch(struct vc_data *vc) +{ + int unit = vc->vc_num; + struct display *p = &fb_display[unit]; + struct fb_info *info = p->fb_info; + + if (softback_top) { + int l = fbcon_softback_size / vc->vc_size_row; + if (softback_lines) + fbcon_set_origin(vc); + softback_top = softback_curr = softback_in = softback_buf; + softback_lines = 0; + + if (l > 5) + softback_end = softback_buf + l * vc->vc_size_row; + else { + /* Smaller scrollback makes no sense, and 0 would screw + the operation totally */ + softback_top = 0; + } + } + if (logo_shown >= 0) { + struct vc_data *conp2 = vc_cons[logo_shown].d; + + if (conp2->vc_top == logo_lines + && conp2->vc_bottom == conp2->vc_rows) + conp2->vc_top = 0; + logo_shown = -1; + } + if (info) + info->var.yoffset = p->yscroll = 0; + switch (p->scrollmode & __SCROLL_YMASK) { + case __SCROLL_YWRAP: + scrollback_phys_max = p->vrows - vc->vc_rows; + break; + case __SCROLL_YPAN: + scrollback_phys_max = p->vrows - 2 * vc->vc_rows; + if (scrollback_phys_max < 0) + scrollback_phys_max = 0; + break; + default: + scrollback_phys_max = 0; + break; + } + scrollback_max = 0; + scrollback_current = 0; + + info->currcon = unit; + + update_var(unit, info); + + if (vt_cons[unit]->vc_mode == KD_TEXT) + accel_clear_margins(vc, p, 0); + if (logo_shown == -2) { + logo_shown = fg_console; + fbcon_show_logo(); /* 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 - + vc->vc_top) / 2); + return 0; + } + return 1; +} + +static int fbcon_blank(struct vc_data *vc, int blank) +{ + struct display *p = &fb_display[vc->vc_num]; + struct fb_info *info = p->fb_info; + + if (blank < 0) /* Entering graphics mode */ + return 0; + + fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); + + if (!p->can_soft_blank) { + if (blank) { + unsigned short oldc; + u_int height; + u_int y_break; + + oldc = vc->vc_video_erase_char; + vc->vc_video_erase_char &= p->charmask; + height = vc->vc_rows; + y_break = p->vrows - p->yscroll; + if (height > y_break) { + accel_clear(vc, p, + real_y(p, 0), 0, + y_break, + vc->vc_cols); + accel_clear(vc, p, + real_y(p, + y_break), + 0, + height - y_break, + vc->vc_cols); + } else + accel_clear(vc, p, + real_y(p, 0), 0, + height, + vc->vc_cols); + vc->vc_video_erase_char = oldc; + } + return 0; + } else { + /* Tell console.c that it has to restore the screen itself */ + return 1; + } + fb_blank(blank, info); + return 0; +} + +static void fbcon_free_font(struct display *p) +{ + if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) + kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); + p->fontdata = NULL; + p->userfont = 0; +} + +static inline int fbcon_get_font(struct vc_data *vc, struct console_font_op *op) +{ + struct display *p = &fb_display[vc->vc_num]; + u8 *data = op->data; + 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; + if (!op->data) + return 0; + + if (op->width <= 8) { + j = vc->vc_font.height; + for (i = 0; i < op->charcount; i++) { + memcpy(data, fontdata, j); + memset(data + j, 0, 32 - j); + data += 32; + fontdata += j; + } + } +#ifndef CONFIG_FONTWIDTH8_ONLY + else if (op->width <= 16) { + j = vc->vc_font.height * 2; + for (i = 0; i < op->charcount; i++) { + memcpy(data, fontdata, j); + memset(data + j, 0, 64 - j); + data += 64; + fontdata += j; + } + } else if (op->width <= 24) { + for (i = 0; i < op->charcount; i++) { + for (j = 0; j < vc->vc_font.height; j++) { + *data++ = fontdata[0]; + *data++ = fontdata[1]; + *data++ = fontdata[2]; + fontdata += sizeof(u32); + } + memset(data, 0, 3 * (32 - j)); + data += 3 * (32 - j); + } + } else { + j = vc->vc_font.height * 4; + for (i = 0; i < op->charcount; i++) { + memcpy(data, fontdata, j); + memset(data + j, 0, 128 - j); + data += 128; + fontdata += j; + } + } +#endif + return 0; +} + +static int fbcon_do_set_font(struct vc_data *vc, struct console_font_op *op, + u8 * data, int userfont) +{ + struct display *p = &fb_display[vc->vc_num]; + struct fb_info *info = p->fb_info; + int resize; + int w = op->width; + int h = op->height; + int cnt; + char *old_data = NULL; + + if (!fontwidthvalid(p, w)) { + if (userfont && op->op != KD_FONT_OP_COPY) + kfree(data - FONT_EXTRA_WORDS * sizeof(int)); + return -ENXIO; + } + + if (CON_IS_VISIBLE(vc) && softback_lines) + fbcon_set_origin(vc); + + resize = (w != vc->vc_font.width) || (h != vc->vc_font.height); + if (p->userfont) + old_data = p->fontdata; + if (userfont) + cnt = FNTCHARCNT(data); + else + cnt = 256; + p->fontdata = data; + if ((p->userfont = userfont)) + REFCOUNT(data)++; + vc->vc_font.width = w; + vc->vc_font.height = h; + if (vc->vc_hi_font_mask && cnt == 256) { + vc->vc_hi_font_mask = 0; + if (vc->vc_can_do_color) + vc->vc_complement_mask >>= 1; + p->fgshift--; + p->bgshift--; + p->charmask = 0xff; + + /* ++Edmund: reorder the attribute bits */ + if (vc->vc_can_do_color) { + unsigned short *cp = + (unsigned short *) vc->vc_origin; + int count = vc->vc_screenbuf_size / 2; + unsigned short c; + for (; count > 0; count--, cp++) { + c = scr_readw(cp); + scr_writew(((c & 0xfe00) >> 1) | + (c & 0xff), cp); + } + c = vc->vc_video_erase_char; + vc->vc_video_erase_char = + ((c & 0xfe00) >> 1) | (c & 0xff); + vc->vc_attr >>= 1; + } + + } else if (!vc->vc_hi_font_mask && cnt == 512) { + vc->vc_hi_font_mask = 0x100; + if (vc->vc_can_do_color) + vc->vc_complement_mask <<= 1; + p->fgshift++; + p->bgshift++; + p->charmask = 0x1ff; + + /* ++Edmund: reorder the attribute bits */ + { + unsigned short *cp = + (unsigned short *) vc->vc_origin; + int count = vc->vc_screenbuf_size / 2; + unsigned short c; + for (; count > 0; count--, cp++) { + unsigned short newc; + c = scr_readw(cp); + if (vc->vc_can_do_color) + newc = + ((c & 0xff00) << 1) | (c & + 0xff); + else + newc = c & ~0x100; + scr_writew(newc, cp); + } + c = vc->vc_video_erase_char; + if (vc->vc_can_do_color) { + vc->vc_video_erase_char = + ((c & 0xff00) << 1) | (c & 0xff); + vc->vc_attr <<= 1; + } else + vc->vc_video_erase_char = c & ~0x100; + } + + } + + if (resize) { + /* reset wrap/pan */ + info->var.xoffset = info->var.yoffset = p->yscroll = 0; + p->vrows = info->var.yres_virtual / h; + if ((info->var.yres % h) + && (info->var.yres_virtual % h < info->var.yres % h)) + p->vrows--; + updatescrollmode(p, vc); + vc_resize(vc->vc_num, info->var.xres / w, info->var.yres / h); + if (CON_IS_VISIBLE(vc) && softback_buf) { + int l = fbcon_softback_size / vc->vc_size_row; + if (l > 5) + softback_end = + softback_buf + l * vc->vc_size_row; + else { + /* Smaller scrollback makes no sense, and 0 would screw + the operation totally */ + softback_top = 0; + } + } + } else if (CON_IS_VISIBLE(vc) + && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) { + accel_clear_margins(vc, p, 0); + update_screen(vc->vc_num); + } + + if (old_data && (--REFCOUNT(old_data) == 0)) + kfree(old_data - FONT_EXTRA_WORDS * sizeof(int)); + return 0; +} + +static inline int fbcon_copy_font(struct vc_data *vc, struct console_font_op *op) +{ + struct display *od, *p = &fb_display[vc->vc_num]; + int h = op->height; + + if (h < 0 || !vc_cons_allocated(h)) + return -ENOTTY; + if (h == vc->vc_num) + return 0; /* nothing to do */ + od = &fb_display[h]; + if (od->fontdata == p->fontdata) + return 0; /* already the same font... */ + op->width = vc->vc_font.width; + op->height = vc->vc_font.height; + return fbcon_do_set_font(vc, op, od->fontdata, od->userfont); +} + +static inline int fbcon_set_font(struct vc_data *vc, struct console_font_op *op) +{ + int w = op->width; + int h = op->height; + int size = h; + 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; + + if (w > 8) { + if (w <= 16) + size *= 2; + else + size *= 4; + } + size *= op->charcount; + + if (! + (new_data = + kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER))) + return -ENOMEM; + new_data += FONT_EXTRA_WORDS * sizeof(int); + FNTSIZE(new_data) = size; + FNTCHARCNT(new_data) = op->charcount; + REFCOUNT(new_data) = 0; /* usage counter */ + p = new_data; + if (w <= 8) { + for (i = 0; i < op->charcount; i++) { + memcpy(p, data, h); + data += 32; + p += h; + } + } +#ifndef CONFIG_FONTWIDTH8_ONLY + else if (w <= 16) { + h *= 2; + for (i = 0; i < op->charcount; i++) { + memcpy(p, data, h); + data += 64; + p += h; + } + } else if (w <= 24) { + for (i = 0; i < op->charcount; i++) { + int j; + for (j = 0; j < h; j++) { + memcpy(p, data, 3); + p[3] = 0; + data += 3; + p += sizeof(u32); + } + data += 3 * (32 - h); + } + } else { + h *= 4; + for (i = 0; i < op->charcount; i++) { + memcpy(p, data, h); + data += 128; + 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 */ + k = 0; + while (p > new_data) + k += *--(u32 *) p; + FNTSUM(new_data) = k; + /* Check if the same font is on some other console already */ + for (i = 0; i < MAX_NR_CONSOLES; i++) { + struct vc_data *tmp = vc_cons[i].d; + + if (fb_display[i].userfont && + fb_display[i].fontdata && + FNTSUM(fb_display[i].fontdata) == k && + FNTSIZE(fb_display[i].fontdata) == size && + tmp->vc_font.width == w && + !memcmp(fb_display[i].fontdata, new_data, size)) { + kfree(new_data - FONT_EXTRA_WORDS * sizeof(int)); + new_data = fb_display[i].fontdata; + break; + } + } + return fbcon_do_set_font(vc, op, new_data, 1); +} + +static inline int fbcon_set_def_font(struct vc_data *vc, struct console_font_op *op) +{ + char name[MAX_FONT_NAME]; + struct font_desc *f; + struct display *p = &fb_display[vc->vc_num]; + struct fb_info *info = p->fb_info; + + if (!op->data) + f = get_default_font(info->var.xres, info->var.yres); + else if (strncpy_from_user(name, op->data, MAX_FONT_NAME - 1) < 0) + return -EFAULT; + else { + name[MAX_FONT_NAME - 1] = 0; + if (!(f = find_font(name))) + return -ENOENT; + } + op->width = f->width; + op->height = f->height; + return fbcon_do_set_font(vc, op, f->data, 0); +} + +static int fbcon_font_op(struct vc_data *vc, struct console_font_op *op) +{ + switch (op->op) { + case KD_FONT_OP_SET: + return fbcon_set_font(vc, op); + case KD_FONT_OP_GET: + return fbcon_get_font(vc, op); + case KD_FONT_OP_SET_DEFAULT: + return fbcon_set_def_font(vc, op); + case KD_FONT_OP_COPY: + return fbcon_copy_font(vc, op); + default: + return -ENOSYS; + } +} + +static u16 palette_red[16]; +static u16 palette_green[16]; +static u16 palette_blue[16]; + +static struct fb_cmap palette_cmap = { + 0, 16, palette_red, palette_green, palette_blue, NULL +}; + +static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) +{ + int unit = vc->vc_num; + struct display *p = &fb_display[unit]; + struct fb_info *info = p->fb_info; + int i, j, k; + u8 val; + + if (!vc->vc_can_do_color + || (!p->can_soft_blank && console_blanked)) + return -EINVAL; + for (i = j = 0; i < 16; i++) { + k = table[i]; + val = vc->vc_palette[j++]; + palette_red[k] = (val << 8) | val; + val = vc->vc_palette[j++]; + palette_green[k] = (val << 8) | val; + val = vc->vc_palette[j++]; + palette_blue[k] = (val << 8) | val; + } + if (info->var.bits_per_pixel <= 4) + palette_cmap.len = 1 << info->var.bits_per_pixel; + else + palette_cmap.len = 16; + palette_cmap.start = 0; + return fb_set_cmap(&palette_cmap, 1, info); +} + +static u16 *fbcon_screen_pos(struct vc_data *vc, int offset) +{ + int line; + unsigned long p; + + if (vc->vc_num != fg_console || !softback_lines) + return (u16 *) (vc->vc_origin + offset); + line = offset / vc->vc_size_row; + if (line >= softback_lines) + return (u16 *) (vc->vc_origin + offset - + softback_lines * vc->vc_size_row); + p = softback_curr + offset; + if (p >= softback_end) + p += softback_buf - softback_end; + return (u16 *) p; +} + +static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos, + int *px, int *py) +{ + int x, y; + unsigned long ret; + if (pos >= vc->vc_origin && pos < vc->vc_scr_end) { + unsigned long offset = (pos - vc->vc_origin) / 2; + + x = offset % vc->vc_cols; + y = offset / vc->vc_cols; + if (vc->vc_num == fg_console) + y += softback_lines; + ret = pos + (vc->vc_cols - x) * 2; + } else if (vc->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 % vc->vc_cols; + y = offset / vc->vc_cols; + ret = pos + (vc->vc_cols - x) * 2; + if (ret == softback_end) + ret = softback_buf; + if (ret == softback_in) + ret = vc->vc_origin; + } else { + /* Should not happen */ + x = y = 0; + ret = vc->vc_origin; + } + if (px) + *px = x; + if (py) + *py = y; + return ret; +} + +/* As we might be inside of softback, we may work with non-contiguous buffer, + that's why we have to use a separate routine. */ +static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt) +{ + while (cnt--) { + u16 a = scr_readw(p); + if (!vc->vc_can_do_color) + a ^= 0x0800; + else if (vc->vc_hi_font_mask == 0x100) + a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | + (((a) & 0x0e00) << 4); + else + a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | + (((a) & 0x0700) << 4); + scr_writew(a, p++); + if (p == (u16 *) softback_end) + p = (u16 *) softback_buf; + if (p == (u16 *) softback_in) + p = (u16 *) vc->vc_origin; + } +} + +static int fbcon_scrolldelta(struct vc_data *vc, int lines) +{ + int unit, offset, limit, scrollback_old; + struct fb_info *info; + struct display *p; + + unit = fg_console; + p = &fb_display[unit]; + info = p->fb_info; + + if (softback_top) { + if (vc->vc_num != unit) + return 0; + if (vt_cons[unit]->vc_mode != KD_TEXT || !lines) + return 0; + if (logo_shown >= 0) { + struct vc_data *conp2 = vc_cons[logo_shown].d; + + if (conp2->vc_top == logo_lines + && conp2->vc_bottom == conp2->vc_rows) + conp2->vc_top = 0; + if (logo_shown == unit) { + unsigned long p, q; + int i; + + p = softback_in; + q = vc->vc_origin + + logo_lines * vc->vc_size_row; + for (i = 0; i < logo_lines; i++) { + if (p == softback_top) + break; + if (p == softback_buf) + p = softback_end; + p -= vc->vc_size_row; + q -= vc->vc_size_row; + scr_memcpyw((u16 *) q, (u16 *) p, + vc->vc_size_row); + } + softback_in = p; + update_region(unit, vc->vc_origin, + logo_lines * vc->vc_cols); + } + logo_shown = -1; + } + fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK); + fbcon_redraw_softback(vc, p, lines); + fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK); + return 0; + } + + if (!scrollback_phys_max) + return -ENOSYS; + + scrollback_old = scrollback_current; + scrollback_current -= lines; + if (scrollback_current < 0) + scrollback_current = 0; + else if (scrollback_current > scrollback_max) + scrollback_current = scrollback_max; + if (scrollback_current == scrollback_old) + return 0; + + if (!p->can_soft_blank && + (console_blanked || vt_cons[unit]->vc_mode != KD_TEXT + || !lines)) + return 0; + fbcon_cursor(vc, CM_ERASE); + + offset = p->yscroll - scrollback_current; + limit = p->vrows; + switch (p->scrollmode && __SCROLL_YMASK) { + case __SCROLL_YWRAP: + info->var.vmode |= FB_VMODE_YWRAP; + break; + case __SCROLL_YPAN: + limit -= vc->vc_rows; + info->var.vmode &= ~FB_VMODE_YWRAP; + break; + } + if (offset < 0) + offset += limit; + else if (offset >= limit) + offset -= limit; + info->var.xoffset = 0; + info->var.yoffset = offset * vc->vc_font.height; + update_var(unit, info); + if (!scrollback_current) + fbcon_cursor(vc, CM_DRAW); + return 0; +} + +static int fbcon_set_origin(struct vc_data *vc) +{ + if (softback_lines && !console_blanked) + fbcon_scrolldelta(vc, softback_lines); + 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 + */ + +const struct consw fb_con = { + .con_startup = fbcon_startup, + .con_init = fbcon_init, + .con_deinit = fbcon_deinit, + .con_clear = fbcon_clear, + .con_putc = fbcon_putc, + .con_putcs = fbcon_putcs, + .con_cursor = fbcon_cursor, + .con_scroll = fbcon_scroll, + .con_bmove = fbcon_bmove, + .con_switch = fbcon_switch, + .con_blank = fbcon_blank, + .con_font_op = fbcon_font_op, + .con_set_palette = fbcon_set_palette, + .con_scrolldelta = fbcon_scrolldelta, + .con_set_origin = fbcon_set_origin, + .con_invert_region = fbcon_invert_region, + .con_screen_pos = fbcon_screen_pos, + .con_getxy = fbcon_getxy, +}; + +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; +} + +void __exit fb_console_exit(void) +{ + give_up_console(&fb_con); +} + +module_init(fb_console_init); +module_exit(fb_console_exit); + +/* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fb_display); +EXPORT_SYMBOL(fbcon_redraw_bmove); +EXPORT_SYMBOL(fbcon_redraw_clear); +EXPORT_SYMBOL(fb_con); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h new file mode 100644 index 000000000000..b49beeccc17e --- /dev/null +++ b/drivers/video/console/fbcon.h @@ -0,0 +1,142 @@ +/* + * linux/drivers/video/console/fbcon.h -- Low level frame buffer based console driver + * + * Copyright (C) 1997 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_FBCON_H +#define _VIDEO_FBCON_H + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/vt_buffer.h> +#include <linux/vt_kern.h> + +#include <asm/io.h> + + /* + * This is the interface between the low-level console driver and the + * low-level frame buffer device + */ + +struct display { + /* Filled in by the frame buffer device */ + u_short can_soft_blank; /* zero if no hardware blanking */ + u_short inverse; /* != 0 text black on white as default */ + struct display_switch *dispsw; /* low level operations */ + + /* Filled in by the low-level console driver */ + struct vc_data *conp; /* pointer to console data */ + struct fb_info *fb_info; /* frame buffer for this console */ + int vrows; /* number of virtual rows */ + unsigned short cursor_x; /* current cursor position */ + unsigned short cursor_y; + unsigned long cursor_pos; + char fontname[40]; /* Font associated to this display */ + u_char *fontdata; + int userfont; /* != 0 if fontdata kmalloc()ed */ + u_short scrollmode; /* Scroll Method */ + short yscroll; /* Hardware scrolling */ + unsigned char fgshift, bgshift; + unsigned short charmask; /* 0xff or 0x1ff */ + unsigned int fontwidthmask; /* 1 at (1 << (width - 1)) if width is supported */ +}; + +/* drivers/video/console/fbcon.c */ +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 + */ + +/* Color */ +#define attr_fgcol(p,s) \ + (((s) >> ((p)->fgshift)) & 0x0f) +#define attr_bgcol(p,s) \ + (((s) >> ((p)->bgshift)) & 0x0f) +#define attr_bgcol_ec(p,conp) \ + ((conp) ? (((conp)->vc_video_erase_char >> ((p)->bgshift)) & 0x0f) : 0) +#define attr_fgcol_ec(p,vc) \ + ((vc) ? (((vc)->vc_video_erase_char >> ((p)->fgshift)) & 0x0f) : 0) + +/* Monochrome */ +#define attr_bold(p,s) \ + ((s) & 0x200) +#define attr_reverse(p,s) \ + (((s) & 0x800) ^ ((p)->inverse ? 0x800 : 0)) +#define attr_underline(p,s) \ + ((s) & 0x400) +#define attr_blink(p,s) \ + ((s) & 0x8000) + + /* + * Scroll Method + */ + +/* Internal flags */ +#define __SCROLL_YPAN 0x001 +#define __SCROLL_YWRAP 0x002 +#define __SCROLL_YMOVE 0x003 +#define __SCROLL_YREDRAW 0x004 +#define __SCROLL_YMASK 0x00f +#define __SCROLL_YFIXED 0x010 +#define __SCROLL_YNOMOVE 0x020 +#define __SCROLL_YPANREDRAW 0x040 +#define __SCROLL_YNOPARTIAL 0x080 + +/* Only these should be used by the drivers */ +/* Which one should you use? If you have a fast card and slow bus, + then probably just 0 to indicate fbcon should choose between + YWRAP/YPAN+MOVE/YMOVE. On the other side, if you have a fast bus + and even better if your card can do fonting (1->8/32bit painting), + you should consider either SCROLL_YREDRAW (if your card is + able to do neither YPAN/YWRAP), or SCROLL_YNOMOVE. + The best is to test it with some real life scrolling (usually, not + all lines on the screen are filled completely with non-space characters, + and REDRAW performs much better on such lines, so don't cat a file + with every line covering all screen columns, it would not be the right + benchmark). + */ +#define SCROLL_YREDRAW (__SCROLL_YFIXED|__SCROLL_YREDRAW) +#define SCROLL_YNOMOVE (__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW) + +/* SCROLL_YNOPARTIAL, used in combination with the above, is for video + cards which can not handle using panning to scroll a portion of the + screen without excessive flicker. Panning will only be used for + whole screens. + */ +/* Namespace consistency */ +#define SCROLL_YNOPARTIAL __SCROLL_YNOPARTIAL + +extern void fbcon_redraw_clear(struct vc_data *, struct display *, int, int, int, int); +extern void fbcon_redraw_bmove(struct vc_data *, struct display *, int, int, int, int, int, int); + +#endif /* _VIDEO_FBCON_H */ diff --git a/include/video/font.h b/drivers/video/console/font.h index 007d97f9b3ef..d612657374d0 100644 --- a/include/video/font.h +++ b/drivers/video/console/font.h @@ -13,7 +13,7 @@ #include <linux/types.h> -struct fbcon_font_desc { +struct font_desc { int idx; char *name; int width, height; @@ -30,22 +30,22 @@ struct fbcon_font_desc { #define ACORN8x8_IDX 6 #define MINI4x6_IDX 7 -extern struct fbcon_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; +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 fbcon_font_desc *fbcon_find_font(char *name); +extern struct font_desc *find_font(char *name); /* Get the default font for a specific screen size */ -extern struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres); +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 diff --git a/drivers/video/font_6x11.c b/drivers/video/console/font_6x11.c index aa95f8863830..062f68d25734 100644 --- a/drivers/video/font_6x11.c +++ b/drivers/video/console/font_6x11.c @@ -4,7 +4,7 @@ /* */ /**********************************************/ -#include <video/font.h> +#include "font.h" #define FONTDATAMAX (11*256) @@ -3341,7 +3341,7 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = { }; -struct fbcon_font_desc font_vga_6x11 = { +struct font_desc font_vga_6x11 = { VGA6x11_IDX, "ProFont6x11", 6, diff --git a/drivers/video/font_8x16.c b/drivers/video/console/font_8x16.c index 786619712560..a24ea2b6da52 100644 --- a/drivers/video/font_8x16.c +++ b/drivers/video/console/font_8x16.c @@ -4,7 +4,7 @@ /* */ /**********************************************/ -#include <video/font.h> +#include "font.h" #define FONTDATAMAX 4096 @@ -4621,7 +4621,7 @@ static unsigned char fontdata_8x16[FONTDATAMAX] = { }; -struct fbcon_font_desc font_vga_8x16 = { +struct font_desc font_vga_8x16 = { VGA8x16_IDX, "VGA8x16", 8, diff --git a/drivers/video/font_8x8.c b/drivers/video/console/font_8x8.c index 6358e671f1ce..d7cfa088ef89 100644 --- a/drivers/video/font_8x8.c +++ b/drivers/video/console/font_8x8.c @@ -4,7 +4,7 @@ /* */ /**********************************************/ -#include <video/font.h> +#include "font.h" #define FONTDATAMAX 2048 @@ -2573,7 +2573,7 @@ static unsigned char fontdata_8x8[FONTDATAMAX] = { }; -struct fbcon_font_desc font_vga_8x8 = { +struct font_desc font_vga_8x8 = { VGA8x8_IDX, "VGA8x8", 8, diff --git a/drivers/video/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c index 154d0fb39da7..3536c7edce1f 100644 --- a/drivers/video/font_acorn_8x8.c +++ b/drivers/video/console/font_acorn_8x8.c @@ -2,7 +2,7 @@ #include <linux/config.h> -#include <video/font.h> +#include "font.h" static unsigned char acorndata_8x8[] = { /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */ @@ -263,7 +263,7 @@ static unsigned char acorndata_8x8[] = { /* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -struct fbcon_font_desc font_acorn_8x8 = { +struct font_desc font_acorn_8x8 = { ACORN8x8_IDX, "Acorn8x8", 8, diff --git a/drivers/video/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c index 9fe2db2a6edc..8e4cb92c82b7 100644 --- a/drivers/video/font_mini_4x6.c +++ b/drivers/video/console/font_mini_4x6.c @@ -39,7 +39,7 @@ __END__; MSBit to LSBit = left to right. */ -#include <video/font.h> +#include "font.h" #define FONTDATAMAX 1536 @@ -2147,7 +2147,7 @@ static unsigned char fontdata_mini_4x6[FONTDATAMAX] = { /*}*/ }; -struct fbcon_font_desc font_mini_4x6 = { +struct font_desc font_mini_4x6 = { MINI4x6_IDX, "MINI4x6", 4, diff --git a/drivers/video/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c index c8d7da5714c5..c84048423cf8 100644 --- a/drivers/video/font_pearl_8x8.c +++ b/drivers/video/console/font_pearl_8x8.c @@ -9,7 +9,7 @@ /* */ /**********************************************/ -#include <video/font.h> +#include "font.h" #define FONTDATAMAX 2048 @@ -2577,7 +2577,7 @@ static unsigned char fontdata_pearl8x8[FONTDATAMAX] = { }; -struct fbcon_font_desc font_pearl_8x8 = { +struct font_desc font_pearl_8x8 = { PEARL8x8_IDX, "PEARL8x8", 8, diff --git a/drivers/video/font_sun12x22.c b/drivers/video/console/font_sun12x22.c index 803b35ea8d72..99f01c060fbb 100644 --- a/drivers/video/font_sun12x22.c +++ b/drivers/video/console/font_sun12x22.c @@ -1,4 +1,4 @@ -#include <video/font.h> +#include "font.h" #define FONTDATAMAX 11264 @@ -6206,7 +6206,7 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = { }; -struct fbcon_font_desc font_sun_12x22 = { +struct font_desc font_sun_12x22 = { SUN12x22_IDX, "SUN12x22", 12, diff --git a/drivers/video/font_sun8x16.c b/drivers/video/console/font_sun8x16.c index 9f5bc40b4762..a8f6d60e8c6e 100644 --- a/drivers/video/font_sun8x16.c +++ b/drivers/video/console/font_sun8x16.c @@ -1,4 +1,4 @@ -#include <video/font.h> +#include "font.h" #define FONTDATAMAX 4096 @@ -261,7 +261,7 @@ static unsigned char fontdata_sun8x16[FONTDATAMAX] = { /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; -struct fbcon_font_desc font_sun_8x16 = { +struct font_desc font_sun_8x16 = { SUN8x16_IDX, "SUN8x16", 8, diff --git a/drivers/video/fonts.c b/drivers/video/console/fonts.c index 436f3a5ec2fc..54eda88e89de 100644 --- a/drivers/video/fonts.c +++ b/drivers/video/console/fonts.c @@ -12,18 +12,18 @@ * for more details. */ - #include <linux/config.h> +#include <linux/module.h> #include <linux/types.h> #include <linux/string.h> #if defined(__mc68000__) || defined(CONFIG_APUS) #include <asm/setup.h> #endif -#include <video/font.h> +#include "font.h" #define NO_FONTS -static struct fbcon_font_desc *fbcon_fonts[] = { +static struct font_desc *fonts[] = { #ifdef CONFIG_FONT_8x8 #undef NO_FONTS &font_vga_8x8, @@ -33,9 +33,7 @@ static struct fbcon_font_desc *fbcon_fonts[] = { &font_vga_8x16, #endif #ifdef CONFIG_FONT_6x11 -#if defined(CONFIG_FBCON_ACCEL) || defined(CONFIG_FB_SBUS) #undef NO_FONTS -#endif &font_vga_6x11, #endif #ifdef CONFIG_FONT_SUN8x16 @@ -43,9 +41,7 @@ static struct fbcon_font_desc *fbcon_fonts[] = { &font_sun_8x16, #endif #ifdef CONFIG_FONT_SUN12x22 -#if defined(CONFIG_FB_SBUS) || defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FBCON_ACCEL) #undef NO_FONTS -#endif &font_sun_12x22, #endif #ifdef CONFIG_FONT_ACORN_8x8 @@ -62,7 +58,7 @@ static struct fbcon_font_desc *fbcon_fonts[] = { #endif }; -#define num_fonts (sizeof(fbcon_fonts)/sizeof(*fbcon_fonts)) +#define num_fonts (sizeof(fonts)/sizeof(*fonts)) #ifdef NO_FONTS #error No fonts configured. @@ -70,7 +66,7 @@ static struct fbcon_font_desc *fbcon_fonts[] = { /** - * fbcon_find_font - find a font + * find_font - find a font * @name: string name of a font * * Find a specified font with string name @name. @@ -80,19 +76,19 @@ static struct fbcon_font_desc *fbcon_fonts[] = { * */ -struct fbcon_font_desc *fbcon_find_font(char *name) +struct font_desc *find_font(char *name) { unsigned int i; for (i = 0; i < num_fonts; i++) - if (!strcmp(fbcon_fonts[i]->name, name)) - return fbcon_fonts[i]; + if (!strcmp(fonts[i]->name, name)) + return fonts[i]; return NULL; } /** - * fbcon_get_default_font - get default font + * get_default_font - get default font * @xres: screen size of X * @yres: screen size of Y * @@ -104,15 +100,15 @@ struct fbcon_font_desc *fbcon_find_font(char *name) * */ -struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres) +struct font_desc *get_default_font(int xres, int yres) { int i, c, cc; - struct fbcon_font_desc *f, *g; + struct font_desc *f, *g; g = NULL; cc = -10000; for(i=0; i<num_fonts; i++) { - f = fbcon_fonts[i]; + f = fonts[i]; c = f->pref; #if defined(__mc68000__) || defined(CONFIG_APUS) #ifdef CONFIG_FONT_PEARL_8x8 @@ -133,3 +129,14 @@ struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres) } return g; } + +int init_module(void) { return 0; }; +void cleanup_module(void) {}; + +EXPORT_SYMBOL(fonts); +EXPORT_SYMBOL(find_font); +EXPORT_SYMBOL(get_default_font); + +MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); +MODULE_DESCRIPTION("Console Fonts"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/mdacon.c b/drivers/video/console/mdacon.c index f1c47bfaa270..9e88eeb9f479 100644 --- a/drivers/video/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -33,7 +33,6 @@ #include <linux/module.h> #include <linux/tty.h> #include <linux/console.h> -#include <linux/console_struct.h> #include <linux/string.h> #include <linux/kd.h> #include <linux/slab.h> @@ -364,7 +363,7 @@ static void mdacon_init(struct vc_data *c, int init) c->vc_cols = mda_num_columns; c->vc_rows = mda_num_lines; } else { - vc_resize_con(mda_num_lines, mda_num_columns, c->vc_num); + vc_resize(c->vc_num, mda_num_columns, mda_num_lines); } /* make the first MDA console visible */ diff --git a/drivers/video/newport_con.c b/drivers/video/console/newport_con.c index 364874dff50d..fae9b93070ba 100644 --- a/drivers/video/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -16,7 +16,6 @@ #include <linux/kd.h> #include <linux/selection.h> #include <linux/console.h> -#include <linux/console_struct.h> #include <linux/vt_kern.h> #include <linux/mm.h> #include <linux/module.h> @@ -30,12 +29,12 @@ #define INCLUDE_LINUX_LOGO_DATA #include <asm/linux_logo.h> -#include <video/font.h> +#include "font.h" #define LOGO_W 80 #define LOGO_H 80 -extern struct fbcon_font_desc font_vga_8x16; +extern struct font_desc font_vga_8x16; #define FONT_DATA ((unsigned char *)font_vga_8x16.data) diff --git a/drivers/video/prom.uni b/drivers/video/console/prom.uni index 58f9c04ed9d3..58f9c04ed9d3 100644 --- a/drivers/video/prom.uni +++ b/drivers/video/console/prom.uni diff --git a/drivers/video/promcon.c b/drivers/video/console/promcon.c index d72ce48cb3f1..c2a3deca898f 100644 --- a/drivers/video/promcon.c +++ b/drivers/video/console/promcon.c @@ -15,7 +15,6 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/console.h> -#include <linux/console_struct.h> #include <linux/vt_kern.h> #include <linux/selection.h> #include <linux/fb.h> @@ -184,7 +183,7 @@ promcon_init(struct vc_data *conp, int init) } if (!init) { if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1) - vc_resize_con(ph + 1, pw + 1, conp->vc_num); + vc_resize(conp->unit, pw + 1, ph + 1); } } diff --git a/drivers/video/sti.h b/drivers/video/console/sti.h index feea4fb92fbb..feea4fb92fbb 100644 --- a/drivers/video/sti.h +++ b/drivers/video/console/sti.h diff --git a/drivers/video/sticon.c b/drivers/video/console/sticon.c index 7dddbe42d40a..634b0289dea7 100644 --- a/drivers/video/sticon.c +++ b/drivers/video/console/sticon.c @@ -49,7 +49,6 @@ #include <linux/kernel.h> #include <linux/tty.h> #include <linux/console.h> -#include <linux/console_struct.h> #include <linux/errno.h> #include <linux/vt_kern.h> #include <linux/selection.h> @@ -137,7 +136,7 @@ static void sticon_init(struct vc_data *c, int init) 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_con(vc_rows, vc_cols, c->vc_num); + vc_resize(c->vc_num, vc_cols, vc_rows); } static void sticon_deinit(struct vc_data *c) diff --git a/drivers/video/sticore.c b/drivers/video/console/sticore.c index 8437e1570ed3..8437e1570ed3 100644 --- a/drivers/video/sticore.c +++ b/drivers/video/console/sticore.c diff --git a/drivers/video/vgacon.c b/drivers/video/console/vgacon.c index b65d47810913..4f7d0c731658 100644 --- a/drivers/video/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -41,7 +41,6 @@ #include <linux/kernel.h> #include <linux/tty.h> #include <linux/console.h> -#include <linux/console_struct.h> #include <linux/string.h> #include <linux/kd.h> #include <linux/slab.h> @@ -180,6 +179,13 @@ static const char __init *vgacon_startup(void) #endif } + /* VGA16 modes are not handled by VGACON */ + if ((ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */ + (ORIG_VIDEO_MODE == 0x0E) || /* 640x200/4 */ + (ORIG_VIDEO_MODE == 0x10) || /* 640x350/4 */ + (ORIG_VIDEO_MODE == 0x12) || /* 640x480/4 */ + (ORIG_VIDEO_MODE == 0x6A)) /* 800x600/4, 0x6A is very common */ + goto no_vga; vga_video_num_lines = ORIG_VIDEO_LINES; vga_video_num_columns = ORIG_VIDEO_COLS; @@ -838,8 +844,8 @@ vgacon_do_font_op(char *arg, int set, int ch512) static int vgacon_adjust_height(unsigned fontheight) { - int rows, maxscan; unsigned char ovr, vde, fsr; + int rows, maxscan, i; if (fontheight == vga_video_font_height) return 0; @@ -881,7 +887,12 @@ vgacon_adjust_height(unsigned fontheight) outb_p( vde, vga_video_port_val ); spin_unlock_irq(&vga_lock); - vc_resize_all(rows, 0); /* Adjust console size */ + for (i = 0; i < MAX_NR_CONSOLES; i++) { + struct vc_data *c = vc_cons[i].d; + + if (c && c->vc_sw == &vga_con) + vc_resize(c->vc_num, 0, rows); /* Adjust console size */ + } return 0; } diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 87b44e7865da..19031e2573f6 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -96,13 +96,11 @@ 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; - struct fb_par_control par; - struct { - __u8 red, green, blue; - } palette[256]; - + struct fb_info info; + struct display display; /* Will disappear */ + struct fb_par_control par; + u32 pseudo_palette[17]; + struct cmap_regs *cmap_regs; unsigned long cmap_regs_phys; @@ -118,14 +116,6 @@ struct fb_info_control { int control_use_bank2; unsigned long total_vram; unsigned char vram_attr; - union { -#ifdef FBCON_HAS_CFB16 - u16 cfb16[16]; -#endif -#ifdef FBCON_HAS_CFB32 - u32 cfb32[16]; -#endif - } fbcon_cmap; }; /* control register access macro */ @@ -136,33 +126,15 @@ struct fb_info_control { /* * struct fb_ops */ -static int control_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *info); -static int control_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info); -static int control_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info); -static int control_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *info); -static int control_get_cmap(struct fb_cmap *cmap, int kspc, int con, +static int controlfb_pan_display(struct fb_var_screeninfo *var, int con, 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); static int controlfb_blank(int blank_mode, struct fb_info *info); -static int control_mmap(struct fb_info *info, struct file *file, +static int controlfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); - -/* - * low level fbcon ops - */ -static int controlfb_switch(int con, struct fb_info *info); -static int controlfb_updatevar(int con, struct fb_info *info); - -/* - * low level cmap set/get ops - */ -static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green, - u_int *blue, u_int *transp, struct fb_info *info); +static int controlfb_set_par (struct fb_info *info); +static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); /* * inititialization @@ -170,13 +142,6 @@ static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green, int control_init(void); void control_setup(char *); -/* - * low level fbcon revc ops - */ -static void control_cfb16_revc(struct display *p, int xx, int yy); -static void control_cfb32_revc(struct display *p, int xx, int yy); - - /******************** Prototypes for internal functions **********************/ static void set_control_clock(unsigned char *params); @@ -184,10 +149,6 @@ static int init_control(struct fb_info_control *p); static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par); static int control_of_init(struct device_node *dp); -static void control_par_to_fix(struct fb_par_control *par, - struct fb_fix_screeninfo *fix, struct fb_info_control *p); -static void control_set_dispsw(struct display *disp, int cmode, - struct fb_info_control *p); static void find_vram_size(struct fb_info_control *p); static int read_control_sense(struct fb_info_control *p); static int calc_clock_params(unsigned long clk, unsigned char *param); @@ -195,13 +156,6 @@ static int control_var_to_par(struct fb_var_screeninfo *var, struct fb_par_control *par, const struct fb_info *fb_info); static inline void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var); -static void control_par_to_fix(struct fb_par_control *par, - struct fb_fix_screeninfo *fix, struct fb_info_control *p); -static void control_par_to_display(struct fb_par_control *par, - struct display *disp, struct fb_fix_screeninfo *fix, - struct fb_info_control *p); -static void control_set_dispsw(struct display *disp, int cmode, - struct fb_info_control *p); static void control_init_info(struct fb_info *info, struct fb_info_control *p); static void control_cleanup(void); @@ -216,16 +170,19 @@ static int default_cmode __initdata = CMODE_NVRAM; static struct fb_ops controlfb_ops = { - .owner = THIS_MODULE, - .fb_get_fix = control_get_fix, - .fb_get_var = control_get_var, - .fb_set_var = control_set_var, - .fb_get_cmap = control_get_cmap, - .fb_set_cmap = gen_set_cmap, - .fb_setcolreg = controlfb_setcolreg, - .fb_pan_display =control_pan_display, - .fb_blank = controlfb_blank, - .fb_mmap = control_mmap, + .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, + .fb_mmap = controlfb_mmap, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, }; @@ -251,87 +208,48 @@ void cleanup_module(void) } #endif -/*********** Providing our information to the user ************/ - -static int control_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *info) +/* + * Checks a var structure + */ +static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info) { - struct fb_info_control *p = (struct fb_info_control *) info; - - if(con == -1) { - control_par_to_fix(&p->par, fix, p); - } else { - struct fb_par_control par; - - control_var_to_par(&fb_display[con].var, &par, info); - control_par_to_fix(&par, fix, p); - } - return 0; -} + struct fb_par_control par; + int err; -static int control_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) -{ - struct fb_info_control *p = (struct fb_info_control *) info; + err = control_var_to_par(var, &par, info); + if (err) + return err; + control_par_to_var(&par, var); - if(con == -1) { - control_par_to_var(&p->par, var); - } else { - *var = fb_display[con].var; - } return 0; } - /* - * Sets everything according to var + * Applies current var to display */ -static int control_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) +static int controlfb_set_par (struct fb_info *info) { struct fb_info_control *p = (struct fb_info_control *) info; - struct display *disp; struct fb_par_control par; - int depthchange, err; - int activate = var->activate; + int err; - if((err = control_var_to_par(var, &par, info))) { - if (con < 0) - printk (KERN_ERR "control_set_var: error calling" - " control_var_to_par: %d.\n", err); + if((err = control_var_to_par(&info->var, &par, info))) { + printk (KERN_ERR "controlfb_set_par: error calling" + " control_var_to_par: %d.\n", err); return err; } - control_par_to_var(&par, var); - - if ((activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) - return 0; - - disp = (con >= 0) ? &fb_display[con] : info->disp; + control_set_hardware(p, &par); - depthchange = (disp->var.bits_per_pixel != var->bits_per_pixel); - if(!VAR_MATCH(&disp->var, var)) { - struct fb_fix_screeninfo fix; - control_par_to_fix(&par, &fix, p); - control_par_to_display(&par, disp, &fix, p); - if(info->changevar) - (*info->changevar)(con); - } else - disp->var = *var; - - if (con == info->currcon) { - control_set_hardware(p, &par); - if(depthchange) { - if((err = fb_alloc_cmap(&disp->cmap, 0, 0))) - return err; - do_install_cmap(con, info); - } - } + info->fix.visual = (p->par.cmode == CMODE_8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; + info->fix.line_length = p->par.pitch; + info->fix.xpanstep = 32 >> p->par.cmode; + info->fix.ypanstep = 1; return 0; } - /* * Set screen start address according to var offset values */ @@ -347,7 +265,7 @@ static inline void set_screen_start(int xoffset, int yoffset, } -static int control_pan_display(struct fb_var_screeninfo *var, int con, +static int controlfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) { unsigned int xoffset, hstep; @@ -369,48 +287,30 @@ static int control_pan_display(struct fb_var_screeninfo *var, int con, return 0; } -static int control_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) -{ - if (con == info->currcon) /* current console? */ - return fb_get_cmap(cmap, kspc, controlfb_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); - } - return 0; -} /* * Private mmap since we want to have a different caching on the framebuffer * for controlfb. * Note there's no locking in here; it's done in fb_mmap() in fbmem.c. */ -static int control_mmap(struct fb_info *info, struct file *file, +static int controlfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { - struct fb_ops *fb = info->fbops; - struct fb_fix_screeninfo fix; - struct fb_var_screeninfo var; unsigned long off, start; u32 len; - fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); off = vma->vm_pgoff << PAGE_SHIFT; /* frame buffer memory */ - start = fix.smem_start; - len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.smem_len); + start = info->fix.smem_start; + len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.smem_len); if (off >= len) { /* memory mapped io */ off -= len; - fb->fb_get_var(&var, PROC_CONSOLE(info), info); - if (var.accel_flags) + if (info->var.accel_flags) return -EINVAL; - start = fix.mmio_start; - len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.mmio_len); + start = info->fix.mmio_start; + len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.mmio_len); pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED; } else { /* framebuffer */ @@ -428,44 +328,6 @@ static int control_mmap(struct fb_info *info, struct file *file, return 0; } - -/******************** End of controlfb_ops implementation ******************/ - -/* - * low level fbcon ops - */ - -static int controlfb_switch(int con, struct fb_info *info) -{ - struct fb_info_control *p = (struct fb_info_control *)info; - struct fb_par_control par; - - if (info->currcon >= 0 && fb_display[info->currcon].cmap.len) - fb_get_cmap(&fb_display[info->currcon].cmap, 1, controlfb_getcolreg, - info); - info->currcon = con; - - fb_display[con].var.activate = FB_ACTIVATE_NOW; - control_var_to_par(&fb_display[con].var, &par, info); - control_set_hardware(p, &par); - control_set_dispsw(&fb_display[con], par.cmode, p); - do_install_cmap(con, info); - - return 1; -} - - -static int controlfb_updatevar(int con, struct fb_info *info) -{ - struct fb_var_screeninfo *var = &fb_display[con].var; - struct fb_info_control *p = (struct fb_info_control *) info; - - set_screen_start(var->xoffset, var->yoffset, p); - - return 0; -} - - static int controlfb_blank(int blank_mode, struct fb_info *info) { struct fb_info_control *p = (struct fb_info_control *) info; @@ -498,30 +360,10 @@ static int controlfb_blank(int blank_mode, struct fb_info *info) return 0; } - -/* - * low level cmap set/get ops - */ - -static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green, - u_int *blue, u_int *transp, struct fb_info *info) -{ - struct fb_info_control *p = (struct fb_info_control *) 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; -} - static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { struct fb_info_control *p = (struct fb_info_control *) info; - u_int i; __u8 r, g, b; if (regno > 255) @@ -531,32 +373,34 @@ static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, g = green >> 8; b = blue >> 8; - p->palette[regno].red = r; - p->palette[regno].green = g; - p->palette[regno].blue = b; - out_8(&p->cmap_regs->addr, regno); /* tell clut what addr to fill */ out_8(&p->cmap_regs->lut, r); /* send one color channel at */ out_8(&p->cmap_regs->lut, g); /* a time... */ out_8(&p->cmap_regs->lut, b); - if (regno < 16) + if (regno < 16) { + int i; switch (p->par.cmode) { -#ifdef FBCON_HAS_CFB16 - case CMODE_16: - p->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case CMODE_32: - i = (regno << 8) | regno; - p->fbcon_cmap.cfb32[regno] = (i << 16) | i; - break; -#endif + case CMODE_16: + ((u16 *) (info->pseudo_palette))[regno] = + (regno << 10) | (regno << 5) | regno; + break; + case CMODE_32: + i = (regno << 8) | regno; + ((u32 *) (info->pseudo_palette))[regno] = + (i << 16) | i; + break; } + } + return 0; } + +/******************** End of controlfb_ops implementation ******************/ + + + static void set_control_clock(unsigned char *params) { #ifdef CONFIG_ADB_CUDA @@ -580,7 +424,8 @@ static int __init init_control(struct fb_info_control *p) { int full, sense, vmode, cmode, vyres; struct fb_var_screeninfo var; - + int rc; + printk(KERN_INFO "controlfb: "); full = p->total_vram == 0x400000; @@ -613,6 +458,10 @@ static int __init init_control(struct fb_info_control *p) } } + /* Initialize info structure */ + control_init_info(&p->info, p); + + /* Setup default var */ if (mac_vmode_to_var(vmode, cmode, &var) < 0) { /* This shouldn't happen! */ printk("mac_vmode_to_var(%d, %d,) failed\n", vmode, cmode); @@ -631,18 +480,14 @@ try_again: if (vyres > var.yres) var.yres_virtual = vyres; - control_init_info(&p->info, p); - p->info.currcon = -1; + /* Apply default var */ + p->info.var = var; var.activate = FB_ACTIVATE_NOW; + rc = gen_set_var(&var, -1, &p->info); + if (rc && (vmode != VMODE_640_480_60 || cmode != CMODE_8)) + goto try_again; - if (control_set_var(&var, -1, &p->info) < 0) { - if (vmode != VMODE_640_480_60 || cmode != CMODE_8) - goto try_again; - printk(KERN_ERR "controlfb: initilization failed\n"); - return -ENXIO; - } - - p->info.flags = FBINFO_FLAG_DEFAULT; + /* Register with fbdev layer */ if (register_framebuffer(&p->info) < 0) return -ENXIO; @@ -820,7 +665,7 @@ static int __init control_of_init(struct device_node *dp) printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs); return -ENXIO; } - p = kmalloc(sizeof(*p), GFP_ATOMIC); + p = kmalloc(sizeof(*p), GFP_KERNEL); if (p == 0) return -ENXIO; control_fb = p; /* save it for cleanups */ @@ -1164,171 +1009,41 @@ static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeni var->pixclock >>= par->regvals.clock_params[2]; } - -/* - * init fix according to given par - */ -static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix, - struct fb_info_control *p) -{ - memset(fix, 0, sizeof(*fix)); - strcpy(fix->id, "control"); - fix->mmio_start = p->control_regs_phys; - fix->mmio_len = sizeof(struct control_regs); - fix->type = FB_TYPE_PACKED_PIXELS; - - fix->xpanstep = 32 >> par->cmode; - fix->ypanstep = 1; - - fix->smem_start = p->frame_buffer_phys + CTRLFB_OFF; - fix->smem_len = p->total_vram - CTRLFB_OFF; - fix->visual = (par->cmode == CMODE_8) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; - fix->line_length = par->pitch; -} - -/* - * initialize a portion of struct display which low level driver is responsible - * for. - */ -static void control_par_to_display(struct fb_par_control *par, - struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p) -{ - disp->type = fix->type; - disp->can_soft_blank = 1; - disp->scrollmode = SCROLL_YNOMOVE | SCROLL_YNOPARTIAL; - disp->ypanstep = fix->ypanstep; - disp->ywrapstep = fix->ywrapstep; - - control_par_to_var(par, &disp->var); - p->info.screen_base = (char *) p->frame_buffer + CTRLFB_OFF; - disp->visual = fix->visual; - disp->line_length = fix->line_length; - control_set_dispsw(disp, par->cmode, p); -} - - -/* - * our own _revc() routines since generic routines don't work for DIRECT Color - * devices like control - */ -static void control_cfb16_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int bytes = p->next_line, rows; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2; - for (rows = fontheight(p); rows--; dest += bytes) { - switch (fontwidth(p)) { - case 16: - ((u32 *)dest)[6] ^= 0x3def3def; ((u32 *)dest)[7] ^= 0x3def3def; - /* FALL THROUGH */ - case 12: - ((u32 *)dest)[4] ^= 0x3def3def; ((u32 *)dest)[5] ^= 0x3def3def; - /* FALL THROUGH */ - case 8: - ((u32 *)dest)[2] ^= 0x3def3def; ((u32 *)dest)[3] ^= 0x3def3def; - /* FALL THROUGH */ - case 4: - ((u32 *)dest)[0] ^= 0x3def3def; ((u32 *)dest)[1] ^= 0x3def3def; - } - } -} - -static void control_cfb32_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int bytes = p->next_line, rows; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4; - for (rows = fontheight(p); rows--; dest += bytes) { - switch (fontwidth(p)) { - case 16: - ((u32 *)dest)[12] ^= 0x0f0f0f0f; ((u32 *)dest)[13] ^= 0x0f0f0f0f; - ((u32 *)dest)[14] ^= 0x0f0f0f0f; ((u32 *)dest)[15] ^= 0x0f0f0f0f; - /* FALL THROUGH */ - case 12: - ((u32 *)dest)[8] ^= 0x0f0f0f0f; ((u32 *)dest)[9] ^= 0x0f0f0f0f; - ((u32 *)dest)[10] ^= 0x0f0f0f0f; ((u32 *)dest)[11] ^= 0x0f0f0f0f; - /* FALL THROUGH */ - case 8: - ((u32 *)dest)[4] ^= 0x0f0f0f0f; ((u32 *)dest)[5] ^= 0x0f0f0f0f; - ((u32 *)dest)[6] ^= 0x0f0f0f0f; ((u32 *)dest)[7] ^= 0x0f0f0f0f; - /* FALL THROUGH */ - case 4: - ((u32 *)dest)[0] ^= 0x0f0f0f0f; ((u32 *)dest)[1] ^= 0x0f0f0f0f; - ((u32 *)dest)[2] ^= 0x0f0f0f0f; ((u32 *)dest)[3] ^= 0x0f0f0f0f; - /* FALL THROUGH */ - } - } -} - -static struct display_switch control_cfb16 = { - setup: fbcon_cfb16_setup, - bmove: fbcon_cfb16_bmove, - clear: fbcon_cfb16_clear, - putc: fbcon_cfb16_putc, - putcs: fbcon_cfb16_putcs, - revc: control_cfb16_revc, - clear_margins: fbcon_cfb16_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; - -static struct display_switch control_cfb32 = { - setup: fbcon_cfb32_setup, - bmove: fbcon_cfb32_bmove, - clear: fbcon_cfb32_clear, - putc: fbcon_cfb32_putc, - putcs: fbcon_cfb32_putcs, - revc: control_cfb32_revc, - clear_margins: fbcon_cfb32_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; - - -/* - * Set struct dispsw according to given cmode - */ -static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p) -{ - switch (cmode) { -#ifdef FBCON_HAS_CFB8 - case CMODE_8: - disp->dispsw = &fbcon_cfb8; - break; -#endif -#ifdef FBCON_HAS_CFB16 - case CMODE_16: - disp->dispsw = &control_cfb16; - disp->dispsw_data = p->fbcon_cmap.cfb16; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case CMODE_32: - disp->dispsw = &control_cfb32; - disp->dispsw_data = p->fbcon_cmap.cfb32; - break; -#endif - default: - disp->dispsw = &fbcon_dummy; - break; - } -} - - /* * Set misc info vars for this driver */ 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; - strcpy(info->fontname, fontname); + 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->switch_con = &controlfb_switch; - info->updatevar = &controlfb_updatevar; + 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); + + /* Fill fix common fields */ + strcpy(info->fix.id, "control"); + info->fix.mmio_start = p->control_regs_phys; + info->fix.mmio_len = sizeof(struct control_regs); + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.smem_start = p->frame_buffer_phys + CTRLFB_OFF; + info->fix.smem_len = p->total_vram - CTRLFB_OFF; + info->fix.ywrapstep = 0; + info->fix.type_aux = 0; + info->fix.accel = FB_ACCEL_NONE; } diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c index 54c9214b9806..79c11de10abf 100644 --- a/drivers/video/cyberfb.c +++ b/drivers/video/cyberfb.c @@ -1063,7 +1063,7 @@ int __init cyberfb_init(void) } printk("fb%d: %s frame buffer device, using %ldK of video memory\n", - GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10); + minor(fb_info.node), fb_info.modename, CyberSize>>10); /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c index bf299d99ea67..1809827e3af9 100644 --- a/drivers/video/dnfb.c +++ b/drivers/video/dnfb.c @@ -15,8 +15,6 @@ #include <linux/fb.h> #include <linux/module.h> -#include <video/fbcon.h> - /* apollo video HW definitions */ /* @@ -111,7 +109,6 @@ #endif static struct fb_info fb_info; -static struct display disp; /* frame buffer operations */ @@ -120,13 +117,11 @@ static void dnfb_copyarea(struct fb_info *info, struct fb_copyarea *area); static struct fb_ops dn_fb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_blank = dnfb_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = dnfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; struct fb_var_screeninfo dnfb_var __initdata = { @@ -239,22 +234,13 @@ unsigned long __init dnfb_init(unsigned long mem_start) { int err; - strcpy(fb_info.modename, dnfb_fix.id); - fb_info.changevar = NULL; - fb_info.fontname[0] = 0; - fb_info.disp = &disp; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_info.node = NODEV; fb_info.fbops = &dn_fb_ops; - fb_info.currcon = -1; fb_info.fix = dnfb_fix; fb_info.var = dnfb_var; + fb_info.screen_base = (u_char *) fb_info.fix.smem_start; fb_alloc_cmap(&fb_info.cmap, 2, 0); - gen_set_disp(-1, &fb_info); - - fb_info.screen_base = (u_char *) fb_info.fix.smem_start; err = register_framebuffer(&fb_info); if (err < 0) diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index d581cb7faf1b..8fa3c2b6e88d 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -517,7 +517,7 @@ int __init e1355fb_init(void) do_install_cmap(0, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info) < 0) return -EINVAL; - printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), + printk(KERN_INFO "fb%d: %s frame buffer device\n", minor(fb_info.gen.info.node), fb_info.gen.info.modename); return 0; diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index e10d65f53d69..3b70c0585b48 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -94,16 +94,7 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) int size = len*sizeof(u16); if (cmap->len != len) { - if (cmap->red) - kfree(cmap->red); - if (cmap->green) - kfree(cmap->green); - if (cmap->blue) - kfree(cmap->blue); - if (cmap->transp) - kfree(cmap->transp); - cmap->red = cmap->green = cmap->blue = cmap->transp = NULL; - cmap->len = 0; + fb_dealloc_cmap(cmap); if (!len) return 0; if (!(cmap->red = kmalloc(size, GFP_ATOMIC))) @@ -124,6 +115,29 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) return 0; } +/** + * fb_dealloc_cmap - deallocate a colormap + * @cmap: frame buffer colormap structure + * + * Deallocates a colormap that was previously allocated with + * fb_alloc_cmap(). + * + */ + +void fb_dealloc_cmap(struct fb_cmap *cmap) +{ + if (cmap->red) + kfree(cmap->red); + if (cmap->green) + kfree(cmap->green); + if (cmap->blue) + kfree(cmap->blue); + if (cmap->transp) + kfree(cmap->transp); + + cmap->red = cmap->green = cmap->blue = cmap->transp = NULL; + cmap->len = 0; +} /** * fb_copy_cmap - copy a colormap @@ -181,62 +195,6 @@ void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto) } } - -/** - * fb_get_cmap - get a colormap - * @cmap: frame buffer colormap - * @kspc: boolean, 0 copy local, 1 put_user() function - * @getcolreg: pointer to a function to get a color register - * @info: frame buffer info structure - * - * Get a colormap @cmap for a screen of device @info. - * - * Returns negative errno on error, or zero on success. - * - */ - -int fb_get_cmap(struct fb_cmap *cmap, int kspc, - int (*getcolreg)(u_int, u_int *, u_int *, u_int *, u_int *, - struct fb_info *), - struct fb_info *info) -{ - int i, start; - u16 *red, *green, *blue, *transp; - u_int hred, hgreen, hblue, htransp; - - red = cmap->red; - green = cmap->green; - blue = cmap->blue; - transp = cmap->transp; - start = cmap->start; - if (start < 0) - return -EINVAL; - for (i = 0; i < cmap->len; i++) { - if (getcolreg(start++, &hred, &hgreen, &hblue, &htransp, info)) - return 0; - if (kspc) { - *red = hred; - *green = hgreen; - *blue = hblue; - if (transp) - *transp = htransp; - } else { - put_user(hred, red); - put_user(hgreen, green); - put_user(hblue, blue); - if (transp) - put_user(htransp, transp); - } - red++; - green++; - blue++; - if (transp) - transp++; - } - return 0; -} - - /** * fb_set_cmap - set the colormap * @cmap: frame buffer colormap structure @@ -352,8 +310,8 @@ void fb_invert_cmaps(void) */ EXPORT_SYMBOL(fb_alloc_cmap); +EXPORT_SYMBOL(fb_dealloc_cmap); EXPORT_SYMBOL(fb_copy_cmap); -EXPORT_SYMBOL(fb_get_cmap); EXPORT_SYMBOL(fb_set_cmap); EXPORT_SYMBOL(fb_default_cmap); EXPORT_SYMBOL(fb_invert_cmaps); diff --git a/drivers/video/fbcon-accel.c b/drivers/video/fbcon-accel.c deleted file mode 100644 index 27119e32c5dc..000000000000 --- a/drivers/video/fbcon-accel.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * linux/drivers/video/fbcon-accel.c -- Framebuffer accel console wrapper - * - * Created 20 Feb 2001 by 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <video/fbcon.h> -#include "fbcon-accel.h" - -void fbcon_accel_setup(struct display *p) -{ - p->next_line = p->fb_info->fix.line_length; - p->next_plane = 0; -} - -void fbcon_accel_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - struct fb_info *info = p->fb_info; - struct fb_copyarea area; - - area.sx = sx * fontwidth(p); - area.sy = sy * fontheight(p); - area.dx = dx * fontwidth(p); - area.dy = dy * fontheight(p); - area.height = height * fontheight(p); - area.width = width * fontwidth(p); - - info->fbops->fb_copyarea(info, &area); -} - -void fbcon_accel_clear(struct vc_data *vc, struct display *p, int sy, int sx, - int height, int width) -{ - struct fb_info *info = p->fb_info; - struct fb_fillrect region; - - region.color = attr_bgcol_ec(p,vc); - region.dx = sx * fontwidth(p); - region.dy = sy * fontheight(p); - region.width = width * fontwidth(p); - region.height = height * fontheight(p); - region.rop = ROP_COPY; - - info->fbops->fb_fillrect(info, ®ion); -} - -void fbcon_accel_putc(struct vc_data *vc, struct display *p, int c, int yy, - int xx) -{ - struct fb_info *info = p->fb_info; - unsigned short charmask = p->charmask; - unsigned int width = ((fontwidth(p)+7)>>3); - struct fb_image image; - - image.fg_color = attr_fgcol(p, c); - image.bg_color = attr_bgcol(p, c); - image.dx = xx * fontwidth(p); - image.dy = yy * fontheight(p); - image.width = fontwidth(p); - image.height = fontheight(p); - image.depth = 1; - image.data = p->fontdata + (c & charmask)*fontheight(p)*width; - - info->fbops->fb_imageblit(info, &image); -} - -void fbcon_accel_putcs(struct vc_data *vc, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - struct fb_info *info = p->fb_info; - unsigned short charmask = p->charmask; - unsigned int width = ((fontwidth(p)+7)>>3); - struct fb_image image; - - image.fg_color = attr_fgcol(p, *s); - image.bg_color = attr_bgcol(p, *s); - image.dx = xx * fontwidth(p); - image.dy = yy * fontheight(p); - image.width = fontwidth(p); - image.height = fontheight(p); - image.depth = 1; - - while (count--) { - image.data = p->fontdata + - (scr_readw(s++) & charmask) * fontheight(p) * width; - info->fbops->fb_imageblit(info, &image); - image.dx += fontwidth(p); - } -} - -void fbcon_accel_revc(struct display *p, int xx, int yy) -{ - struct fb_info *info = p->fb_info; - struct fb_fillrect region; - - region.color = attr_fgcol_ec(p, p->conp); - region.dx = xx * fontwidth(p); - region.dy = yy * fontheight(p); - region.width = fontwidth(p); - region.height = fontheight(p); - region.rop = ROP_XOR; - - info->fbops->fb_fillrect(info, ®ion); -} - -void fbcon_accel_clear_margins(struct vc_data *vc, struct display *p, - int bottom_only) -{ - struct fb_info *info = p->fb_info; - unsigned int cw = fontwidth(p); - unsigned int ch = fontheight(p); - unsigned int rw = info->var.xres % cw; - unsigned int bh = info->var.yres % ch; - unsigned int rs = info->var.xres - rw; - unsigned int bs = info->var.yres - bh; - struct fb_fillrect region; - - region.color = attr_bgcol_ec(p,vc); - region.rop = ROP_COPY; - - if (rw && !bottom_only) { - region.dx = info->var.xoffset + rs; - region.dy = 0; - region.width = rw; - region.height = info->var.yres_virtual; - info->fbops->fb_fillrect(info, ®ion); - } - - if (bh) { - region.dx = info->var.xoffset; - region.dy = info->var.yoffset + bs; - region.width = rs; - region.height = bh; - info->fbops->fb_fillrect(info, ®ion); - } -} - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_accel = { - .setup = fbcon_accel_setup, - .bmove = fbcon_accel_bmove, - .clear = fbcon_accel_clear, - .putc = fbcon_accel_putc, - .putcs = fbcon_accel_putcs, - .revc = fbcon_accel_revc, - .clear_margins =fbcon_accel_clear_margins, - .fontwidthmask =FONTWIDTHRANGE(1, 16) -}; - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_accel); -EXPORT_SYMBOL(fbcon_accel_setup); -EXPORT_SYMBOL(fbcon_accel_bmove); -EXPORT_SYMBOL(fbcon_accel_clear); -EXPORT_SYMBOL(fbcon_accel_putc); -EXPORT_SYMBOL(fbcon_accel_putcs); -EXPORT_SYMBOL(fbcon_accel_revc); -EXPORT_SYMBOL(fbcon_accel_clear_margins); diff --git a/drivers/video/fbcon-accel.h b/drivers/video/fbcon-accel.h deleted file mode 100644 index 80944b6e04c1..000000000000 --- a/drivers/video/fbcon-accel.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * FBcon low-level driver that is a wrapper for the accel engine. - */ - -#ifndef _VIDEO_FBCON_ACCEL_H -#define _VIDEO_FBCON_ACCEL_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_ACCEL) || defined(CONFIG_FBCON_ACCEL_MODULE) -#define FBCON_HAS_ACCEL -#endif -#else -#if defined(CONFIG_FBCON_ACCEL) -#define FBCON_HAS_ACCEL -#endif -#endif - -extern struct display_switch fbcon_accel; -extern void fbcon_accel_setup(struct display *p); -extern void fbcon_accel_bmove(struct display *p, int sy, int sx, int dy, - int dx, int height, int width); -extern void fbcon_accel_clear(struct vc_data *vc, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_accel_putc(struct vc_data *vc, struct display *p, int c, - int yy, int xx); -extern void fbcon_accel_putcs(struct vc_data *vc, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_accel_revc(struct display *p, int xx, int yy); -extern void fbcon_accel_clear_margins(struct vc_data *vc, struct display *p, - int bottom_only); - -#endif /* _VIDEO_FBCON_ACCEL_H */ diff --git a/drivers/video/fbcon-afb.c b/drivers/video/fbcon-afb.c deleted file mode 100644 index 6afee164b609..000000000000 --- a/drivers/video/fbcon-afb.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * linux/drivers/video/afb.c -- Low level frame buffer operations for - * bitplanes à la Amiga - * - * Created 5 Apr 1997 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <video/fbcon.h> -#include <video/fbcon-afb.h> - - - /* - * Bitplanes à la Amiga - */ - -static u8 expand_table[1024] = { - /* bg = fg = 0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* bg = 0, fg = 1 */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - /* bg = 1, fg = 0 */ - 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, - 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, - 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, - 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, - 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8, - 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, - 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, - 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, - 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, - 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, - 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8, - 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, - 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, - 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, - 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, - 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, - 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, - 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, - 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, - 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, - 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, - 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, - 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, - 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, - 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, - 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, - 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, - 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, - 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, - 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, - 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - /* bg = fg = 1 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - -void fbcon_afb_setup(struct display *p) -{ - if (p->fb_info->fix.line_length) - p->next_line = p->fb_info->fix.line_length; - else - p->next_line = p->var.xres_virtual>>3; - p->next_plane = p->var.yres_virtual*p->next_line; -} - -void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - u8 *src, *dest, *src0, *dest0; - u_short i, j; - - 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; - i = p->var.bits_per_pixel; - do { - fb_memmove(dest, src, height*fontheight(p)*width); - src += p->next_plane; - dest += p->next_plane; - } while (--i); - } else if (dy <= sy) { - src0 = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx; - dest0 = p->fb_info->screen_base+dy*fontheight(p)*p->next_line+dx; - i = p->var.bits_per_pixel; - do { - src = src0; - dest = dest0; - j = height*fontheight(p); - do { - fb_memmove(dest, src, width); - src += p->next_line; - dest += p->next_line; - } while (--j); - src0 += p->next_plane; - dest0 += p->next_plane; - } while (--i); - } else { - src0 = p->fb_info->screen_base+(sy+height)*fontheight(p)*p->next_line+sx; - dest0 = p->fb_info->screen_base+(dy+height)*fontheight(p)*p->next_line+dx; - i = p->var.bits_per_pixel; - do { - src = src0; - dest = dest0; - j = height*fontheight(p); - do { - src -= p->next_line; - dest -= p->next_line; - fb_memmove(dest, src, width); - } while (--j); - src0 += p->next_plane; - dest0 += p->next_plane; - } while (--i); - } -} - -void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - u8 *dest, *dest0; - u_short i, j; - int bg; - - dest0 = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx; - - bg = attr_bgcol_ec(p,conp); - i = p->var.bits_per_pixel; - do { - dest = dest0; - j = height*fontheight(p); - do { - if (bg & 1) - fb_memset255(dest, width); - else - fb_memclear(dest, width); - dest += p->next_line; - } while (--j); - bg >>= 1; - dest0 += p->next_plane; - } while (--i); -} - -void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u8 *dest, *dest0, *cdat, *cdat0, *expand; - u_short i, j; - int fg, bg; - - dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx; - cdat0 = p->fontdata+(c&p->charmask)*fontheight(p); - fg = attr_fgcol(p,c); - bg = attr_bgcol(p,c); - - i = p->var.bits_per_pixel; - do { - dest = dest0; - cdat = cdat0; - expand = expand_table; - if (bg & 1) - expand += 512; - if (fg & 1) - expand += 256; - j = fontheight(p); - do { - *dest = expand[*cdat++]; - dest += p->next_line; - } while (--j); - bg >>= 1; - fg >>= 1; - dest0 += p->next_plane; - } while (--i); -} - - /* - * I've split the console character loop in two parts - * (cfr. fbcon_putcs_ilbm()) - */ - -void fbcon_afb_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *dest, *dest0, *dest1, *expand; - u8 *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40; - u_short i, j; - u16 c1, c2, c3, c4; - int fg0, bg0, fg, bg; - - dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx; - c1 = scr_readw(s); - fg0 = attr_fgcol(p, c1); - bg0 = attr_bgcol(p, c1); - - while (count--) - if (xx&3 || count < 3) { /* Slow version */ - c1 = scr_readw(s++) & p->charmask; - dest1 = dest0++; - xx++; - - cdat10 = p->fontdata+c1*fontheight(p); - fg = fg0; - bg = bg0; - - i = p->var.bits_per_pixel; - do { - dest = dest1; - cdat1 = cdat10; - expand = expand_table; - if (bg & 1) - expand += 512; - if (fg & 1) - expand += 256; - j = fontheight(p); - do { - *dest = expand[*cdat1++]; - dest += p->next_line; - } while (--j); - bg >>= 1; - fg >>= 1; - dest1 += p->next_plane; - } while (--i); - } else { /* Fast version */ - c1 = scr_readw(&s[0]) & p->charmask; - c2 = scr_readw(&s[1]) & p->charmask; - c3 = scr_readw(&s[2]) & p->charmask; - c4 = scr_readw(&s[3]) & p->charmask; - - dest1 = dest0; - cdat10 = p->fontdata+c1*fontheight(p); - cdat20 = p->fontdata+c2*fontheight(p); - cdat30 = p->fontdata+c3*fontheight(p); - cdat40 = p->fontdata+c4*fontheight(p); - fg = fg0; - bg = bg0; - - i = p->var.bits_per_pixel; - do { - dest = dest1; - cdat1 = cdat10; - cdat2 = cdat20; - cdat3 = cdat30; - cdat4 = cdat40; - expand = expand_table; - if (bg & 1) - expand += 512; - if (fg & 1) - expand += 256; - j = fontheight(p); - do { -#if defined(__BIG_ENDIAN) - *(u32 *)dest = expand[*cdat1++]<<24 | - expand[*cdat2++]<<16 | - expand[*cdat3++]<<8 | - expand[*cdat4++]; -#elif defined(__LITTLE_ENDIAN) - *(u32 *)dest = expand[*cdat1++] | - expand[*cdat2++]<<8 | - expand[*cdat3++]<<16 | - expand[*cdat4++]<<24; -#else -#error FIXME: No endianness?? -#endif - dest += p->next_line; - } while (--j); - bg >>= 1; - fg >>= 1; - dest1 += p->next_plane; - } while (--i); - s += 4; - dest0 += 4; - xx += 4; - count -= 3; - } -} - -void fbcon_afb_revc(struct display *p, int xx, int yy) -{ - u8 *dest, *dest0; - u_short i, j; - int mask; - - dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx; - mask = p->fgcol ^ p->bgcol; - - /* - * This should really obey the individual character's - * background and foreground colors instead of simply - * inverting. - */ - - i = p->var.bits_per_pixel; - do { - if (mask & 1) { - dest = dest0; - j = fontheight(p); - do { - *dest = ~*dest; - dest += p->next_line; - } while (--j); - } - mask >>= 1; - dest0 += p->next_plane; - } while (--i); -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_afb = { - setup: fbcon_afb_setup, - bmove: fbcon_afb_bmove, - clear: fbcon_afb_clear, - putc: fbcon_afb_putc, - putcs: fbcon_afb_putcs, - revc: fbcon_afb_revc, - fontwidthmask: FONTWIDTH(8) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_afb); -EXPORT_SYMBOL(fbcon_afb_setup); -EXPORT_SYMBOL(fbcon_afb_bmove); -EXPORT_SYMBOL(fbcon_afb_clear); -EXPORT_SYMBOL(fbcon_afb_putc); -EXPORT_SYMBOL(fbcon_afb_putcs); -EXPORT_SYMBOL(fbcon_afb_revc); diff --git a/drivers/video/fbcon-cfb16.c b/drivers/video/fbcon-cfb16.c deleted file mode 100644 index 254e559fb591..000000000000 --- a/drivers/video/fbcon-cfb16.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * linux/drivers/video/cfb16.c -- Low level frame buffer operations for 16 bpp - * truecolor packed pixels - * - * Created 5 Apr 1997 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> -#include <asm/io.h> - -#include <video/fbcon.h> -#include <video/fbcon-cfb16.h> - - - /* - * 16 bpp packed pixels - */ - -static u32 tab_cfb16[] = { -#if defined(__BIG_ENDIAN) - 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff -#elif defined(__LITTLE_ENDIAN) - 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff -#else -#error FIXME: No endianness?? -#endif -}; - -void fbcon_cfb16_setup(struct display *p) -{ - p->next_line = p->fb_info->fix.line_length ? p->fb_info->fix.line_length : p->var.xres_virtual<<1; - p->next_plane = 0; -} - -void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - int bytes = p->next_line, linesize = bytes * fontheight(p), rows; - u8 *src, *dst; - - if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes) { - fb_memmove(p->fb_info->screen_base + dy * linesize, - p->fb_info->screen_base + sy * linesize, - height * linesize); - return; - } - if (fontwidthlog(p)) { - sx <<= fontwidthlog(p)+1; - dx <<= fontwidthlog(p)+1; - width <<= fontwidthlog(p)+1; - } else { - sx *= fontwidth(p)*2; - dx *= fontwidth(p)*2; - width *= fontwidth(p)*2; - } - if (dy < sy || (dy == sy && dx < sx)) { - src = p->fb_info->screen_base + sy * linesize + sx; - dst = p->fb_info->screen_base + dy * linesize + dx; - for (rows = height * fontheight(p); rows--;) { - fb_memmove(dst, src, width); - src += bytes; - dst += bytes; - } - } else { - src = p->fb_info->screen_base + (sy+height) * linesize + sx - bytes; - dst = p->fb_info->screen_base + (dy+height) * linesize + dx - bytes; - for (rows = height * fontheight(p); rows--;) { - fb_memmove(dst, src, width); - src -= bytes; - dst -= bytes; - } - } -} - -static inline void rectfill(u8 *dest, int width, int height, u32 data, - int linesize) -{ - int i; - - data |= data<<16; - - while (height-- > 0) { - u32 *p = (u32 *)dest; - for (i = 0; i < width/4; i++) { - fb_writel(data, p++); - fb_writel(data, p++); - } - if (width & 2) - fb_writel(data, p++); - if (width & 1) - fb_writew(data, (u16*)p); - dest += linesize; - } -} - -void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - u8 *dest; - int bytes = p->next_line, lines = height * fontheight(p); - u32 bgx; - - dest = p->fb_info->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2; - - bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - width *= fontwidth(p)/4; - if (width * 8 == bytes) - rectfill(dest, lines * width * 4, 1, bgx, bytes); - else - rectfill(dest, width * 4, lines, bgx, bytes); -} - -void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u8 *dest, *cdat, bits; - int bytes = p->next_line, rows; - u32 eorx, fgx, bgx; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2; - - fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)]; - fgx |= (fgx << 16); - bgx |= (bgx << 16); - eorx = fgx ^ bgx; - - switch (fontwidth(p)) { - case 4: - case 8: - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - for (rows = fontheight(p); rows--; dest += bytes) { - bits = *cdat++; - fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest); - fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4); - if (fontwidth(p) == 8) { - fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8); - fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12); - } - } - break; - case 12: - case 16: - cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1); - for (rows = fontheight(p); rows--; dest += bytes) { - bits = *cdat++; - fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest); - fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4); - fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8); - fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12); - bits = *cdat++; - fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest+16); - fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+20); - if (fontwidth(p) == 16) { - fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+24); - fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+28); - } - } - break; - } -} - -void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *cdat, *dest, *dest0; - u16 c; - int rows, bytes = p->next_line; - u32 eorx, fgx, bgx; - - dest0 = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2; - c = scr_readw(s); - fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)]; - fgx |= (fgx << 16); - bgx |= (bgx << 16); - eorx = fgx ^ bgx; - - switch (fontwidth(p)) { - case 4: - case 8: - while (count--) { - c = scr_readw(s++) & p->charmask; - cdat = p->fontdata + c * fontheight(p); - for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) { - u8 bits = *cdat++; - fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest); - fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4); - if (fontwidth(p) == 8) { - fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8); - fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12); - } - } - dest0 += fontwidth(p)*2;; - } - break; - case 12: - case 16: - while (count--) { - c = scr_readw(s++) & p->charmask; - cdat = p->fontdata + (c * fontheight(p) << 1); - for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) { - u8 bits = *cdat++; - fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest); - fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4); - fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8); - fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12); - bits = *cdat++; - fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest+16); - fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+20); - if (fontwidth(p) == 16) { - fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+24); - fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+28); - } - } - dest0 += fontwidth(p)*2; - } - break; - } -} - -void fbcon_cfb16_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int bytes = p->next_line, rows; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2; - for (rows = fontheight(p); rows--; dest += bytes) { - switch (fontwidth(p)) { - case 16: - fb_writel(fb_readl(dest+24) ^ 0xffffffff, dest+24); - fb_writel(fb_readl(dest+28) ^ 0xffffffff, dest+28); - /* FALL THROUGH */ - case 12: - fb_writel(fb_readl(dest+16) ^ 0xffffffff, dest+16); - fb_writel(fb_readl(dest+20) ^ 0xffffffff, dest+20); - /* FALL THROUGH */ - case 8: - fb_writel(fb_readl(dest+8) ^ 0xffffffff, dest+8); - fb_writel(fb_readl(dest+12) ^ 0xffffffff, dest+12); - /* FALL THROUGH */ - case 4: - fb_writel(fb_readl(dest+0) ^ 0xffffffff, dest+0); - fb_writel(fb_readl(dest+4) ^ 0xffffffff, dest+4); - } - } -} - -void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - int bytes = p->next_line; - u32 bgx; - - unsigned int right_start = conp->vc_cols*fontwidth(p); - unsigned int bottom_start = conp->vc_rows*fontheight(p); - unsigned int right_width, bottom_width; - - bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - if (!bottom_only && (right_width = p->var.xres-right_start)) - rectfill(p->fb_info->screen_base+right_start*2, right_width, - p->var.yres_virtual, bgx, bytes); - if ((bottom_width = p->var.yres-bottom_start)) - rectfill(p->fb_info->screen_base+(p->var.yoffset+bottom_start)*bytes, - right_start, bottom_width, bgx, bytes); -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_cfb16 = { - setup: fbcon_cfb16_setup, - bmove: fbcon_cfb16_bmove, - clear: fbcon_cfb16_clear, - putc: fbcon_cfb16_putc, - putcs: fbcon_cfb16_putcs, - revc: fbcon_cfb16_revc, - clear_margins: fbcon_cfb16_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_cfb16); -EXPORT_SYMBOL(fbcon_cfb16_setup); -EXPORT_SYMBOL(fbcon_cfb16_bmove); -EXPORT_SYMBOL(fbcon_cfb16_clear); -EXPORT_SYMBOL(fbcon_cfb16_putc); -EXPORT_SYMBOL(fbcon_cfb16_putcs); -EXPORT_SYMBOL(fbcon_cfb16_revc); -EXPORT_SYMBOL(fbcon_cfb16_clear_margins); diff --git a/drivers/video/fbcon-cfb2.c b/drivers/video/fbcon-cfb2.c deleted file mode 100644 index e4896a6ce9e3..000000000000 --- a/drivers/video/fbcon-cfb2.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * linux/drivers/video/cfb2.c -- Low level frame buffer operations for 2 bpp - * packed pixels - * - * Created 26 Dec 1997 by Michael Schmitz - * Based on cfb4.c - * - * 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 <video/fbcon.h> -#include <video/fbcon-cfb2.h> - - - /* - * 2 bpp packed pixels - */ - - /* - * IFF the font is even pixel aligned (that is to say each - * character start is a byte start in the pixel pairs). That - * avoids us having to mask bytes and means we won't be here - * all week. On a MacII that matters _lots_ - */ - -static u_char nibbletab_cfb2[]={ -#if defined(__BIG_ENDIAN) - 0x00,0x03,0x0c,0x0f, - 0x30,0x33,0x3c,0x3f, - 0xc0,0xc3,0xcc,0xcf, - 0xf0,0xf3,0xfc,0xff -#elif defined(__LITTLE_ENDIAN) - 0x00,0xc0,0x30,0xf0, - 0x0c,0xcc,0x3c,0xfc, - 0x03,0xc3,0x33,0xf3, - 0x0f,0xcf,0x3f,0xff -#else -#error FIXME: No endianness?? -#endif -}; - - -void fbcon_cfb2_setup(struct display *p) -{ - p->next_line = p->fb_info->fix.line_length ? p->fb_info->fix.line_length : p->var.xres_virtual>>2; - p->next_plane = 0; -} - -void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - int bytes = p->next_line, linesize = bytes * fontheight(p), rows; - u8 *src,*dst; - - if (sx == 0 && dx == 0 && width * 2 == bytes) { - fb_memmove(p->fb_info->screen_base + dy * linesize, - p->fb_info->screen_base + sy * linesize, - height * linesize); - } - else { - if (dy < sy || (dy == sy && dx < sx)) { - src = p->fb_info->screen_base + sy * linesize + sx * 2; - dst = p->fb_info->screen_base + dy * linesize + dx * 2; - for (rows = height * fontheight(p) ; rows-- ;) { - fb_memmove(dst, src, width * 2); - src += bytes; - dst += bytes; - } - } - else { - src = p->fb_info->screen_base + (sy+height) * linesize + sx * 2 - bytes; - dst = p->fb_info->screen_base + (dy+height) * linesize + dx * 2 - bytes; - for (rows = height * fontheight(p) ; rows-- ;) { - fb_memmove(dst, src, width * 2); - src -= bytes; - dst -= bytes; - } - } - } -} - -void fbcon_cfb2_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - u8 *dest0,*dest; - int bytes=p->next_line,lines=height * fontheight(p), rows, i; - u32 bgx; - - dest = p->fb_info->screen_base + sy * fontheight(p) * bytes + sx * 2; - - bgx=attr_bgcol_ec(p,conp); - bgx |= (bgx << 2); /* expand the colour to 16 bits */ - bgx |= (bgx << 4); - bgx |= (bgx << 8); - - if (sx == 0 && width * 2 == bytes) { - for (i = 0 ; i < lines * width ; i++) { - fb_writew (bgx, dest); - dest+=2; - } - } else { - dest0=dest; - for (rows = lines; rows-- ; dest0 += bytes) { - dest=dest0; - for (i = 0 ; i < width ; i++) { - /* memset ?? */ - fb_writew (bgx, dest); - dest+=2; - } - } - } -} - -void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u8 *dest,*cdat; - int bytes=p->next_line,rows; - u32 eorx,fgx,bgx; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * 2; - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - - fgx=3;/*attr_fgcol(p,c);*/ - bgx=attr_bgcol(p,c); - fgx |= (fgx << 2); /* expand color to 8 bits */ - fgx |= (fgx << 4); - bgx |= (bgx << 2); - bgx |= (bgx << 4); - eorx = fgx ^ bgx; - - for (rows = fontheight(p) ; rows-- ; dest += bytes) { - fb_writeb((nibbletab_cfb2[*cdat >> 4] & eorx) ^ bgx, dest+0); - fb_writeb((nibbletab_cfb2[*cdat++ & 0xf] & eorx) ^ bgx, dest+1); - } -} - -void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, - int count, int yy, int xx) -{ - u8 *cdat, *dest, *dest0; - u16 c; - int rows,bytes=p->next_line; - u32 eorx, fgx, bgx; - - dest0 = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * 2; - c = scr_readw(s); - fgx = 3/*attr_fgcol(p, c)*/; - bgx = attr_bgcol(p, c); - fgx |= (fgx << 2); - fgx |= (fgx << 4); - bgx |= (bgx << 2); - bgx |= (bgx << 4); - eorx = fgx ^ bgx; - while (count--) { - c = scr_readw(s++) & p->charmask; - cdat = p->fontdata + c * fontheight(p); - - for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { - fb_writeb((nibbletab_cfb2[*cdat >> 4] & eorx) ^ bgx, dest+0); - fb_writeb((nibbletab_cfb2[*cdat++ & 0xf] & eorx) ^ bgx, dest+1); - } - dest0+=2; - } -} - -void fbcon_cfb2_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int bytes=p->next_line, rows; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * 2; - for (rows = fontheight(p) ; rows-- ; dest += bytes) { - fb_writew(fb_readw(dest) ^ 0xffff, dest); - } -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_cfb2 = { - setup: fbcon_cfb2_setup, - bmove: fbcon_cfb2_bmove, - clear: fbcon_cfb2_clear, - putc: fbcon_cfb2_putc, - putcs: fbcon_cfb2_putcs, - revc: fbcon_cfb2_revc, - fontwidthmask: FONTWIDTH(8) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_cfb2); -EXPORT_SYMBOL(fbcon_cfb2_setup); -EXPORT_SYMBOL(fbcon_cfb2_bmove); -EXPORT_SYMBOL(fbcon_cfb2_clear); -EXPORT_SYMBOL(fbcon_cfb2_putc); -EXPORT_SYMBOL(fbcon_cfb2_putcs); -EXPORT_SYMBOL(fbcon_cfb2_revc); diff --git a/drivers/video/fbcon-cfb24.c b/drivers/video/fbcon-cfb24.c deleted file mode 100644 index 878bac753eb5..000000000000 --- a/drivers/video/fbcon-cfb24.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * linux/drivers/video/cfb24.c -- Low level frame buffer operations for 24 bpp - * truecolor packed pixels - * - * Created 7 Mar 1998 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <video/fbcon.h> -#include <video/fbcon-cfb24.h> - - - /* - * 24 bpp packed pixels - */ - -void fbcon_cfb24_setup(struct display *p) -{ - struct fb_info *info = p->fb_info; - - p->next_line = info->fix.line_length ? info->fix.line_length : p->var.xres_virtual*3; - p->next_plane = 0; -} - -void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - int bytes = p->next_line, linesize = bytes * fontheight(p), rows; - u8 *src, *dst; - - if (sx == 0 && dx == 0 && width * fontwidth(p) * 3 == bytes) { - fb_memmove(p->fb_info->screen_base + dy * linesize, - p->fb_info->screen_base + sy * linesize, - height * linesize); - return; - } - if (fontwidthlog(p)) { - sx <<= fontwidthlog(p); - dx <<= fontwidthlog(p); - width <<= fontwidthlog(p); - } else { - sx *= fontwidth(p); - dx *= fontwidth(p); - width *= fontwidth(p); - } - sx *= 3; dx *= 3; width *= 3; - if (dy < sy || (dy == sy && dx < sx)) { - src = p->fb_info->screen_base + sy * linesize + sx; - dst = p->fb_info->screen_base + dy * linesize + dx; - for (rows = height * fontheight(p); rows--;) { - fb_memmove(dst, src, width); - src += bytes; - dst += bytes; - } - } else { - src = p->fb_info->screen_base + (sy+height) * linesize + sx - bytes; - dst = p->fb_info->screen_base + (dy+height) * linesize + dx - bytes; - for (rows = height * fontheight(p); rows--;) { - fb_memmove(dst, src, width); - src -= bytes; - dst -= bytes; - } - } -} - -#if defined(__BIG_ENDIAN) -#define convert4to3(in1, in2, in3, in4, out1, out2, out3) \ - do { \ - out1 = (in1<<8) | (in2>>16); \ - out2 = (in2<<16) | (in3>>8); \ - out3 = (in3<<24) | in4; \ - } while (0); -#elif defined(__LITTLE_ENDIAN) -#define convert4to3(in1, in2, in3, in4, out1, out2, out3) \ - do { \ - out1 = in1 | (in2<<24); \ - out2 = (in2>> 8) | (in3<<16); \ - out3 = (in3>>16) | (in4<< 8); \ - } while (0); -#else -#error FIXME: No endianness?? -#endif - -static inline void store4pixels(u32 d1, u32 d2, u32 d3, u32 d4, u32 *dest) -{ - u32 o1, o2, o3; - convert4to3(d1, d2, d3, d4, o1, o2, o3); - fb_writel (o1, dest++); - fb_writel (o2, dest++); - fb_writel (o3, dest); -} - -static inline void rectfill(u8 *dest, int width, int height, u32 data, - int linesize) -{ - u32 d1, d2, d3; - int i; - - convert4to3(data, data, data, data, d1, d2, d3); - while (height-- > 0) { - u32 *p = (u32 *)dest; - for (i = 0; i < width/4; i++) { - fb_writel(d1, p++); - fb_writel(d2, p++); - fb_writel(d3, p++); - } - dest += linesize; - } -} - -void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - u8 *dest; - int bytes = p->next_line, lines = height * fontheight(p); - u32 bgx; - - dest = p->fb_info->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 3; - - bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - width *= fontwidth(p)/4; - if (width * 12 == bytes) - rectfill(dest, lines * width * 4, 1, bgx, bytes); - else - rectfill(dest, width * 4, lines, bgx, bytes); -} - -void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u8 *dest, *cdat, bits; - int bytes = p->next_line, rows; - u32 eorx, fgx, bgx, d1, d2, d3, d4; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3; - if (fontwidth(p) <= 8) - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - else - cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1); - - fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)]; - eorx = fgx ^ bgx; - - for (rows = fontheight(p); rows--; dest += bytes) { - bits = *cdat++; - d1 = (-(bits >> 7) & eorx) ^ bgx; - d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; - d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; - d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; - store4pixels(d1, d2, d3, d4, (u32 *)dest); - if (fontwidth(p) < 8) - continue; - d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; - d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; - d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; - d4 = (-(bits & 1) & eorx) ^ bgx; - store4pixels(d1, d2, d3, d4, (u32 *)(dest+12)); - if (fontwidth(p) < 12) - continue; - bits = *cdat++; - d1 = (-(bits >> 7) & eorx) ^ bgx; - d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; - d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; - d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; - store4pixels(d1, d2, d3, d4, (u32 *)(dest+24)); - if (fontwidth(p) < 16) - continue; - d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; - d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; - d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; - d4 = (-(bits & 1) & eorx) ^ bgx; - store4pixels(d1, d2, d3, d4, (u32 *)(dest+36)); - } -} - -void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *cdat, *dest, *dest0, bits; - u16 c; - int rows, bytes = p->next_line; - u32 eorx, fgx, bgx, d1, d2, d3, d4; - - dest0 = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3; - c = scr_readw(s); - fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)]; - eorx = fgx ^ bgx; - while (count--) { - c = scr_readw(s++) & p->charmask; - if (fontwidth(p) <= 8) - cdat = p->fontdata + c * fontheight(p); - - else - cdat = p->fontdata + (c * fontheight(p) << 1); - for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) { - bits = *cdat++; - d1 = (-(bits >> 7) & eorx) ^ bgx; - d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; - d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; - d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; - store4pixels(d1, d2, d3, d4, (u32 *)dest); - if (fontwidth(p) < 8) - continue; - d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; - d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; - d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; - d4 = (-(bits & 1) & eorx) ^ bgx; - store4pixels(d1, d2, d3, d4, (u32 *)(dest+12)); - if (fontwidth(p) < 12) - continue; - bits = *cdat++; - d1 = (-(bits >> 7) & eorx) ^ bgx; - d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; - d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; - d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; - store4pixels(d1, d2, d3, d4, (u32 *)(dest+24)); - if (fontwidth(p) < 16) - continue; - d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; - d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; - d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; - d4 = (-(bits & 1) & eorx) ^ bgx; - store4pixels(d1, d2, d3, d4, (u32 *)(dest+36)); - } - dest0 += fontwidth(p)*3; - } -} - -void fbcon_cfb24_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int bytes = p->next_line, rows; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3; - for (rows = fontheight(p); rows--; dest += bytes) { - switch (fontwidth(p)) { - case 16: - fb_writel(fb_readl(dest+36) ^ 0xffffffff, dest+36); - fb_writel(fb_readl(dest+40) ^ 0xffffffff, dest+40); - fb_writel(fb_readl(dest+44) ^ 0xffffffff, dest+44); - /* FALL THROUGH */ - case 12: - fb_writel(fb_readl(dest+24) ^ 0xffffffff, dest+24); - fb_writel(fb_readl(dest+28) ^ 0xffffffff, dest+28); - fb_writel(fb_readl(dest+32) ^ 0xffffffff, dest+32); - /* FALL THROUGH */ - case 8: - fb_writel(fb_readl(dest+12) ^ 0xffffffff, dest+12); - fb_writel(fb_readl(dest+16) ^ 0xffffffff, dest+16); - fb_writel(fb_readl(dest+20) ^ 0xffffffff, dest+20); - /* FALL THROUGH */ - case 4: - fb_writel(fb_readl(dest+0) ^ 0xffffffff, dest+0); - fb_writel(fb_readl(dest+4) ^ 0xffffffff, dest+4); - fb_writel(fb_readl(dest+8) ^ 0xffffffff, dest+8); - } - } -} - -void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - int bytes = p->next_line; - u32 bgx; - - unsigned int right_start = conp->vc_cols*fontwidth(p); - unsigned int bottom_start = conp->vc_rows*fontheight(p); - unsigned int right_width, bottom_width; - - bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - if (!bottom_only && (right_width = p->var.xres-right_start)) - rectfill(p->fb_info->screen_base+right_start*3, right_width, - p->var.yres_virtual, bgx, bytes); - if ((bottom_width = p->var.yres-bottom_start)) - rectfill(p->fb_info->screen_base+(p->var.yoffset+bottom_start)*bytes, - right_start, bottom_width, bgx, bytes); -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_cfb24 = { - setup: fbcon_cfb24_setup, - bmove: fbcon_cfb24_bmove, - clear: fbcon_cfb24_clear, - putc: fbcon_cfb24_putc, - putcs: fbcon_cfb24_putcs, - revc: fbcon_cfb24_revc, - clear_margins: fbcon_cfb24_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_cfb24); -EXPORT_SYMBOL(fbcon_cfb24_setup); -EXPORT_SYMBOL(fbcon_cfb24_bmove); -EXPORT_SYMBOL(fbcon_cfb24_clear); -EXPORT_SYMBOL(fbcon_cfb24_putc); -EXPORT_SYMBOL(fbcon_cfb24_putcs); -EXPORT_SYMBOL(fbcon_cfb24_revc); -EXPORT_SYMBOL(fbcon_cfb24_clear_margins); diff --git a/drivers/video/fbcon-cfb32.c b/drivers/video/fbcon-cfb32.c deleted file mode 100644 index 76e703610960..000000000000 --- a/drivers/video/fbcon-cfb32.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * linux/drivers/video/cfb32.c -- Low level frame buffer operations for 32 bpp - * truecolor packed pixels - * - * Created 28 Dec 1997 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <video/fbcon.h> -#include <video/fbcon-cfb32.h> - - - /* - * 32 bpp packed pixels - */ - -void fbcon_cfb32_setup(struct display *p) -{ - p->next_line = p->fb_info->fix.line_length ? p->fb_info->fix.line_length : p->var.xres_virtual<<2; - p->next_plane = 0; -} - -void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - int bytes = p->next_line, linesize = bytes * fontheight(p), rows; - u8 *src, *dst; - - if (sx == 0 && dx == 0 && width * fontwidth(p) * 4 == bytes) { - fb_memmove(p->fb_info->screen_base + dy * linesize, - p->fb_info->screen_base + sy * linesize, - height * linesize); - return; - } - if (fontwidthlog(p)) { - sx <<= fontwidthlog(p)+2; - dx <<= fontwidthlog(p)+2; - width <<= fontwidthlog(p)+2; - } else { - sx *= fontwidth(p)*4; - dx *= fontwidth(p)*4; - width *= fontwidth(p)*4; - } - if (dy < sy || (dy == sy && dx < sx)) { - src = p->fb_info->screen_base + sy * linesize + sx; - dst = p->fb_info->screen_base + dy * linesize + dx; - for (rows = height * fontheight(p); rows--;) { - fb_memmove(dst, src, width); - src += bytes; - dst += bytes; - } - } else { - src = p->fb_info->screen_base + (sy+height) * linesize + sx - bytes; - dst = p->fb_info->screen_base + (dy+height) * linesize + dx - bytes; - for (rows = height * fontheight(p); rows--;) { - fb_memmove(dst, src, width); - src -= bytes; - dst -= bytes; - } - } -} - -static inline void rectfill(u8 *dest, int width, int height, u32 data, - int linesize) -{ - int i; - - while (height-- > 0) { - u32 *p = (u32 *)dest; - for (i = 0; i < width/4; i++) { - fb_writel(data, p++); - fb_writel(data, p++); - fb_writel(data, p++); - fb_writel(data, p++); - } - if (width & 2) { - fb_writel(data, p++); - fb_writel(data, p++); - } - if (width & 1) - fb_writel(data, p++); - dest += linesize; - } -} - -void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - u8 *dest; - int bytes = p->next_line, lines = height * fontheight(p); - u32 bgx; - - dest = p->fb_info->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 4; - - bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - width *= fontwidth(p)/4; - if (width * 16 == bytes) - rectfill(dest, lines * width * 4, 1, bgx, bytes); - else - rectfill(dest, width * 4, lines, bgx, bytes); -} - -void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u8 *dest, *cdat, bits; - int bytes = p->next_line, rows; - u32 eorx, fgx, bgx, *pt; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4; - if (fontwidth(p) <= 8) - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - else - cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1); - fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)]; - eorx = fgx ^ bgx; - - for (rows = fontheight(p); rows--; dest += bytes) { - bits = *cdat++; - pt = (u32 *) dest; - fb_writel((-(bits >> 7) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 6 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 5 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 4 & 1) & eorx) ^ bgx, pt++); - if (fontwidth(p) < 8) - continue; - fb_writel((-(bits >> 3 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 2 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 1 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits & 1) & eorx) ^ bgx, pt++); - if (fontwidth(p) < 12) - continue; - bits = *cdat++; - fb_writel((-(bits >> 7) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 6 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 5 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 4 & 1) & eorx) ^ bgx, pt++); - if (fontwidth(p) < 16) - continue; - fb_writel((-(bits >> 3 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 2 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 1 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits & 1) & eorx) ^ bgx, pt++); - } -} - -void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *cdat, *dest, *dest0, bits; - u16 c; - int rows, bytes = p->next_line; - u32 eorx, fgx, bgx, *pt; - - dest0 = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4; - c = scr_readw(s); - fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)]; - eorx = fgx ^ bgx; - while (count--) { - c = scr_readw(s++) & p->charmask; - if (fontwidth(p) <= 8) - cdat = p->fontdata + c * fontheight(p); - else - cdat = p->fontdata + (c * fontheight(p) << 1); - for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) { - bits = *cdat++; - pt = (u32 *) dest; - fb_writel((-(bits >> 7) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 6 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 5 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 4 & 1) & eorx) ^ bgx, pt++); - if (fontwidth(p) < 8) - continue; - fb_writel((-(bits >> 3 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 2 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 1 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits & 1) & eorx) ^ bgx, pt++); - if (fontwidth(p) < 12) - continue; - bits = *cdat++; - fb_writel((-(bits >> 7) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 6 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 5 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 4 & 1) & eorx) ^ bgx, pt++); - if (fontwidth(p) < 16) - continue; - fb_writel((-(bits >> 3 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 2 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits >> 1 & 1) & eorx) ^ bgx, pt++); - fb_writel((-(bits & 1) & eorx) ^ bgx, pt++); - } - dest0 += fontwidth(p)*4; - } -} - -void fbcon_cfb32_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int bytes = p->next_line, rows; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4; - for (rows = fontheight(p); rows--; dest += bytes) { - switch (fontwidth(p)) { - case 16: - fb_writel(fb_readl(dest+(4*12)) ^ 0xffffffff, dest+(4*12)); - fb_writel(fb_readl(dest+(4*13)) ^ 0xffffffff, dest+(4*13)); - fb_writel(fb_readl(dest+(4*14)) ^ 0xffffffff, dest+(4*14)); - fb_writel(fb_readl(dest+(4*15)) ^ 0xffffffff, dest+(4*15)); - /* FALL THROUGH */ - case 12: - fb_writel(fb_readl(dest+(4*8)) ^ 0xffffffff, dest+(4*8)); - fb_writel(fb_readl(dest+(4*9)) ^ 0xffffffff, dest+(4*9)); - fb_writel(fb_readl(dest+(4*10)) ^ 0xffffffff, dest+(4*10)); - fb_writel(fb_readl(dest+(4*11)) ^ 0xffffffff, dest+(4*11)); - /* FALL THROUGH */ - case 8: - fb_writel(fb_readl(dest+(4*4)) ^ 0xffffffff, dest+(4*4)); - fb_writel(fb_readl(dest+(4*5)) ^ 0xffffffff, dest+(4*5)); - fb_writel(fb_readl(dest+(4*6)) ^ 0xffffffff, dest+(4*6)); - fb_writel(fb_readl(dest+(4*7)) ^ 0xffffffff, dest+(4*7)); - /* FALL THROUGH */ - case 4: - fb_writel(fb_readl(dest+(4*0)) ^ 0xffffffff, dest+(4*0)); - fb_writel(fb_readl(dest+(4*1)) ^ 0xffffffff, dest+(4*1)); - fb_writel(fb_readl(dest+(4*2)) ^ 0xffffffff, dest+(4*2)); - fb_writel(fb_readl(dest+(4*3)) ^ 0xffffffff, dest+(4*3)); - /* FALL THROUGH */ - } - } -} - -void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - int bytes = p->next_line; - u32 bgx; - - unsigned int right_start = conp->vc_cols*fontwidth(p); - unsigned int bottom_start = conp->vc_rows*fontheight(p); - unsigned int right_width, bottom_width; - - bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - if (!bottom_only && (right_width = p->var.xres-right_start)) - rectfill(p->fb_info->screen_base+right_start*4, right_width, - p->var.yres_virtual, bgx, bytes); - if ((bottom_width = p->var.yres-bottom_start)) - rectfill(p->fb_info->screen_base+(p->var.yoffset+bottom_start)*bytes, - right_start, bottom_width, bgx, bytes); -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_cfb32 = { - setup: fbcon_cfb32_setup, - bmove: fbcon_cfb32_bmove, - clear: fbcon_cfb32_clear, - putc: fbcon_cfb32_putc, - putcs: fbcon_cfb32_putcs, - revc: fbcon_cfb32_revc, - clear_margins: fbcon_cfb32_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_cfb32); -EXPORT_SYMBOL(fbcon_cfb32_setup); -EXPORT_SYMBOL(fbcon_cfb32_bmove); -EXPORT_SYMBOL(fbcon_cfb32_clear); -EXPORT_SYMBOL(fbcon_cfb32_putc); -EXPORT_SYMBOL(fbcon_cfb32_putcs); -EXPORT_SYMBOL(fbcon_cfb32_revc); -EXPORT_SYMBOL(fbcon_cfb32_clear_margins); diff --git a/drivers/video/fbcon-cfb4.c b/drivers/video/fbcon-cfb4.c deleted file mode 100644 index 5af563a65965..000000000000 --- a/drivers/video/fbcon-cfb4.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * linux/drivers/video/cfb4.c -- Low level frame buffer operations for 4 bpp - * packed pixels - * - * Created 26 Dec 1997 by Michael Schmitz - * Based on the old macfb.c 4bpp code by Alan Cox - * - * 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 <video/fbcon.h> -#include <video/fbcon-cfb4.h> - - - /* - * 4 bpp packed pixels - */ - - /* - * IFF the font is even pixel aligned (that is to say each - * character start is a byte start in the pixel pairs). That - * avoids us having to mask bytes and means we won't be here - * all week. On a MacII that matters _lots_ - */ - -static u16 nibbletab_cfb4[] = { -#if defined(__BIG_ENDIAN) - 0x0000,0x000f,0x00f0,0x00ff, - 0x0f00,0x0f0f,0x0ff0,0x0fff, - 0xf000,0xf00f,0xf0f0,0xf0ff, - 0xff00,0xff0f,0xfff0,0xffff -#elif defined(__LITTLE_ENDIAN) - 0x0000,0xf000,0x0f00,0xff00, - 0x00f0,0xf0f0,0x0ff0,0xfff0, - 0x000f,0xf00f,0x0f0f,0xff0f, - 0x00ff,0xf0ff,0x0fff,0xffff -#else -#error FIXME: No endianness?? -#endif - -}; - -void fbcon_cfb4_setup(struct display *p) -{ - p->next_line = p->fb_info->fix.line_length ? p->fb_info->fix.line_length : p->var.xres_virtual>>1; - p->next_plane = 0; -} - -void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - int bytes = p->next_line, linesize = bytes * fontheight(p), rows; - u8 *src,*dst; - - if (sx == 0 && dx == 0 && width * 4 == bytes) { - fb_memmove(p->fb_info->screen_base + dy * linesize, - p->fb_info->screen_base + sy * linesize, - height * linesize); - } - else { - if (dy < sy || (dy == sy && dx < sx)) { - src = p->fb_info->screen_base + sy * linesize + sx * 4; - dst = p->fb_info->screen_base + dy * linesize + dx * 4; - for (rows = height * fontheight(p) ; rows-- ;) { - fb_memmove(dst, src, width * 4); - src += bytes; - dst += bytes; - } - } - else { - src = p->fb_info->screen_base + (sy+height) * linesize + sx * 4 - bytes; - dst = p->fb_info->screen_base + (dy+height) * linesize + dx * 4 - bytes; - for (rows = height * fontheight(p) ; rows-- ;) { - fb_memmove(dst, src, width * 4); - src -= bytes; - dst -= bytes; - } - } - } -} - -void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - u8 *dest0,*dest; - int bytes=p->next_line,lines=height * fontheight(p), rows, i; - u32 bgx; - -/* if(p->fb_info->screen_base!=0xFDD00020) - mac_boom(1);*/ - dest = p->fb_info->screen_base + sy * fontheight(p) * bytes + sx * 4; - - bgx=attr_bgcol_ec(p,conp); - bgx |= (bgx << 4); /* expand the colour to 32bits */ - bgx |= (bgx << 8); - bgx |= (bgx << 16); - - if (sx == 0 && width * 4 == bytes) { - for (i = 0 ; i < lines * width ; i++) { - fb_writel (bgx, dest); - dest+=4; - } - } else { - dest0=dest; - for (rows = lines; rows-- ; dest0 += bytes) { - dest=dest0; - for (i = 0 ; i < width ; i++) { - /* memset ?? */ - fb_writel (bgx, dest); - dest+=4; - } - } - } -} - -void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u8 *dest,*cdat; - int bytes=p->next_line,rows; - u32 eorx,fgx,bgx; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * 4; - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - - fgx=attr_fgcol(p,c); - bgx=attr_bgcol(p,c); - fgx |= (fgx << 4); - fgx |= (fgx << 8); - bgx |= (bgx << 4); - bgx |= (bgx << 8); - eorx = fgx ^ bgx; - - for (rows = fontheight(p) ; rows-- ; dest += bytes) { - fb_writew((nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx, dest+0); - fb_writew((nibbletab_cfb4[*cdat++ & 0xf] & eorx) ^ bgx, dest+2); - } -} - -void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *cdat, *dest, *dest0; - u16 c; - int rows,bytes=p->next_line; - u32 eorx, fgx, bgx; - - dest0 = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * 4; - c = scr_readw(s); - fgx = attr_fgcol(p, c); - bgx = attr_bgcol(p, c); - fgx |= (fgx << 4); - fgx |= (fgx << 8); - fgx |= (fgx << 16); - bgx |= (bgx << 4); - bgx |= (bgx << 8); - bgx |= (bgx << 16); - eorx = fgx ^ bgx; - while (count--) { - c = scr_readw(s++) & p->charmask; - cdat = p->fontdata + c * fontheight(p); - - for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { - fb_writew((nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx, dest+0); - fb_writew((nibbletab_cfb4[*cdat++ & 0xf] & eorx) ^ bgx, dest+2); - } - dest0+=4; - } -} - -void fbcon_cfb4_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int bytes=p->next_line, rows; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * 4; - for (rows = fontheight(p) ; rows-- ; dest += bytes) { - fb_writel(fb_readl(dest+0) ^ 0xffffffff, dest+0); - } -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_cfb4 = { - setup: fbcon_cfb4_setup, - bmove: fbcon_cfb4_bmove, - clear: fbcon_cfb4_clear, - putc: fbcon_cfb4_putc, - putcs: fbcon_cfb4_putcs, - revc: fbcon_cfb4_revc, - fontwidthmask: FONTWIDTH(8) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_cfb4); -EXPORT_SYMBOL(fbcon_cfb4_setup); -EXPORT_SYMBOL(fbcon_cfb4_bmove); -EXPORT_SYMBOL(fbcon_cfb4_clear); -EXPORT_SYMBOL(fbcon_cfb4_putc); -EXPORT_SYMBOL(fbcon_cfb4_putcs); -EXPORT_SYMBOL(fbcon_cfb4_revc); diff --git a/drivers/video/fbcon-cfb8.c b/drivers/video/fbcon-cfb8.c deleted file mode 100644 index 1ac103832e2a..000000000000 --- a/drivers/video/fbcon-cfb8.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * linux/drivers/video/cfb8.c -- Low level frame buffer operations for 8 bpp - * packed pixels - * - * Created 5 Apr 1997 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <video/fbcon.h> -#include <video/fbcon-cfb8.h> - - - /* - * 8 bpp packed pixels - */ - -static u32 nibbletab_cfb8[] = { -#if defined(__BIG_ENDIAN) - 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, - 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, - 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, - 0xffff0000,0xffff00ff,0xffffff00,0xffffffff -#elif defined(__LITTLE_ENDIAN) - 0x00000000,0xff000000,0x00ff0000,0xffff0000, - 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, - 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, - 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff -#else -#error FIXME: No endianness?? -#endif -}; - -void fbcon_cfb8_setup(struct display *p) -{ - p->next_line = p->fb_info->fix.line_length ? p->fb_info->fix.line_length : p->var.xres_virtual; - p->next_plane = 0; -} - -void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - int bytes = p->next_line, linesize = bytes * fontheight(p), rows; - u8 *src,*dst; - - if (sx == 0 && dx == 0 && width * fontwidth(p) == bytes) { - fb_memmove(p->fb_info->screen_base + dy * linesize, - p->fb_info->screen_base + sy * linesize, - height * linesize); - return; - } - if (fontwidthlog(p)) { - sx <<= fontwidthlog(p); dx <<= fontwidthlog(p); width <<= fontwidthlog(p); - } else { - sx *= fontwidth(p); dx *= fontwidth(p); width *= fontwidth(p); - } - if (dy < sy || (dy == sy && dx < sx)) { - src = p->fb_info->screen_base + sy * linesize + sx; - dst = p->fb_info->screen_base + dy * linesize + dx; - for (rows = height * fontheight(p) ; rows-- ;) { - fb_memmove(dst, src, width); - src += bytes; - dst += bytes; - } - } else { - src = p->fb_info->screen_base + (sy+height) * linesize + sx - bytes; - dst = p->fb_info->screen_base + (dy+height) * linesize + dx - bytes; - for (rows = height * fontheight(p) ; rows-- ;) { - fb_memmove(dst, src, width); - src -= bytes; - dst -= bytes; - } - } -} - -static inline void rectfill(u8 *dest, int width, int height, u8 data, - int linesize) -{ - while (height-- > 0) { - fb_memset(dest, data, width); - dest += linesize; - } -} - -void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - u8 *dest; - int bytes=p->next_line,lines=height * fontheight(p); - u8 bgx; - - dest = p->fb_info->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p); - - bgx=attr_bgcol_ec(p,conp); - - width *= fontwidth(p); - if (width == bytes) - rectfill(dest, lines * width, 1, bgx, bytes); - else - rectfill(dest, width, lines, bgx, bytes); -} - -void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u8 *dest,*cdat; - int bytes=p->next_line,rows; - u32 eorx,fgx,bgx; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p); - if (fontwidth(p) <= 8) - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - else - cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1); - - fgx=attr_fgcol(p,c); - bgx=attr_bgcol(p,c); - fgx |= (fgx << 8); - fgx |= (fgx << 16); - bgx |= (bgx << 8); - bgx |= (bgx << 16); - eorx = fgx ^ bgx; - - switch (fontwidth(p)) { - case 4: - for (rows = fontheight(p) ; rows-- ; dest += bytes) - fb_writel((nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx, dest); - break; - case 8: - for (rows = fontheight(p) ; rows-- ; dest += bytes) { - fb_writel((nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx, dest); - fb_writel((nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx, dest+4); - } - break; - case 12: - case 16: - for (rows = fontheight(p) ; rows-- ; dest += bytes) { - fb_writel((nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx, dest); - fb_writel((nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx, dest+4); - fb_writel((nibbletab_cfb8[(*cdat >> 4) & 0xf] & eorx) ^ bgx, dest+8); - if (fontwidth(p) == 16) - fb_writel((nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx, dest+12); - cdat++; - } - break; - } -} - -void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *cdat, *dest, *dest0; - u16 c; - int rows,bytes=p->next_line; - u32 eorx, fgx, bgx; - - dest0 = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p); - c = scr_readw(s); - fgx = attr_fgcol(p, c); - bgx = attr_bgcol(p, c); - fgx |= (fgx << 8); - fgx |= (fgx << 16); - bgx |= (bgx << 8); - bgx |= (bgx << 16); - eorx = fgx ^ bgx; - switch (fontwidth(p)) { - case 4: - while (count--) { - c = scr_readw(s++) & p->charmask; - cdat = p->fontdata + c * fontheight(p); - - for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) - fb_writel((nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx, dest); - dest0+=4; - } - break; - case 8: - while (count--) { - c = scr_readw(s++) & p->charmask; - cdat = p->fontdata + c * fontheight(p); - - for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { - fb_writel((nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx, dest); - fb_writel((nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx, dest+4); - } - dest0+=8; - } - break; - case 12: - case 16: - while (count--) { - c = scr_readw(s++) & p->charmask; - cdat = p->fontdata + (c * fontheight(p) << 1); - - for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { - fb_writel((nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx, dest); - fb_writel((nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx, dest+4); - fb_writel((nibbletab_cfb8[(*cdat >> 4) & 0xf] & eorx) ^ bgx, dest+8); - if (fontwidth(p) == 16) - fb_writel((nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx, dest+12); - cdat++; - } - dest0+=fontwidth(p); - } - break; - } -} - -void fbcon_cfb8_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int bytes=p->next_line, rows; - - dest = p->fb_info->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p); - for (rows = fontheight(p) ; rows-- ; dest += bytes) { - switch (fontwidth(p)) { - case 16: fb_writel(fb_readl(dest+12) ^ 0x0f0f0f0f, dest+12); /* fall thru */ - case 12: fb_writel(fb_readl(dest+8) ^ 0x0f0f0f0f, dest+8); /* fall thru */ - case 8: fb_writel(fb_readl(dest+4) ^ 0x0f0f0f0f, dest+4); /* fall thru */ - case 4: fb_writel(fb_readl(dest) ^ 0x0f0f0f0f, dest); /* fall thru */ - default: break; - } - } -} - -void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - int bytes=p->next_line; - u8 bgx; - - unsigned int right_start = conp->vc_cols*fontwidth(p); - unsigned int bottom_start = conp->vc_rows*fontheight(p); - unsigned int right_width, bottom_width; - - bgx=attr_bgcol_ec(p,conp); - - if (!bottom_only && (right_width = p->var.xres-right_start)) - rectfill(p->fb_info->screen_base+right_start, right_width, p->var.yres_virtual, bgx, bytes); - if ((bottom_width = p->var.yres-bottom_start)) - rectfill(p->fb_info->screen_base+(p->var.yoffset+bottom_start)*bytes, - right_start, bottom_width, bgx, bytes); -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_cfb8 = { - setup: fbcon_cfb8_setup, - bmove: fbcon_cfb8_bmove, - clear: fbcon_cfb8_clear, - putc: fbcon_cfb8_putc, - putcs: fbcon_cfb8_putcs, - revc: fbcon_cfb8_revc, - clear_margins: fbcon_cfb8_clear_margins, - fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_cfb8); -EXPORT_SYMBOL(fbcon_cfb8_setup); -EXPORT_SYMBOL(fbcon_cfb8_bmove); -EXPORT_SYMBOL(fbcon_cfb8_clear); -EXPORT_SYMBOL(fbcon_cfb8_putc); -EXPORT_SYMBOL(fbcon_cfb8_putcs); -EXPORT_SYMBOL(fbcon_cfb8_revc); -EXPORT_SYMBOL(fbcon_cfb8_clear_margins); diff --git a/drivers/video/fbcon-hga.c b/drivers/video/fbcon-hga.c deleted file mode 100644 index 4cb12c6e47f5..000000000000 --- a/drivers/video/fbcon-hga.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * linux/drivers/video/fbcon-hga.c -- Low level frame buffer operations for - * the Hercules graphics adaptor - * - * Created 25 Nov 1999 by Ferenc Bakonyi (fero@drama.obuda.kando.hu) - * Based on fbcon-mfb.c by Geert Uytterhoeven - * - * History: - * - * - Revision 0.1.0 (6 Dec 1999): comment changes - * - First release (25 Nov 1999) - * - * 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 <video/fbcon.h> -#include <video/fbcon-hga.h> - -#if 0 -#define DPRINTK(args...) printk(KERN_DEBUG __FILE__": " ##args) -#else -#define DPRINTK(args...) -#endif - -#define HGA_ROWADDR(row) ((row%4)*8192 + (row>>2)*90) - - /* - * Hercules monochrome - */ - -static inline u8* rowaddr(struct display *p, u_int row) -{ - return p->fb_info->screen_base + HGA_ROWADDR(row); -} - -void fbcon_hga_setup(struct display *p) -{ - DPRINTK("fbcon_hga_setup: ll:%d\n", (int)p->line_length); - - p->next_line = p->fb_info->fix.line_length; - p->next_plane = 0; -} - -void fbcon_hga_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - u8 *src, *dest; - u_int rows, y1, y2; - -#if 0 - 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; - fb_memmove(dest, src, height*fontheight(p)*width); - } else -#endif - if (dy <= sy) { - y1 = sy*fontheight(p); - y2 = dy*fontheight(p); - for (rows = height*fontheight(p); rows--; ) { - src = rowaddr(p, y1)+sx; - dest = rowaddr(p, y2)+dx; - fb_memmove(dest, src, width); - y1++; - y2++; - } - } else { - y1 = (sy+height)*fontheight(p)-1; - y2 = (dy+height)*fontheight(p)-1; - for (rows = height*fontheight(p); rows--;) { - src = rowaddr(p, y1)+sx; - dest = rowaddr(p, y2)+dx; - fb_memmove(dest, src, width); - y1--; - y2--; - } - } -} - -void fbcon_hga_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - u8 *dest; - u_int rows, y; - int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0; - - DPRINTK("fbcon_hga_clear: sx:%d, sy:%d, height:%d, width:%d\n", sx, sy, height, width); - - y = sy*fontheight(p); -#if 0 - if (sx == 0 && width == p->next_line) { - if (inverse) { - fb_memset255(dest, height*fontheight(p)*width); - } else { - fb_memclear(dest, height*fontheight(p)*width); - } - } else -#endif - for (rows = height*fontheight(p); rows--; y++) { - dest = rowaddr(p, y)+sx; - if (inverse) { - fb_memset255(dest, width); - } else { - fb_memclear(dest, width); - } - } -} - -void fbcon_hga_putc(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u8 *dest, *cdat; - u_int rows, y, bold, revs, underl; - u8 d; - - cdat = p->fontdata+(c&p->charmask)*fontheight(p); - bold = attr_bold(p, c); - revs = attr_reverse(p, c); - underl = attr_underline(p, c); - y = yy*fontheight(p); - - for (rows = fontheight(p); rows--; y++) { - d = *cdat++; - if (underl && !rows) - d = 0xff; - else if (bold) - d |= d>>1; - if (revs) - d = ~d; - dest = rowaddr(p, y)+xx; - *dest = d; - } -} - -void fbcon_hga_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *dest, *cdat; - u_int rows, y, y0, bold, revs, underl; - u8 d; - u16 c; - - c = scr_readw(s); - bold = attr_bold(p, c); - revs = attr_reverse(p, c); - underl = attr_underline(p, c); - y0 = yy*fontheight(p); - - while (count--) { - c = scr_readw(s++) & p->charmask; - cdat = p->fontdata+c*fontheight(p); - y = y0; - for (rows = fontheight(p); rows--; y++) { - d = *cdat++; - if (underl && !rows) - d = 0xff; - else if (bold) - d |= d>>1; - if (revs) - d = ~d; - dest = rowaddr(p, y)+xx; - *dest = d; - } - xx++; - } -} - -void fbcon_hga_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - u_int rows, y; - - y = yy*fontheight(p); - for (rows = fontheight(p); rows--; y++) { - dest = rowaddr(p, y)+xx; - *dest = ~*dest; - } -} - -void fbcon_hga_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - u8 *dest; - u_int height, y; - int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0; - - DPRINTK("fbcon_hga_clear_margins: enter\n"); - - /* No need to handle right margin. */ - - y = conp->vc_rows * fontheight(p); - for (height = p->var.yres - y; height-- > 0; y++) { - DPRINTK("fbcon_hga_clear_margins: y:%d, height:%d\n", y, height); - dest = rowaddr(p, y); - if (inverse) { - fb_memset255(dest, p->next_line); - } else { - fb_memclear(dest, p->next_line); - } - } -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_hga = { - .setup = fbcon_hga_setup, - .bmove = fbcon_hga_bmove, - .clear = fbcon_hga_clear, - .putc = fbcon_hga_putc, - .putcs = fbcon_hga_putcs, - .revc = fbcon_hga_revc, - .clear_margins =fbcon_hga_clear_margins, - .fontwidthmask =FONTWIDTH(8) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{ -} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_hga); -EXPORT_SYMBOL(fbcon_hga_setup); -EXPORT_SYMBOL(fbcon_hga_bmove); -EXPORT_SYMBOL(fbcon_hga_clear); -EXPORT_SYMBOL(fbcon_hga_putc); -EXPORT_SYMBOL(fbcon_hga_putcs); -EXPORT_SYMBOL(fbcon_hga_revc); -EXPORT_SYMBOL(fbcon_hga_clear_margins); diff --git a/drivers/video/fbcon-ilbm.c b/drivers/video/fbcon-ilbm.c deleted file mode 100644 index 157736e809a7..000000000000 --- a/drivers/video/fbcon-ilbm.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * linux/drivers/video/ilbm.c -- Low level frame buffer operations for - * interleaved bitplanes à la Amiga - * - * Created 5 Apr 1997 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <video/fbcon.h> -#include <video/fbcon-ilbm.h> - - - /* - * Interleaved bitplanes à la Amiga - * - * This code heavily relies on the fact that - * - * next_line == interleave == next_plane*bits_per_pixel - * - * But maybe it can be merged with the code for normal bitplanes without - * much performance loss? - */ - -void fbcon_ilbm_setup(struct display *p) -{ - if (p->fb_info->fix.line_length) { - p->next_line = p->fb_info->fix.line_length*p->var.bits_per_pixel; - p->next_plane = p->fb_info->fix.line_length; - } else { - p->next_line = p->fb_info->fix.type_aux; - p->next_plane = p->fb_info->fix.type_aux/p->var.bits_per_pixel; - } -} - -void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - if (sx == 0 && dx == 0 && width == p->next_plane) - fb_memmove(p->fb_info->screen_base+dy*fontheight(p)*p->next_line, - p->fb_info->screen_base+sy*fontheight(p)*p->next_line, - height*fontheight(p)*p->next_line); - else { - u8 *src, *dest; - u_int i; - - 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 (i = p->var.bits_per_pixel*height*fontheight(p); i--;) { - fb_memmove(dest, src, width); - src += p->next_plane; - dest += p->next_plane; - } - } else { - src = p->fb_info->screen_base+(sy+height)*fontheight(p)*p->next_line+sx; - dest = p->fb_info->screen_base+(dy+height)*fontheight(p)*p->next_line+dx; - for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) { - src -= p->next_plane; - dest -= p->next_plane; - fb_memmove(dest, src, width); - } - } - } -} - -void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - u8 *dest; - u_int i, rows; - int bg, bg0; - - dest = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx; - - bg0 = attr_bgcol_ec(p,conp); - for (rows = height*fontheight(p); rows--;) { - bg = bg0; - for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { - if (bg & 1) - fb_memset255(dest, width); - else - fb_memclear(dest, width); - bg >>= 1; - } - } -} - -void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u8 *dest, *cdat; - u_int rows, i; - u8 d; - int fg0, bg0, fg, bg; - - dest = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx; - cdat = p->fontdata+(c&p->charmask)*fontheight(p); - fg0 = attr_fgcol(p,c); - bg0 = attr_bgcol(p,c); - - for (rows = fontheight(p); rows--;) { - d = *cdat++; - fg = fg0; - bg = bg0; - for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { - if (bg & 1){ - if (fg & 1) - *dest = 0xff; - else - *dest = ~d; - }else{ - if (fg & 1) - *dest = d; - else - *dest = 0x00; - } - bg >>= 1; - fg >>= 1; - } - } -} - - /* - * I've split the console character loop in two parts: - * - * - slow version: this blits one character at a time - * - * - fast version: this blits 4 characters at a time at a longword - * aligned address, to reduce the number of expensive - * Chip RAM accesses. - * - * Experiments on my A4000/040 revealed that this makes a console switch - * on a 640x400 screen with 256 colors about 3 times faster. - * - * -- Geert - */ - -void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4; - u_int rows, i; - u16 c1, c2, c3, c4; - u32 d; - int fg0, bg0, fg, bg; - - dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx; - c1 = scr_readw(s); - fg0 = attr_fgcol(p, c1); - bg0 = attr_bgcol(p, c1); - - while (count--) - if (xx&3 || count < 3) { /* Slow version */ - c1 = scr_readw(s++) & p->charmask; - dest = dest0++; - xx++; - - cdat1 = p->fontdata+c1*fontheight(p); - for (rows = fontheight(p); rows--;) { - d = *cdat1++; - fg = fg0; - bg = bg0; - for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { - if (bg & 1){ - if (fg & 1) - *dest = 0xff; - else - *dest = ~d; - }else{ - if (fg & 1) - *dest = d; - else - *dest = 0x00; - } - bg >>= 1; - fg >>= 1; - } - } - } else { /* Fast version */ - c1 = scr_readw(&s[0]) & p->charmask; - c2 = scr_readw(&s[1]) & p->charmask; - c3 = scr_readw(&s[2]) & p->charmask; - c4 = scr_readw(&s[3]) & p->charmask; - - dest = dest0; - cdat1 = p->fontdata+c1*fontheight(p); - cdat2 = p->fontdata+c2*fontheight(p); - cdat3 = p->fontdata+c3*fontheight(p); - cdat4 = p->fontdata+c4*fontheight(p); - for (rows = fontheight(p); rows--;) { -#if defined(__BIG_ENDIAN) - d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++; -#elif defined(__LITTLE_ENDIAN) - d = *cdat1++ | *cdat2++<<8 | *cdat3++<<16 | *cdat4++<<24; -#else -#error FIXME: No endianness?? -#endif - fg = fg0; - bg = bg0; - for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { - if (bg & 1){ - if (fg & 1) - *(u32 *)dest = 0xffffffff; - else - *(u32 *)dest = ~d; - }else{ - if (fg & 1) - *(u32 *)dest = d; - else - *(u32 *)dest = 0x00000000; - } - bg >>= 1; - fg >>= 1; - } - } - s += 4; - dest0 += 4; - xx += 4; - count -= 3; - } -} - -void fbcon_ilbm_revc(struct display *p, int xx, int yy) -{ - u8 *dest, *dest0; - u_int rows, i; - int mask; - - dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx; - mask = p->fgcol ^ p->bgcol; - - /* - * This should really obey the individual character's - * background and foreground colors instead of simply - * inverting. - */ - - for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) { - if (mask & 1) { - dest = dest0; - for (rows = fontheight(p); rows--; dest += p->next_line) - *dest = ~*dest; - } - mask >>= 1; - } -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_ilbm = { - setup: fbcon_ilbm_setup, - bmove: fbcon_ilbm_bmove, - clear: fbcon_ilbm_clear, - putc: fbcon_ilbm_putc, - putcs: fbcon_ilbm_putcs, - revc: fbcon_ilbm_revc, - fontwidthmask: FONTWIDTH(8) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_ilbm); -EXPORT_SYMBOL(fbcon_ilbm_setup); -EXPORT_SYMBOL(fbcon_ilbm_bmove); -EXPORT_SYMBOL(fbcon_ilbm_clear); -EXPORT_SYMBOL(fbcon_ilbm_putc); -EXPORT_SYMBOL(fbcon_ilbm_putcs); -EXPORT_SYMBOL(fbcon_ilbm_revc); diff --git a/drivers/video/fbcon-iplan2p2.c b/drivers/video/fbcon-iplan2p2.c deleted file mode 100644 index 9eea32a4efb9..000000000000 --- a/drivers/video/fbcon-iplan2p2.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * linux/drivers/video/fbcon-iplan2p2.c -- Low level frame buffer operations - * for interleaved bitplanes à la Atari (2 - * planes, 2 bytes interleave) - * - * Created 5 Apr 1997 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <asm/byteorder.h> - -#ifdef __mc68000__ -#include <asm/setup.h> -#endif - -#include <video/fbcon.h> -#include <video/fbcon-iplan2p2.h> - - - /* - * Interleaved bitplanes à la Atari (2 planes, 2 bytes interleave) - */ - -/* Increment/decrement 2 plane addresses */ - -#define INC_2P(p) do { if (!((long)(++(p)) & 1)) (p) += 2; } while(0) -#define DEC_2P(p) do { if ((long)(--(p)) & 1) (p) -= 2; } while(0) - - /* Convert a standard 4 bit color to our 2 bit color assignment: - * If at least two RGB channels are active, the low bit is turned on; - * The intensity bit (b3) is shifted into b1. - */ - -static const u8 color_2p[] = { 0, 0, 0, 1, 0, 1, 1, 1, 2, 2, 2, 3, 2, 3, 3, 3 }; -#define COLOR_2P(c) color_2p[c] - -/* Perform the m68k movepw operation. */ -static inline void movepw(u8 *d, u16 val) -{ -#if defined __mc68000__ && !defined CPU_M68060_ONLY - asm volatile ("movepw %1,%0@(0)" : : "a" (d), "d" (val)); -#else - d[0] = (val >> 16) & 0xff; - d[2] = val & 0xff; -#endif -} - -/* Sets the bytes in the visible column at d, height h, to the value - * val for a 2 plane screen. The bits of the color in 'color' are - * moved (8 times) to the respective bytes. This means: - * - * for(h times; d += bpr) - * *d = (color & 1) ? 0xff : 0; - * *(d+2) = (color & 2) ? 0xff : 0; - */ - -static __inline__ void memclear_2p_col(void *d, size_t h, u16 val, int bpr) -{ - u8 *dd = d; - do { - movepw(dd, val); - dd += bpr; - } while (--h); -} - -/* Sets a 2 plane region from 'd', length 'count' bytes, to the color - * in val1. 'd' has to be an even address and count must be divisible - * by 8, because only whole words and all planes are accessed. I.e.: - * - * for(count/4 times) - * *d = *(d+1) = (color & 1) ? 0xff : 0; - * *(d+2) = *(d+3) = (color & 2) ? 0xff : 0; - */ - -static __inline__ void memset_even_2p(void *d, size_t count, u32 val) -{ - u32 *dd = d; - - count /= 4; - while (count--) - *dd++ = val; -} - -/* Copies a 2 plane column from 's', height 'h', to 'd'. */ - -static __inline__ void memmove_2p_col (void *d, void *s, int h, int bpr) -{ - u8 *dd = d, *ss = s; - - while (h--) { - dd[0] = ss[0]; - dd[2] = ss[2]; - dd += bpr; - ss += bpr; - } -} - - -/* This expands a 2 bit color into a short for movepw (2 plane) operations. */ - -static const u16 two2byte[] = { - 0x0000, 0xff00, 0x00ff, 0xffff -}; - -static __inline__ u16 expand2w(u8 c) -{ - return two2byte[c]; -} - - -/* This expands a 2 bit color into one long for a movel operation - * (2 planes). - */ - -static const u32 two2word[] = { -#ifndef __LITTLE_ENDIAN - 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff -#else - 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff -#endif -}; - -static __inline__ u32 expand2l(u8 c) -{ - return two2word[c]; -} - - -/* This duplicates a byte 2 times into a short. */ - -static __inline__ u16 dup2w(u8 c) -{ - u16 rv; - - rv = c; - rv |= c << 8; - return rv; -} - - -void fbcon_iplan2p2_setup(struct display *p) -{ - p->next_line = p->var.xres_virtual>>2; - p->next_plane = 2; -} - -void fbcon_iplan2p2_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - /* bmove() has to distinguish two major cases: If both, source and - * destination, start at even addresses or both are at odd - * addresses, just the first odd and last even column (if present) - * require special treatment (memmove_col()). The rest between - * then can be copied by normal operations, because all adjacent - * bytes are affected and are to be stored in the same order. - * The pathological case is when the move should go from an odd - * address to an even or vice versa. Since the bytes in the plane - * words must be assembled in new order, it seems wisest to make - * all movements by memmove_col(). - */ - - if (sx == 0 && dx == 0 && width * 2 == p->next_line) { - /* Special (but often used) case: Moving whole lines can be - * done with memmove() - */ - fb_memmove(p->fb_info->screen_base + dy * p->next_line * fontheight(p), - p->fb_info->screen_base + sy * p->next_line * fontheight(p), - p->next_line * height * fontheight(p)); - } else { - int rows, cols; - u8 *src; - u8 *dst; - int bytes = p->next_line; - int linesize; - u_int colsize; - u_int upwards = (dy < sy) || (dy == sy && dx < sx); - - if (fontheightlog(p)) { - linesize = bytes << fontheightlog(p); - colsize = height << fontheightlog(p); - } else { - linesize = bytes * fontheight(p); - colsize = height * fontheight(p); - } - if ((sx & 1) == (dx & 1)) { - /* odd->odd or even->even */ - if (upwards) { - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1); - if (sx & 1) { - memmove_2p_col(dst, src, colsize, bytes); - src += 3; - dst += 3; - --width; - } - if (width > 1) { - for (rows = colsize; rows > 0; --rows) { - fb_memmove(dst, src, (width>>1)*4); - src += bytes; - dst += bytes; - } - } - if (width & 1) { - src -= colsize * bytes; - dst -= colsize * bytes; - memmove_2p_col(dst + (width>>1)*4, src + (width>>1)*4, - colsize, bytes); - } - } else { - if (!((sx+width-1) & 1)) { - src = p->fb_info->screen_base + sy * linesize + ((sx+width-1)>>1)*4; - dst = p->fb_info->screen_base + dy * linesize + ((dx+width-1)>>1)*4; - memmove_2p_col(dst, src, colsize, bytes); - --width; - } - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1); - if (width > 1) { - src += colsize * bytes + (sx & 1)*3; - dst += colsize * bytes + (sx & 1)*3; - for(rows = colsize; rows > 0; --rows) { - src -= bytes; - dst -= bytes; - fb_memmove(dst, src, (width>>1)*4); - } - } - if (width & 1) - memmove_2p_col(dst-3, src-3, colsize, bytes); - } - } else { - /* odd->even or even->odd */ - if (upwards) { - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1); - for (cols = width; cols > 0; --cols) { - memmove_2p_col(dst, src, colsize, bytes); - INC_2P(src); - INC_2P(dst); - } - } else { - sx += width-1; - dx += width-1; - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1); - for(cols = width; cols > 0; --cols) { - memmove_2p_col(dst, src, colsize, bytes); - DEC_2P(src); - DEC_2P(dst); - } - } - } - } -} - -void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) -{ - u32 offset; - u8 *start; - int rows; - int bytes = p->next_line; - int lines; - u32 size; - u32 cval; - u16 pcval; - - cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp))); - - if (fontheightlog(p)) - lines = height << fontheightlog(p); - else - lines = height * fontheight(p); - - if (sx == 0 && width * 2 == bytes) { - if (fontheightlog(p)) - offset = (sy * bytes) << fontheightlog(p); - else - offset = sy * bytes * fontheight(p); - size = lines * bytes; - memset_even_2p(p->fb_info->screen_base+offset, size, cval); - } else { - if (fontheightlog(p)) - offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*4 + (sx & 1); - else - offset = sy * bytes * fontheight(p) + (sx>>1)*4 + (sx & 1); - start = p->fb_info->screen_base + offset; - pcval = expand2w(COLOR_2P(attr_bgcol_ec(p,conp))); - - /* Clears are split if the region starts at an odd column or - * end at an even column. These extra columns are spread - * across the interleaved planes. All in between can be - * cleared by normal fb_memclear_small(), because both bytes of - * the single plane words are affected. - */ - - if (sx & 1) { - memclear_2p_col(start, lines, pcval, bytes); - start += 3; - width--; - } - if (width & 1) { - memclear_2p_col(start + (width>>1)*4, lines, pcval, bytes); - width--; - } - if (width) { - for (rows = lines; rows-- ; start += bytes) - memset_even_2p(start, width*2, cval); - } - } -} - -void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx) -{ - u8 *dest; - u8 *cdat; - int rows; - int bytes = p->next_line; - u16 eorx, fgx, bgx, fdx; - - if (fontheightlog(p)) { - dest = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) + - (xx>>1)*4 + (xx & 1)); - cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p)); - } else { - dest = (p->fb_info->screen_base + yy * bytes * fontheight(p) + - (xx>>1)*4 + (xx & 1)); - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - } - - fgx = expand2w(COLOR_2P(attr_fgcol(p,c))); - bgx = expand2w(COLOR_2P(attr_bgcol(p,c))); - eorx = fgx ^ bgx; - - for (rows = fontheight(p) ; rows-- ; dest += bytes) { - fdx = dup2w(*cdat++); - movepw(dest, (fdx & eorx) ^ bgx); - } -} - -void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *dest, *dest0; - u8 *cdat; - u16 c; - int rows; - int bytes; - u16 eorx, fgx, bgx, fdx; - - bytes = p->next_line; - if (fontheightlog(p)) - dest0 = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) + - (xx>>1)*4 + (xx & 1)); - else - dest0 = (p->fb_info->screen_base + yy * bytes * fontheight(p) + - (xx>>1)*4 + (xx & 1)); - c = scr_readw(s); - fgx = expand2w(COLOR_2P(attr_fgcol(p, c))); - bgx = expand2w(COLOR_2P(attr_bgcol(p, c))); - eorx = fgx ^ bgx; - - while (count--) { - c = scr_readw(s++) & p->charmask; - if (fontheightlog(p)) - cdat = p->fontdata + (c << fontheightlog(p)); - else - cdat = p->fontdata + c * fontheight(p); - - for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { - fdx = dup2w(*cdat++); - movepw(dest, (fdx & eorx) ^ bgx); - } - INC_2P(dest0); - } -} - -void fbcon_iplan2p2_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int j; - int bytes; - - if (fontheightlog(p)) - dest = (p->fb_info->screen_base + ((yy * p->next_line) << fontheightlog(p)) + (xx>>1)*4 + (xx & 1)); - else - dest = (p->fb_info->screen_base + yy * p->next_line * fontheight(p) + - (xx>>1)*4 + (xx & 1)); - j = fontheight(p); - bytes = p->next_line; - while (j--) { - /* This should really obey the individual character's - * background and foreground colors instead of simply - * inverting. - */ - dest[0] = ~dest[0]; - dest[2] = ~dest[2]; - dest += bytes; - } -} - -void fbcon_iplan2p2_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - u32 offset; - int bytes; - int lines; - u32 cval; - -/* No need to handle right margin, cannot occur with fontwidth == 8 */ - - bytes = p->next_line; - if (fontheightlog(p)) { - lines = p->var.yres - (conp->vc_rows << fontheightlog(p)); - offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p); - } else { - lines = p->var.yres - conp->vc_rows * fontheight(p); - offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p); - } - if (lines) { - cval = expand2l(COLOR_2P(attr_bgcol_ec(p,conp))); - memset_even_2p(p->fb_info->screen_base+offset, lines * bytes, cval); - } -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_iplan2p2 = { - setup: fbcon_iplan2p2_setup, - bmove: fbcon_iplan2p2_bmove, - clear: fbcon_iplan2p2_clear, - putc: fbcon_iplan2p2_putc, - putcs: fbcon_iplan2p2_putcs, - revc: fbcon_iplan2p2_revc, - clear_margins: fbcon_iplan2p2_clear_margins, - fontwidthmask: FONTWIDTH(8) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_iplan2p2); -EXPORT_SYMBOL(fbcon_iplan2p2_setup); -EXPORT_SYMBOL(fbcon_iplan2p2_bmove); -EXPORT_SYMBOL(fbcon_iplan2p2_clear); -EXPORT_SYMBOL(fbcon_iplan2p2_putc); -EXPORT_SYMBOL(fbcon_iplan2p2_putcs); -EXPORT_SYMBOL(fbcon_iplan2p2_revc); -EXPORT_SYMBOL(fbcon_iplan2p2_clear_margins); diff --git a/drivers/video/fbcon-iplan2p4.c b/drivers/video/fbcon-iplan2p4.c deleted file mode 100644 index fdbb6a4d2790..000000000000 --- a/drivers/video/fbcon-iplan2p4.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * linux/drivers/video/fbcon-iplan2p4.c -- Low level frame buffer operations - * for interleaved bitplanes à la Atari (4 - * planes, 2 bytes interleave) - * - * Created 5 Apr 1997 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <asm/byteorder.h> - -#ifdef __mc68000__ -#include <asm/setup.h> -#endif - -#include <video/fbcon.h> -#include <video/fbcon-iplan2p4.h> - - - /* - * Interleaved bitplanes à la Atari (4 planes, 2 bytes interleave) - */ - -/* Increment/decrement 4 plane addresses */ - -#define INC_4P(p) do { if (!((long)(++(p)) & 1)) (p) += 6; } while(0) -#define DEC_4P(p) do { if ((long)(--(p)) & 1) (p) -= 6; } while(0) - -/* Perform the m68k movepl operation. */ -static inline void movepl(u8 *d, u32 val) -{ -#if defined __mc68000__ && !defined CPU_M68060_ONLY - asm volatile ("movepl %1,%0@(0)" : : "a" (d), "d" (val)); -#else - d[0] = (val >> 24) & 0xff; - d[2] = (val >> 16) & 0xff; - d[4] = (val >> 8) & 0xff; - d[6] = val & 0xff; -#endif -} - -/* Sets the bytes in the visible column at d, height h, to the value - * val for a 4 plane screen. The bits of the color in 'color' are - * moved (8 times) to the respective bytes. This means: - * - * for(h times; d += bpr) - * *d = (color & 1) ? 0xff : 0; - * *(d+2) = (color & 2) ? 0xff : 0; - * *(d+4) = (color & 4) ? 0xff : 0; - * *(d+6) = (color & 8) ? 0xff : 0; - */ - -static __inline__ void memclear_4p_col(void *d, size_t h, u32 val, int bpr) -{ - u8 *dd = d; - do { - movepl(dd, val); - dd += bpr; - } while (--h); -} - -/* Sets a 4 plane region from 'd', length 'count' bytes, to the color - * in val1/val2. 'd' has to be an even address and count must be divisible - * by 8, because only whole words and all planes are accessed. I.e.: - * - * for(count/8 times) - * *d = *(d+1) = (color & 1) ? 0xff : 0; - * *(d+2) = *(d+3) = (color & 2) ? 0xff : 0; - * *(d+4) = *(d+5) = (color & 4) ? 0xff : 0; - * *(d+6) = *(d+7) = (color & 8) ? 0xff : 0; - */ - -static __inline__ void memset_even_4p(void *d, size_t count, u32 val1, - u32 val2) -{ - u32 *dd = d; - - count /= 8; - while (count--) { - *dd++ = val1; - *dd++ = val2; - } -} - -/* Copies a 4 plane column from 's', height 'h', to 'd'. */ - -static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr) -{ - u8 *dd = d, *ss = s; - - while (h--) { - dd[0] = ss[0]; - dd[2] = ss[2]; - dd[4] = ss[4]; - dd[6] = ss[6]; - dd += bpr; - ss += bpr; - } -} - - -/* This expands a 4 bit color into a long for movepl (4 plane) operations. */ - -static const u32 four2byte[] = { - 0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, - 0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00, - 0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff, - 0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff -}; - -static __inline__ u32 expand4l(u8 c) -{ - return four2byte[c]; -} - - -/* This expands a 4 bit color into two longs for two movel operations - * (4 planes). - */ - -static const u32 two2word[] = { -#ifndef __LITTLE_ENDIAN - 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff, -#else - 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff, -#endif -}; - -static __inline__ void expand4dl(u8 c, u32 *ret1, u32 *ret2) -{ - *ret1 = two2word[c & 3]; - *ret2 = two2word[c >> 2]; -} - - -/* This duplicates a byte 4 times into a long. */ - -static __inline__ u32 dup4l(u8 c) -{ - u32 rv; - - rv = c; - rv |= rv << 8; - rv |= rv << 16; - return rv; -} - - -void fbcon_iplan2p4_setup(struct display *p) -{ - p->next_line = p->var.xres_virtual>>1; - p->next_plane = 2; -} - -void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - /* bmove() has to distinguish two major cases: If both, source and - * destination, start at even addresses or both are at odd - * addresses, just the first odd and last even column (if present) - * require special treatment (memmove_col()). The rest between - * then can be copied by normal operations, because all adjacent - * bytes are affected and are to be stored in the same order. - * The pathological case is when the move should go from an odd - * address to an even or vice versa. Since the bytes in the plane - * words must be assembled in new order, it seems wisest to make - * all movements by memmove_col(). - */ - - if (sx == 0 && dx == 0 && width * 4 == p->next_line) { - /* Special (but often used) case: Moving whole lines can be - *done with memmove() - */ - fb_memmove(p->fb_info->screen_base + dy * p->next_line * fontheight(p), - p->fb_info->screen_base + sy * p->next_line * fontheight(p), - p->next_line * height * fontheight(p)); - } else { - int rows, cols; - u8 *src; - u8 *dst; - int bytes = p->next_line; - int linesize; - u_int colsize; - u_int upwards = (dy < sy) || (dy == sy && dx < sx); - - if (fontheightlog(p)) { - linesize = bytes << fontheightlog(p); - colsize = height << fontheightlog(p); - } else { - linesize = bytes * fontheight(p); - colsize = height * fontheight(p); - } - if ((sx & 1) == (dx & 1)) { - /* odd->odd or even->even */ - - if (upwards) { - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1); - if (sx & 1) { - memmove_4p_col(dst, src, colsize, bytes); - src += 7; - dst += 7; - --width; - } - if (width > 1) { - for(rows = colsize; rows > 0; --rows) { - fb_memmove(dst, src, (width>>1)*8); - src += bytes; - dst += bytes; - } - } - if (width & 1) { - src -= colsize * bytes; - dst -= colsize * bytes; - memmove_4p_col(dst + (width>>1)*8, src + (width>>1)*8, - colsize, bytes); - } - } else { - if (!((sx+width-1) & 1)) { - src = p->fb_info->screen_base + sy * linesize + ((sx+width-1)>>1)*8; - dst = p->fb_info->screen_base + dy * linesize + ((dx+width-1)>>1)*8; - memmove_4p_col(dst, src, colsize, bytes); - --width; - } - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1); - if (width > 1) { - src += colsize * bytes + (sx & 1)*7; - dst += colsize * bytes + (sx & 1)*7; - for(rows = colsize; rows > 0; --rows) { - src -= bytes; - dst -= bytes; - fb_memmove(dst, src, (width>>1)*8); - } - } - if (width & 1) { - memmove_4p_col(dst-7, src-7, colsize, bytes); - } - } - } else { - /* odd->even or even->odd */ - - if (upwards) { - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1); - for(cols = width; cols > 0; --cols) { - memmove_4p_col(dst, src, colsize, bytes); - INC_4P(src); - INC_4P(dst); - } - } else { - sx += width-1; - dx += width-1; - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1); - for(cols = width; cols > 0; --cols) { - memmove_4p_col(dst, src, colsize, bytes); - DEC_4P(src); - DEC_4P(dst); - } - } - } - } -} - -void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) -{ - u32 offset; - u8 *start; - int rows; - int bytes = p->next_line; - int lines; - u32 size; - u32 cval1, cval2, pcval; - - expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2); - - if (fontheightlog(p)) - lines = height << fontheightlog(p); - else - lines = height * fontheight(p); - - if (sx == 0 && width * 4 == bytes) { - if (fontheightlog(p)) - offset = (sy * bytes) << fontheightlog(p); - else - offset = sy * bytes * fontheight(p); - size = lines * bytes; - memset_even_4p(p->fb_info->screen_base+offset, size, cval1, cval2); - } else { - if (fontheightlog(p)) - offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*8 + (sx & 1); - else - offset = sy * bytes * fontheight(p) + (sx>>1)*8 + (sx & 1); - start = p->fb_info->screen_base + offset; - pcval = expand4l(attr_bgcol_ec(p,conp)); - - /* Clears are split if the region starts at an odd column or - * end at an even column. These extra columns are spread - * across the interleaved planes. All in between can be - * cleared by normal fb_memclear_small(), because both bytes of - * the single plane words are affected. - */ - - if (sx & 1) { - memclear_4p_col(start, lines, pcval, bytes); - start += 7; - width--; - } - if (width & 1) { - memclear_4p_col(start + (width>>1)*8, lines, pcval, bytes); - width--; - } - if (width) { - for(rows = lines; rows-- ; start += bytes) - memset_even_4p(start, width*4, cval1, cval2); - } - } -} - -void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx) -{ - u8 *dest; - u8 *cdat; - int rows; - int bytes = p->next_line; - u32 eorx, fgx, bgx, fdx; - - if (fontheightlog(p)) { - dest = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) + - (xx>>1)*8 + (xx & 1)); - cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p)); - } else { - dest = (p->fb_info->screen_base + yy * bytes * fontheight(p) + - (xx>>1)*8 + (xx & 1)); - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - } - - fgx = expand4l(attr_fgcol(p,c)); - bgx = expand4l(attr_bgcol(p,c)); - eorx = fgx ^ bgx; - - for(rows = fontheight(p) ; rows-- ; dest += bytes) { - fdx = dup4l(*cdat++); - movepl(dest, (fdx & eorx) ^ bgx); - } -} - -void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *dest, *dest0; - u8 *cdat; - u16 c; - int rows; - int bytes; - u32 eorx, fgx, bgx, fdx; - - bytes = p->next_line; - if (fontheightlog(p)) - dest0 = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) + - (xx>>1)*8 + (xx & 1)); - else - dest0 = (p->fb_info->screen_base + yy * bytes * fontheight(p) + - (xx>>1)*8 + (xx & 1)); - c = scr_readw(s); - fgx = expand4l(attr_fgcol(p, c)); - bgx = expand4l(attr_bgcol(p, c)); - eorx = fgx ^ bgx; - - while (count--) { - /* I think, unrolling the loops like in the 1 plane case isn't - * practicable here, because the body is much longer for 4 - * planes (mostly the dup4l()). I guess, unrolling this would - * need more than 256 bytes and so exceed the instruction - * cache :-( - */ - - c = scr_readw(s++) & p->charmask; - if (fontheightlog(p)) - cdat = p->fontdata + (c << fontheightlog(p)); - else - cdat = p->fontdata + c * fontheight(p); - - for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { - fdx = dup4l(*cdat++); - movepl(dest, (fdx & eorx) ^ bgx); - } - INC_4P(dest0); - } -} - -void fbcon_iplan2p4_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int j; - int bytes; - - if (fontheightlog(p)) - dest = (p->fb_info->screen_base + ((yy * p->next_line) << fontheightlog(p)) + - (xx>>1)*8 + (xx & 1)); - else - dest = (p->fb_info->screen_base + yy * p->next_line * fontheight(p) + - (xx>>1)*8 + (xx & 1)); - j = fontheight(p); - bytes = p->next_line; - - while (j--) { - /* This should really obey the individual character's - * background and foreground colors instead of simply - * inverting. - */ - dest[0] = ~dest[0]; - dest[2] = ~dest[2]; - dest[4] = ~dest[4]; - dest[6] = ~dest[6]; - dest += bytes; - } -} - -void fbcon_iplan2p4_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - u32 offset; - int bytes; - int lines; - u32 cval1, cval2; - -/* No need to handle right margin, cannot occur with fontwidth == 8 */ - - bytes = p->next_line; - if (fontheightlog(p)) { - lines = p->var.yres - (conp->vc_rows << fontheightlog(p)); - offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p); - } else { - lines = p->var.yres - conp->vc_rows * fontheight(p); - offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p); - } - if (lines) { - expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2); - memset_even_4p(p->fb_info->screen_base+offset, lines * bytes, cval1, cval2); - } -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_iplan2p4 = { - setup: fbcon_iplan2p4_setup, - bmove: fbcon_iplan2p4_bmove, - clear: fbcon_iplan2p4_clear, - putc: fbcon_iplan2p4_putc, - putcs: fbcon_iplan2p4_putcs, - revc: fbcon_iplan2p4_revc, - clear_margins: fbcon_iplan2p4_clear_margins, - fontwidthmask: FONTWIDTH(8) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_iplan2p4); -EXPORT_SYMBOL(fbcon_iplan2p4_setup); -EXPORT_SYMBOL(fbcon_iplan2p4_bmove); -EXPORT_SYMBOL(fbcon_iplan2p4_clear); -EXPORT_SYMBOL(fbcon_iplan2p4_putc); -EXPORT_SYMBOL(fbcon_iplan2p4_putcs); -EXPORT_SYMBOL(fbcon_iplan2p4_revc); -EXPORT_SYMBOL(fbcon_iplan2p4_clear_margins); diff --git a/drivers/video/fbcon-iplan2p8.c b/drivers/video/fbcon-iplan2p8.c deleted file mode 100644 index 416f28fd1e59..000000000000 --- a/drivers/video/fbcon-iplan2p8.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for - * interleaved bitplanes à la Atari (8 - * planes, 2 bytes interleave) - * - * Created 5 Apr 1997 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <asm/byteorder.h> - -#ifdef __mc68000__ -#include <asm/setup.h> -#endif - -#include <video/fbcon.h> -#include <video/fbcon-iplan2p8.h> - - - /* - * Interleaved bitplanes à la Atari (8 planes, 2 bytes interleave) - * - * In 8 plane mode, 256 colors would be possible, but only the first - * 16 are used by the console code (the upper 4 bits are - * background/unused). For that, the following functions mask off the - * higher 4 bits of each color. - */ - -/* Increment/decrement 8 plane addresses */ - -#define INC_8P(p) do { if (!((long)(++(p)) & 1)) (p) += 14; } while(0) -#define DEC_8P(p) do { if ((long)(--(p)) & 1) (p) -= 14; } while(0) - -/* Perform the m68k movepl operation extended to 64 bits. */ -static inline void movepl2(u8 *d, u32 val1, u32 val2) -{ -#if defined __mc68000__ && !defined CPU_M68060_ONLY - asm volatile ("movepl %1,%0@(0); movepl %2,%0@(8)" - : : "a" (d), "d" (val1), "d" (val2)); -#else - d[0] = (val1 >> 24) & 0xff; - d[2] = (val1 >> 16) & 0xff; - d[4] = (val1 >> 8) & 0xff; - d[6] = val1 & 0xff; - d[8] = (val2 >> 24) & 0xff; - d[10] = (val2 >> 16) & 0xff; - d[12] = (val2 >> 8) & 0xff; - d[14] = val2 & 0xff; -#endif -} - -/* Sets the bytes in the visible column at d, height h, to the value - * val1,val2 for a 8 plane screen. The bits of the color in 'color' are - * moved (8 times) to the respective bytes. This means: - * - * for(h times; d += bpr) - * *d = (color & 1) ? 0xff : 0; - * *(d+2) = (color & 2) ? 0xff : 0; - * *(d+4) = (color & 4) ? 0xff : 0; - * *(d+6) = (color & 8) ? 0xff : 0; - * *(d+8) = (color & 16) ? 0xff : 0; - * *(d+10) = (color & 32) ? 0xff : 0; - * *(d+12) = (color & 64) ? 0xff : 0; - * *(d+14) = (color & 128) ? 0xff : 0; - */ - -static __inline__ void memclear_8p_col(void *d, size_t h, u32 val1, - u32 val2, int bpr) -{ - u8 *dd = d; - do { - movepl2(dd, val1, val2); - dd += bpr; - } while (--h); -} - -/* Sets a 8 plane region from 'd', length 'count' bytes, to the color - * val1..val4. 'd' has to be an even address and count must be divisible - * by 16, because only whole words and all planes are accessed. I.e.: - * - * for(count/16 times) - * *d = *(d+1) = (color & 1) ? 0xff : 0; - * *(d+2) = *(d+3) = (color & 2) ? 0xff : 0; - * *(d+4) = *(d+5) = (color & 4) ? 0xff : 0; - * *(d+6) = *(d+7) = (color & 8) ? 0xff : 0; - * *(d+8) = *(d+9) = (color & 16) ? 0xff : 0; - * *(d+10) = *(d+11) = (color & 32) ? 0xff : 0; - * *(d+12) = *(d+13) = (color & 64) ? 0xff : 0; - * *(d+14) = *(d+15) = (color & 128) ? 0xff : 0; - */ - -static __inline__ void memset_even_8p(void *d, size_t count, u32 val1, - u32 val2, u32 val3, u32 val4) -{ - u32 *dd = d; - - count /= 16; - while (count--) { - *dd++ = val1; - *dd++ = val2; - *dd++ = val3; - *dd++ = val4; - } -} - -/* Copies a 8 plane column from 's', height 'h', to 'd'. */ - -static __inline__ void memmove_8p_col (void *d, void *s, int h, int bpr) -{ - u8 *dd = d, *ss = s; - - while (h--) { - dd[0] = ss[0]; - dd[2] = ss[2]; - dd[4] = ss[4]; - dd[6] = ss[6]; - dd[8] = ss[8]; - dd[10] = ss[10]; - dd[12] = ss[12]; - dd[14] = ss[14]; - dd += bpr; - ss += bpr; - } -} - - -/* This expands a 8 bit color into two longs for two movepl (8 plane) - * operations. - */ - -static const u32 four2long[] = -{ - 0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, - 0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00, - 0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff, - 0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff, -}; - -static __inline__ void expand8dl(u8 c, u32 *ret1, u32 *ret2) -{ - *ret1 = four2long[c & 15]; - *ret2 = four2long[c >> 4]; -} - - -/* This expands a 8 bit color into four longs for four movel operations - * (8 planes). - */ - -static const u32 two2word[] = -{ -#ifndef __LITTLE_ENDIAN - 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff -#else - 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff -#endif -}; - -static inline void expand8ql(u8 c, u32 *rv1, u32 *rv2, u32 *rv3, u32 *rv4) -{ - *rv1 = two2word[c & 4]; - *rv2 = two2word[(c >> 2) & 4]; - *rv3 = two2word[(c >> 4) & 4]; - *rv4 = two2word[c >> 6]; -} - - -/* This duplicates a byte 4 times into a long. */ - -static __inline__ u32 dup4l(u8 c) -{ - u32 rv; - - rv = c; - rv |= rv << 8; - rv |= rv << 16; - return rv; -} - - -void fbcon_iplan2p8_setup(struct display *p) -{ - p->next_line = p->var.xres_virtual; - p->next_plane = 2; -} - -void fbcon_iplan2p8_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - /* bmove() has to distinguish two major cases: If both, source and - * destination, start at even addresses or both are at odd - * addresses, just the first odd and last even column (if present) - * require special treatment (memmove_col()). The rest between - * then can be copied by normal operations, because all adjacent - * bytes are affected and are to be stored in the same order. - * The pathological case is when the move should go from an odd - * address to an even or vice versa. Since the bytes in the plane - * words must be assembled in new order, it seems wisest to make - * all movements by memmove_col(). - */ - - if (sx == 0 && dx == 0 && width * 8 == p->next_line) { - /* Special (but often used) case: Moving whole lines can be - * done with memmove() - */ - fast_memmove(p->fb_info->screen_base + dy * p->next_line * fontheight(p), - p->fb_info->screen_base + sy * p->next_line * fontheight(p), - p->next_line * height * fontheight(p)); - } else { - int rows, cols; - u8 *src; - u8 *dst; - int bytes = p->next_line; - int linesize; - u_int colsize; - u_int upwards = (dy < sy) || (dy == sy && dx < sx); - - if (fontheightlog(p)) { - linesize = bytes << fontheightlog(p); - colsize = height << fontheightlog(p); - } else { - linesize = bytes * fontheight(p); - colsize = height * fontheight(p); - } - if ((sx & 1) == (dx & 1)) { - /* odd->odd or even->even */ - - if (upwards) { - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1); - if (sx & 1) { - memmove_8p_col(dst, src, colsize, bytes); - src += 15; - dst += 15; - --width; - } - if (width > 1) { - for(rows = colsize; rows > 0; --rows) { - fast_memmove (dst, src, (width >> 1) * 16); - src += bytes; - dst += bytes; - } - } - - if (width & 1) { - src -= colsize * bytes; - dst -= colsize * bytes; - memmove_8p_col(dst + (width>>1)*16, src + (width>>1)*16, - colsize, bytes); - } - } else { - if (!((sx+width-1) & 1)) { - src = p->fb_info->screen_base + sy * linesize + ((sx+width-1)>>1)*16; - dst = p->fb_info->screen_base + dy * linesize + ((dx+width-1)>>1)*16; - memmove_8p_col(dst, src, colsize, bytes); - --width; - } - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1); - if (width > 1) { - src += colsize * bytes + (sx & 1)*15; - dst += colsize * bytes + (sx & 1)*15; - for(rows = colsize; rows > 0; --rows) { - src -= bytes; - dst -= bytes; - fast_memmove (dst, src, (width>>1)*16); - } - } - if (width & 1) - memmove_8p_col(dst-15, src-15, colsize, bytes); - } - } else { - /* odd->even or even->odd */ - - if (upwards) { - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1); - for(cols = width; cols > 0; --cols) { - memmove_8p_col(dst, src, colsize, bytes); - INC_8P(src); - INC_8P(dst); - } - } else { - sx += width-1; - dx += width-1; - src = p->fb_info->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1); - dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1); - for(cols = width; cols > 0; --cols) { - memmove_8p_col(dst, src, colsize, bytes); - DEC_8P(src); - DEC_8P(dst); - } - } - } - } -} - -void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) -{ - u32 offset; - u8 *start; - int rows; - int bytes = p->next_line; - int lines; - u32 size; - u32 cval1, cval2, cval3, cval4, pcval1, pcval2; - - expand8ql(attr_bgcol_ec(p,conp), &cval1, &cval2, &cval3, &cval4); - - if (fontheightlog(p)) - lines = height << fontheightlog(p); - else - lines = height * fontheight(p); - - if (sx == 0 && width * 8 == bytes) { - if (fontheightlog(p)) - offset = (sy * bytes) << fontheightlog(p); - else - offset = sy * bytes * fontheight(p); - size = lines * bytes; - memset_even_8p(p->fb_info->screen_base+offset, size, cval1, cval2, cval3, cval4); - } else { - if (fontheightlog(p)) - offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*16 + (sx & 1); - else - offset = sy * bytes * fontheight(p) + (sx>>1)*16 + (sx & 1); - start = p->fb_info->screen_base + offset; - expand8dl(attr_bgcol_ec(p,conp), &pcval1, &pcval2); - - /* Clears are split if the region starts at an odd column or - * end at an even column. These extra columns are spread - * across the interleaved planes. All in between can be - * cleared by normal fb_memclear_small(), because both bytes of - * the single plane words are affected. - */ - - if (sx & 1) { - memclear_8p_col(start, lines, pcval1, pcval2, bytes); - start += 7; - width--; - } - if (width & 1) { - memclear_8p_col(start + (width>>1)*16, lines, pcval1, - pcval2, bytes); - width--; - } - if (width) - for(rows = lines; rows-- ; start += bytes) - memset_even_8p(start, width*8, cval1, cval2, cval3, cval4); - } -} - -void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx) -{ - u8 *dest; - u8 *cdat; - int rows; - int bytes = p->next_line; - u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx; - - if (fontheightlog(p)) { - dest = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) + - (xx>>1)*16 + (xx & 1)); - cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p)); - } else { - dest = (p->fb_info->screen_base + yy * bytes * fontheight(p) + - (xx>>1)*16 + (xx & 1)); - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - } - - expand8dl(attr_fgcol(p,c), &fgx1, &fgx2); - expand8dl(attr_bgcol(p,c), &bgx1, &bgx2); - eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2; - - for(rows = fontheight(p) ; rows-- ; dest += bytes) { - fdx = dup4l(*cdat++); - movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2); - } -} - -void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) -{ - u8 *dest, *dest0; - u8 *cdat; - u16 c; - int rows; - int bytes; - u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx; - - bytes = p->next_line; - if (fontheightlog(p)) - dest0 = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) + - (xx>>1)*16 + (xx & 1)); - else - dest0 = (p->fb_info->screen_base + yy * bytes * fontheight(p) + - (xx>>1)*16 + (xx & 1)); - - c = scr_readw(s); - expand8dl(attr_fgcol(p, c), &fgx1, &fgx2); - expand8dl(attr_bgcol(p, c), &bgx1, &bgx2); - eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2; - - while (count--) { - - /* I think, unrolling the loops like in the 1 plane case isn't - * practicable here, because the body is much longer for 4 - * planes (mostly the dup4l()). I guess, unrolling this would - * need more than 256 bytes and so exceed the instruction - * cache :-( - */ - - c = scr_readw(s++) & p->charmask; - if (fontheightlog(p)) - cdat = p->fontdata + (c << fontheightlog(p)); - else - cdat = p->fontdata + c * fontheight(p); - - for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { - fdx = dup4l(*cdat++); - movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2); - } - INC_8P(dest0); - } -} - -void fbcon_iplan2p8_revc(struct display *p, int xx, int yy) -{ - u8 *dest; - int j; - int bytes; - - if (fontheightlog(p)) - dest = (p->fb_info->screen_base + ((yy * p->next_line) << fontheightlog(p)) + - (xx>>1)*16 + (xx & 1)); - else - dest = (p->fb_info->screen_base + yy * p->next_line * fontheight(p) + - (xx>>1)*16 + (xx & 1)); - j = fontheight(p); - bytes = p->next_line; - - while (j--) { - /* This should really obey the individual character's - * background and foreground colors instead of simply - * inverting. For 8 plane mode, only the lower 4 bits of the - * color are inverted, because only these color registers have - * been set up. - */ - dest[0] = ~dest[0]; - dest[2] = ~dest[2]; - dest[4] = ~dest[4]; - dest[6] = ~dest[6]; - dest += bytes; - } -} - -void fbcon_iplan2p8_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - u32 offset; - int bytes; - int lines; - u32 cval1, cval2, cval3, cval4; - -/* No need to handle right margin, cannot occur with fontwidth == 8 */ - - bytes = p->next_line; - if (fontheightlog(p)) { - lines = p->var.yres - (conp->vc_rows << fontheightlog(p)); - offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p); - } else { - lines = p->var.yres - conp->vc_rows * fontheight(p); - offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p); - } - if (lines) { - expand8ql(attr_bgcol_ec(p,conp), &cval1, &cval2, &cval3, &cval4); - memset_even_8p(p->fb_info->screen_base+offset, lines * bytes, - cval1, cval2, cval3, cval4); - } -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_iplan2p8 = { - setup: fbcon_iplan2p8_setup, - bmove: fbcon_iplan2p8_bmove, - clear: fbcon_iplan2p8_clear, - putc: fbcon_iplan2p8_putc, - putcs: fbcon_iplan2p8_putcs, - revc: fbcon_iplan2p8_revc, - clear_margins: fbcon_iplan2p8_clear_margins, - fontwidthmask: FONTWIDTH(8) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_iplan2p8); -EXPORT_SYMBOL(fbcon_iplan2p8_setup); -EXPORT_SYMBOL(fbcon_iplan2p8_bmove); -EXPORT_SYMBOL(fbcon_iplan2p8_clear); -EXPORT_SYMBOL(fbcon_iplan2p8_putc); -EXPORT_SYMBOL(fbcon_iplan2p8_putcs); -EXPORT_SYMBOL(fbcon_iplan2p8_revc); -EXPORT_SYMBOL(fbcon_iplan2p8_clear_margins); diff --git a/drivers/video/fbcon-mfb.c b/drivers/video/fbcon-mfb.c deleted file mode 100644 index 21b7b3ddaba7..000000000000 --- a/drivers/video/fbcon-mfb.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * linux/drivers/video/mfb.c -- Low level frame buffer operations for - * monochrome - * - * Created 5 Apr 1997 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. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include <video/fbcon.h> -#include <video/fbcon-mfb.h> - - - /* - * Monochrome - */ - -void fbcon_mfb_setup(struct display *p) -{ - if (p->fb_info->fix.line_length) - p->next_line = p->fb_info->fix.line_length; - else - p->next_line = p->var.xres_virtual>>3; - p->next_plane = 0; -} - -void fbcon_mfb_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - 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; - fb_memmove(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--;) { - fb_memmove(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--;) { - fb_memmove(dest, src, width); - src -= p->next_line; - dest -= p->next_line; - } - } -} - -void fbcon_mfb_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) - fb_memset255(dest, height*fontheight(p)*width); - else - fb_memclear(dest, height*fontheight(p)*width); - } else - for (rows = height*fontheight(p); rows--; dest += p->next_line) - if (inverse) - fb_memset255(dest, width); - else - fb_memclear_small(dest, width); -} - -void fbcon_mfb_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; - fb_writeb (d, dest); - } -} - -void fbcon_mfb_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; - - dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx; - 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 (underl && !rows) - d = 0xff; - else if (bold) - d |= d>>1; - if (revs) - d = ~d; - fb_writeb (d, dest); - } - } -} - -void fbcon_mfb_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 = fb_readb(dest); - fb_writeb (~d, dest); - } -} - -void fbcon_mfb_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) - fb_memset255(dest, height * p->next_line); - else - fb_memclear(dest, height * p->next_line); -} - - - /* - * `switch' for the low level operations - */ - -struct display_switch fbcon_mfb = { - setup: fbcon_mfb_setup, - bmove: fbcon_mfb_bmove, - clear: fbcon_mfb_clear, - putc: fbcon_mfb_putc, - putcs: fbcon_mfb_putcs, - revc: fbcon_mfb_revc, - clear_margins: fbcon_mfb_clear_margins, - fontwidthmask: FONTWIDTH(8) -}; - - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_mfb); -EXPORT_SYMBOL(fbcon_mfb_setup); -EXPORT_SYMBOL(fbcon_mfb_bmove); -EXPORT_SYMBOL(fbcon_mfb_clear); -EXPORT_SYMBOL(fbcon_mfb_putc); -EXPORT_SYMBOL(fbcon_mfb_putcs); -EXPORT_SYMBOL(fbcon_mfb_revc); -EXPORT_SYMBOL(fbcon_mfb_clear_margins); diff --git a/drivers/video/fbcon-vga-planes.c b/drivers/video/fbcon-vga-planes.c deleted file mode 100644 index b350820fd3c1..000000000000 --- a/drivers/video/fbcon-vga-planes.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * linux/drivers/video/fbcon-vga-planes.c -- Low level frame buffer operations - * for VGA 4-plane modes - * - * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> - * Based on code by Michael Schmitz - * Based on the old macfb.c 4bpp code by Alan Cox - * - * 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/vt_buffer.h> - -#include <asm/io.h> - -#include <video/fbcon.h> -#include <video/fbcon-vga-planes.h> - -#define GRAPHICS_ADDR_REG 0x3ce /* Graphics address register. */ -#define GRAPHICS_DATA_REG 0x3cf /* Graphics data register. */ - -#define SET_RESET_INDEX 0 /* Set/Reset Register index. */ -#define ENABLE_SET_RESET_INDEX 1 /* Enable Set/Reset Register index. */ -#define DATA_ROTATE_INDEX 3 /* Data Rotate Register index. */ -#define GRAPHICS_MODE_INDEX 5 /* Graphics Mode Register index. */ -#define BIT_MASK_INDEX 8 /* Bit Mask Register index. */ - -/* The VGA's weird architecture often requires that we read a byte and - write a byte to the same location. It doesn't matter *what* byte - we write, however. This is because all the action goes on behind - the scenes in the VGA's 32-bit latch register, and reading and writing - video memory just invokes latch behavior. - - To avoid race conditions (is this necessary?), reading and writing - the memory byte should be done with a single instruction. One - suitable instruction is the x86 bitwise OR. The following - read-modify-write routine should optimize to one such bitwise - OR. */ -static inline void rmw(volatile char *p) -{ - readb(p); - writeb(1, p); -} - -/* Set the Graphics Mode Register. Bits 0-1 are write mode, bit 3 is - read mode. */ -static inline void setmode(int mode) -{ - outb(GRAPHICS_MODE_INDEX, GRAPHICS_ADDR_REG); - outb(mode, GRAPHICS_DATA_REG); -} - -/* Select the Bit Mask Register. */ -static inline void selectmask(void) -{ - outb(BIT_MASK_INDEX, GRAPHICS_ADDR_REG); -} - -/* Set the value of the Bit Mask Register. It must already have been - selected with selectmask(). */ -static inline void setmask(int mask) -{ - outb(mask, GRAPHICS_DATA_REG); -} - -/* Set the Data Rotate Register. Bits 0-2 are rotate count, bits 3-4 - are logical operation (0=NOP, 1=AND, 2=OR, 3=XOR). */ -static inline void setop(int op) -{ - outb(DATA_ROTATE_INDEX, GRAPHICS_ADDR_REG); - outb(op, GRAPHICS_DATA_REG); -} - -/* Set the Enable Set/Reset Register. The code here always uses value - 0xf for this register. */ -static inline void setsr(int sr) -{ - outb(ENABLE_SET_RESET_INDEX, GRAPHICS_ADDR_REG); - outb(sr, GRAPHICS_DATA_REG); -} - -/* Set the Set/Reset Register. */ -static inline void setcolor(int color) -{ - outb(SET_RESET_INDEX, GRAPHICS_ADDR_REG); - outb(color, GRAPHICS_DATA_REG); -} - -/* Set the value in the Graphics Address Register. */ -static inline void setindex(int index) -{ - outb(index, GRAPHICS_ADDR_REG); -} - -void fbcon_vga_planes_setup(struct display *p) -{ -} - -void fbcon_vga_planes_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - char *src; - char *dest; - int line_ofs; - int x; - - setmode(1); - setop(0); - setsr(0xf); - - sy *= fontheight(p); - dy *= fontheight(p); - height *= fontheight(p); - - if (dy < sy || (dy == sy && dx < sx)) { - line_ofs = p->fb_info->fix.line_length - width; - dest = p->fb_info->screen_base + dx + dy * p->fb_info->fix.line_length; - src = p->fb_info->screen_base + sx + sy * p->fb_info->fix.line_length; - while (height--) { - for (x = 0; x < width; x++) { - readb(src); - writeb(0, dest); - dest++; - src++; - } - src += line_ofs; - dest += line_ofs; - } - } else { - line_ofs = p->fb_info->fix.line_length - width; - dest = p->fb_info->screen_base + dx + width + (dy + height - 1) * p->fb_info->fix.line_length; - src = p->fb_info->screen_base + sx + width + (sy + height - 1) * p->fb_info->fix.line_length; - while (height--) { - for (x = 0; x < width; x++) { - dest--; - src--; - readb(src); - writeb(0, dest); - } - src -= line_ofs; - dest -= line_ofs; - } - } -} - -void fbcon_vga_planes_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - int line_ofs = p->fb_info->fix.line_length - width; - char *where; - int x; - - setmode(0); - setop(0); - setsr(0xf); - setcolor(attr_bgcol_ec(p, conp)); - selectmask(); - - setmask(0xff); - - sy *= fontheight(p); - height *= fontheight(p); - - where = p->fb_info->screen_base + sx + sy * p->fb_info->fix.line_length; - while (height--) { - for (x = 0; x < width; x++) { - writeb(0, where); - where++; - } - where += line_ofs; - } -} - -void fbcon_ega_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) -{ - int fg = attr_fgcol(p,c); - int bg = attr_bgcol(p,c); - - int y; - u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p); - char *where = p->fb_info->screen_base + xx + yy * p->fb_info->fix.line_length * fontheight(p); - - setmode(0); - setop(0); - setsr(0xf); - setcolor(bg); - selectmask(); - - setmask(0xff); - for (y = 0; y < fontheight(p); y++, where += p->fb_info->fix.line_length) - rmw(where); - - where -= p->fb_info->fix.line_length * y; - setcolor(fg); - selectmask(); - for (y = 0; y < fontheight(p); y++, where += p->fb_info->fix.line_length) - if (cdat[y]) { - setmask(cdat[y]); - rmw(where); - } -} - -void fbcon_vga_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) -{ - int fg = attr_fgcol(p,c); - int bg = attr_bgcol(p,c); - - int y; - u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p); - char *where = p->fb_info->screen_base + xx + yy * p->fb_info->fix.line_length * fontheight(p); - - setmode(2); - setop(0); - setsr(0xf); - setcolor(fg); - selectmask(); - - setmask(0xff); - writeb(bg, where); - rmb(); - readb(where); /* fill latches */ - setmode(3); - wmb(); - for (y = 0; y < fontheight(p); y++, where += p->fb_info->fix.line_length) - writeb(cdat[y], where); - wmb(); -} - -/* 28.50 in my test */ -void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, - int count, int yy, int xx) -{ - u16 c = scr_readw(s); - int fg = attr_fgcol(p, c); - int bg = attr_bgcol(p, c); - - char *where; - int n; - - setmode(2); - setop(0); - selectmask(); - - setmask(0xff); - where = p->fb_info->screen_base + xx + yy * p->fb_info->fix.line_length * fontheight(p); - writeb(bg, where); - rmb(); - readb(where); /* fill latches */ - wmb(); - selectmask(); - for (n = 0; n < count; n++) { - int c = scr_readw(s++) & p->charmask; - u8 *cdat = p->fontdata + c * fontheight(p); - u8 *end = cdat + fontheight(p); - - while (cdat < end) { - outb(*cdat++, GRAPHICS_DATA_REG); - wmb(); - writeb(fg, where); - where += p->fb_info->fix.line_length; - } - where += 1 - p->fb_info->fix.line_length * fontheight(p); - } - - wmb(); -} - -/* 6.96 in my test */ -void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, - int count, int yy, int xx) -{ - u16 c = scr_readw(s); - int fg = attr_fgcol(p, c); - int bg = attr_bgcol(p, c); - - char *where; - int n; - - setmode(2); - setop(0); - setsr(0xf); - setcolor(fg); - selectmask(); - - setmask(0xff); - where = p->fb_info->screen_base + xx + yy * p->fb_info->fix.line_length * fontheight(p); - writeb(bg, where); - rmb(); - readb(where); /* fill latches */ - setmode(3); - wmb(); - for (n = 0; n < count; n++) { - int y; - int c = scr_readw(s++) & p->charmask; - u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p); - - for (y = 0; y < fontheight(p); y++, cdat++) { - writeb (*cdat, where); - where += p->fb_info->fix.line_length; - } - where += 1 - p->fb_info->fix.line_length * fontheight(p); - } - - wmb(); -} - -void fbcon_vga_planes_revc(struct display *p, int xx, int yy) -{ - char *where = p->fb_info->screen_base + xx + yy * p->fb_info->fix.line_length * fontheight(p); - int y; - - setmode(0); - setop(0x18); - setsr(0xf); - setcolor(0xf); - selectmask(); - - setmask(0xff); - for (y = 0; y < fontheight(p); y++) { - rmw(where); - where += p->fb_info->fix.line_length; - } -} - -struct display_switch fbcon_vga_planes = { - setup: fbcon_vga_planes_setup, - bmove: fbcon_vga_planes_bmove, - clear: fbcon_vga_planes_clear, - putc: fbcon_vga_planes_putc, - putcs: fbcon_vga_planes_putcs, - revc: fbcon_vga_planes_revc, - fontwidthmask: FONTWIDTH(8) -}; - -struct display_switch fbcon_ega_planes = { - setup: fbcon_vga_planes_setup, - bmove: fbcon_vga_planes_bmove, - clear: fbcon_vga_planes_clear, - putc: fbcon_ega_planes_putc, - putcs: fbcon_ega_planes_putcs, - revc: fbcon_vga_planes_revc, - fontwidthmask: FONTWIDTH(8) -}; - -#ifdef MODULE -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{} -#endif /* MODULE */ - - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fbcon_vga_planes); -EXPORT_SYMBOL(fbcon_vga_planes_setup); -EXPORT_SYMBOL(fbcon_vga_planes_bmove); -EXPORT_SYMBOL(fbcon_vga_planes_clear); -EXPORT_SYMBOL(fbcon_vga_planes_putc); -EXPORT_SYMBOL(fbcon_vga_planes_putcs); -EXPORT_SYMBOL(fbcon_vga_planes_revc); - -EXPORT_SYMBOL(fbcon_ega_planes); -EXPORT_SYMBOL(fbcon_ega_planes_putc); -EXPORT_SYMBOL(fbcon_ega_planes_putcs); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ - diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c deleted file mode 100644 index 69374876d64f..000000000000 --- a/drivers/video/fbcon.c +++ /dev/null @@ -1,2508 +0,0 @@ -/* - * linux/drivers/video/fbcon.c -- Low level frame buffer based console driver - * - * Copyright (C) 1995 Geert Uytterhoeven - * - * - * This file is based on the original Amiga console driver (amicon.c): - * - * Copyright (C) 1993 Hamish Macdonald - * Greg Harp - * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] - * - * with work by William Rucklidge (wjr@cs.cornell.edu) - * Geert Uytterhoeven - * Jes Sorensen (jds@kom.auc.dk) - * Martin Apel - * - * and on the original Atari console driver (atacon.c): - * - * Copyright (C) 1993 Bjoern Brauel - * Roman Hodek - * - * with work by Guenther Kelleter - * Martin Schaller - * Andreas Schwab - * - * Hardware cursor support added by Emmanuel Marty (core@ggi-project.org) - * Smart redraw scrolling, arbitrary font width support, 512char font support - * and software scrollback added by - * Jakub Jelinek (jj@ultra.linux.cz) - * - * Random hacking by Martin Mares <mj@ucw.cz> - * - * 2001 - Documented with DocBook - * - Brad Douglas <brad@neruo.com> - * - * The low level operations for the various display memory organizations are - * now in separate source files. - * - * Currently the following organizations are supported: - * - * o afb Amiga bitplanes - * o cfb{2,4,8,16,24,32} Packed pixels - * o ilbm Amiga interleaved bitplanes - * o iplan2p[248] Atari interleaved bitplanes - * o mfb Monochrome - * o vga VGA characters/attributes - * - * To do: - * - * - Implement 16 plane mode (iplan2p16) - * - * - * 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. - */ - -#undef FBCONDEBUG - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/delay.h> /* MSch: for IRQ probe */ -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/kd.h> -#include <linux/slab.h> -#include <linux/fb.h> -#include <linux/vt_kern.h> -#include <linux/selection.h> -#include <linux/smp.h> -#include <linux/init.h> - -#include <asm/irq.h> -#include <asm/system.h> -#include <asm/uaccess.h> -#ifdef CONFIG_AMIGA -#include <asm/amigahw.h> -#include <asm/amigaints.h> -#endif /* CONFIG_AMIGA */ -#ifdef CONFIG_ATARI -#include <asm/atariints.h> -#endif -#ifdef CONFIG_MAC -#include <asm/macints.h> -#endif -#if defined(__mc68000__) || defined(CONFIG_APUS) -#include <asm/machdep.h> -#include <asm/setup.h> -#endif -#ifdef CONFIG_FBCON_VGA_PLANES -#include <asm/io.h> -#endif -#define INCLUDE_LINUX_LOGO_DATA -#include <asm/linux_logo.h> - -#include <video/fbcon.h> -#include <video/fbcon-mac.h> /* for 6x11 font on mac */ -#include <video/font.h> - -#ifdef FBCONDEBUG -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -#define LOGO_H 80 -#define LOGO_W 80 -#define LOGO_LINE (LOGO_W/8) - -struct display fb_display[MAX_NR_CONSOLES]; -char con2fb_map[MAX_NR_CONSOLES]; -static int logo_lines; -static int logo_shown = -1; -/* Software scrollback */ -int fbcon_softback_size = 32768; -static unsigned long softback_buf, softback_curr; -static unsigned long softback_in; -static unsigned long softback_top, softback_end; -static int softback_lines; - -#define REFCOUNT(fd) (((int *)(fd))[-1]) -#define FNTSIZE(fd) (((int *)(fd))[-2]) -#define FNTCHARCNT(fd) (((int *)(fd))[-3]) -#define FNTSUM(fd) (((int *)(fd))[-4]) -#define FONT_EXTRA_WORDS 4 - -#define CM_SOFTBACK (8) - -#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * conp->vc_size_row) - -static void fbcon_free_font(struct display *); -static int fbcon_set_origin(struct vc_data *); - -/* - * Emmanuel: fbcon will now use a hardware cursor if the - * low-level driver provides a non-NULL dispsw->cursor pointer, - * in which case the hardware should do blinking, etc. - * - * if dispsw->cursor is NULL, use Atari alike software cursor - */ - -static int cursor_drawn; - -#define CURSOR_DRAW_DELAY (1) - -/* # VBL ints between cursor state changes */ -#define ARM_CURSOR_BLINK_RATE (10) -#define AMIGA_CURSOR_BLINK_RATE (20) -#define ATARI_CURSOR_BLINK_RATE (42) -#define MAC_CURSOR_BLINK_RATE (32) -#define DEFAULT_CURSOR_BLINK_RATE (20) - -static int vbl_cursor_cnt; -static int cursor_on; -static int cursor_blink_rate; - -static inline void cursor_undrawn(void) -{ - vbl_cursor_cnt = 0; - cursor_drawn = 0; -} - - -#define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1) - - -/* - * Interface used by the world - */ - -static const char *fbcon_startup(void); -static void fbcon_init(struct vc_data *conp, int init); -static void fbcon_deinit(struct vc_data *conp); -static int fbcon_changevar(int con); -static void fbcon_clear(struct vc_data *conp, int sy, int sx, int height, - int width); -static void fbcon_putc(struct vc_data *conp, int c, int ypos, int xpos); -static void fbcon_putcs(struct vc_data *conp, const unsigned short *s, int count, - int ypos, int xpos); -static void fbcon_cursor(struct vc_data *conp, int mode); -static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, - int count); -static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, - int height, int width); -static int fbcon_switch(struct vc_data *conp); -static int fbcon_blank(struct vc_data *conp, int blank); -static int fbcon_font_op(struct vc_data *conp, struct console_font_op *op); -static int fbcon_set_palette(struct vc_data *conp, unsigned char *table); -static int fbcon_scrolldelta(struct vc_data *conp, int lines); - - -/* - * Internal routines - */ - -static void fbcon_setup(int con, int init, int logo); -static __inline__ int real_y(struct display *p, int ypos); -static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp); -static __inline__ void updatescrollmode(struct display *p); -static __inline__ void ywrap_up(int unit, struct vc_data *conp, - struct display *p, int count); -static __inline__ void ywrap_down(int unit, struct vc_data *conp, - struct display *p, int count); -static __inline__ void ypan_up(int unit, struct vc_data *conp, - struct display *p, int count); -static __inline__ void ypan_down(int unit, struct vc_data *conp, - struct display *p, int count); -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 - */ -static int vbl_detected; - -static void fbcon_vbl_detect(int irq, void *dummy, struct pt_regs *fp) -{ - vbl_detected++; -} -#endif - -static void cursor_timer_handler(unsigned long dev_addr); - -static struct timer_list cursor_timer = - TIMER_INITIALIZER(cursor_timer_handler, 0, 0); - -static void cursor_timer_handler(unsigned long dev_addr) -{ - fbcon_vbl_handler(0, NULL, NULL); - cursor_timer.expires = jiffies+HZ/50; - add_timer(&cursor_timer); -} - - -/** - * PROC_CONSOLE - find the attached tty or visible console - * @info: frame buffer info structure - * - * Finds the tty attached to the process or visible console if - * the process is not directly attached to a tty (e.g. remote - * user) for device @info. - * - * Returns -1 errno on error, or tty/visible console number - * on success. - * - */ - -int PROC_CONSOLE(const struct fb_info *info) -{ - int fgc; - - if (info->display_fg != NULL) - fgc = info->display_fg->vc_num; - else - return -1; - - if (!current->tty) - return fgc; - - if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE) - /* XXX Should report error here? */ - return fgc; - - if (minor(current->tty->device) < 1) - return fgc; - - return minor(current->tty->device) - 1; -} - - -/** - * set_all_vcs - set all virtual consoles to match - * @fbidx: frame buffer index (e.g. fb0, fb1, ...) - * @fb: frame buffer ops structure - * @var: frame buffer screen structure to set - * @info: frame buffer info structure - * - * Set all virtual consoles to match screen info set in @var - * for device @info. - * - * Returns negative errno on error, or zero on success. - * - */ - -int set_all_vcs(int fbidx, struct fb_ops *fb, struct fb_var_screeninfo *var, - struct fb_info *info) -{ - int unit, err; - - var->activate |= FB_ACTIVATE_TEST; - err = fb->fb_set_var(var, PROC_CONSOLE(info), info); - var->activate &= ~FB_ACTIVATE_TEST; - if (err) - return err; - for (unit = 0; unit < MAX_NR_CONSOLES; unit++) - if (fb_display[unit].conp && con2fb_map[unit] == fbidx) - fb->fb_set_var(var, unit, info); - return 0; -} - - -/** - * set_con2fb_map - map console to frame buffer device - * @unit: virtual console number to map - * @newidx: frame buffer index to map virtual console to - * - * Maps a virtual console @unit to a frame buffer device - * @newidx. - * - */ - -void set_con2fb_map(int unit, int newidx) -{ - int oldidx = con2fb_map[unit]; - struct fb_info *oldfb, *newfb; - struct vc_data *conp; - char *fontdata; - unsigned short fontwidth, fontheight, fontwidthlog, fontheightlog; - int userfont; - - if (newidx != con2fb_map[unit]) { - oldfb = registered_fb[oldidx]; - newfb = registered_fb[newidx]; - if (newfb->fbops->owner) - __MOD_INC_USE_COUNT(newfb->fbops->owner); - if (newfb->fbops->fb_open && newfb->fbops->fb_open(newfb,0)) { - if (newfb->fbops->owner) - __MOD_DEC_USE_COUNT(newfb->fbops->owner); - return; - } - if (oldfb->fbops->fb_release) - oldfb->fbops->fb_release(oldfb,0); - if (oldfb->fbops->owner) - __MOD_DEC_USE_COUNT(oldfb->fbops->owner); - conp = fb_display[unit].conp; - fontdata = fb_display[unit].fontdata; - fontwidth = fb_display[unit]._fontwidth; - fontheight = fb_display[unit]._fontheight; - fontwidthlog = fb_display[unit]._fontwidthlog; - fontheightlog = fb_display[unit]._fontheightlog; - userfont = fb_display[unit].userfont; - con2fb_map[unit] = newidx; - fb_display[unit] = *(newfb->disp); - fb_display[unit].conp = conp; - fb_display[unit].fontdata = fontdata; - fb_display[unit]._fontwidth = fontwidth; - fb_display[unit]._fontheight = fontheight; - fb_display[unit]._fontwidthlog = fontwidthlog; - fb_display[unit]._fontheightlog = fontheightlog; - fb_display[unit].userfont = userfont; - fb_display[unit].fb_info = newfb; - if (conp) - conp->vc_display_fg = &newfb->display_fg; - if (!newfb->display_fg) - newfb->display_fg = conp; - if (!newfb->changevar) - newfb->changevar = oldfb->changevar; - /* tell console var has changed */ - if (newfb->changevar) - newfb->changevar(unit); - } -} - -/* - * Low Level Operations - */ - -struct display_switch fbcon_dummy; - -/* NOTE: fbcon cannot be __init: it may be called from take_over_console later */ - -static const char *fbcon_startup(void) -{ - const char *display_desc = "frame buffer device"; - int irqres = 1; - static int done = 0; - - /* - * If num_registered_fb is zero, this is a call for the dummy part. - * The frame buffer devices weren't initialized yet. - */ - if (!num_registered_fb || done) - return display_desc; - done = 1; - -#ifdef CONFIG_AMIGA - if (MACH_IS_AMIGA) { - cursor_blink_rate = AMIGA_CURSOR_BLINK_RATE; - irqres = request_irq(IRQ_AMIGA_VERTB, fbcon_vbl_handler, 0, - "console/cursor", fbcon_vbl_handler); - } -#endif /* CONFIG_AMIGA */ -#ifdef CONFIG_ATARI - if (MACH_IS_ATARI) { - cursor_blink_rate = ATARI_CURSOR_BLINK_RATE; - irqres = request_irq(IRQ_AUTO_4, fbcon_vbl_handler, IRQ_TYPE_PRIO, - "console/cursor", fbcon_vbl_handler); - } -#endif /* CONFIG_ATARI */ - -#ifdef CONFIG_MAC - /* - * On a Macintoy, the VBL interrupt may or may not be active. - * As interrupt based cursor is more reliable and race free, we - * probe for VBL interrupts. - */ - if (MACH_IS_MAC) { - int ct = 0; - /* - * Probe for VBL: set temp. handler ... - */ - irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_detect, 0, - "console/cursor", fbcon_vbl_detect); - vbl_detected = 0; - - /* - * ... and spin for 20 ms ... - */ - while (!vbl_detected && ++ct<1000) - udelay(20); - - if(ct==1000) - printk("fbcon_startup: No VBL detected, using timer based cursor.\n"); - - free_irq(IRQ_MAC_VBL, fbcon_vbl_detect); - - if (vbl_detected) { - /* - * interrupt based cursor ok - */ - cursor_blink_rate = MAC_CURSOR_BLINK_RATE; - irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_handler, 0, - "console/cursor", fbcon_vbl_handler); - } else { - /* - * VBL not detected: fall through, use timer based cursor - */ - irqres = 1; - } - } -#endif /* CONFIG_MAC */ - -#if defined(__arm__) && defined(IRQ_VSYNCPULSE) - cursor_blink_rate = ARM_CURSOR_BLINK_RATE; - irqres = request_irq(IRQ_VSYNCPULSE, fbcon_vbl_handler, SA_SHIRQ, - "console/cursor", fbcon_vbl_handler); -#endif - - if (irqres) { - cursor_blink_rate = DEFAULT_CURSOR_BLINK_RATE; - cursor_timer.expires = jiffies+HZ/50; - add_timer(&cursor_timer); - } - - return display_desc; -} - - -static void fbcon_init(struct vc_data *conp, int init) -{ - int unit = conp->vc_num; - struct fb_info *info; - - /* on which frame buffer will we open this console? */ - info = registered_fb[(int)con2fb_map[unit]]; - - info->changevar = &fbcon_changevar; - fb_display[unit] = *(info->disp); /* copy from default */ - DPRINTK("mode: %s\n",info->modename); - DPRINTK("visual: %d\n",fb_display[unit].visual); - DPRINTK("res: %dx%d-%d\n",fb_display[unit].var.xres, - fb_display[unit].var.yres, - fb_display[unit].var.bits_per_pixel); - fb_display[unit].conp = conp; - fb_display[unit].fb_info = info; - /* clear out the cmap so we don't have dangling pointers */ - fb_display[unit].cmap.len = 0; - fb_display[unit].cmap.red = 0; - fb_display[unit].cmap.green = 0; - fb_display[unit].cmap.blue = 0; - fb_display[unit].cmap.transp = 0; - fbcon_setup(unit, init, !init); - /* Must be done after fbcon_setup to prevent excess updates */ - conp->vc_display_fg = &info->display_fg; - if (!info->display_fg) - info->display_fg = conp; -} - - -static void fbcon_deinit(struct vc_data *conp) -{ - int unit = conp->vc_num; - struct display *p = &fb_display[unit]; - - fbcon_free_font(p); - p->dispsw = &fbcon_dummy; - p->conp = 0; -} - - -static int fbcon_changevar(int con) -{ - if (fb_display[con].conp) - fbcon_setup(con, 0, 0); - return 0; -} - - -static __inline__ void updatescrollmode(struct display *p) -{ - struct fb_info *info = p->fb_info; - - int m; - if (p->scrollmode & __SCROLL_YFIXED) - return; - if (divides(info->fix.ywrapstep, fontheight(p)) && - divides(fontheight(p), info->var.yres_virtual)) - m = __SCROLL_YWRAP; - else if (divides(info->fix.ypanstep, fontheight(p)) && - p->var.yres_virtual >= p->var.yres+fontheight(p)) - m = __SCROLL_YPAN; - else if (p->scrollmode & __SCROLL_YNOMOVE) - m = __SCROLL_YREDRAW; - else - m = __SCROLL_YMOVE; - p->scrollmode = (p->scrollmode & ~__SCROLL_YMASK) | m; -} - -static void fbcon_font_widths(struct display *p) -{ - int i; - - p->_fontwidthlog = 0; - for (i = 2; i <= 6; i++) - if (fontwidth(p) == (1 << i)) - p->_fontwidthlog = i; - p->_fontheightlog = 0; - for (i = 2; i <= 6; i++) - if (fontheight(p) == (1 << i)) - p->_fontheightlog = i; -} - -#define fontwidthvalid(p,w) ((p)->dispsw->fontwidthmask & FONTWIDTH(w)) - -static void fbcon_setup(int con, int init, int logo) -{ - struct display *p = &fb_display[con]; - struct fb_info *info = p->fb_info; - struct vc_data *conp = p->conp; - int nr_rows, nr_cols; - int old_rows, old_cols; - unsigned short *save = NULL, *r, *q; - int i, charcnt = 256; - struct fbcon_font_desc *font; - - if (con != fg_console || (info->flags & FBINFO_FLAG_MODULE) || - info->fix.type == FB_TYPE_TEXT) - logo = 0; - - p->var.xoffset = p->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ - - if (con == fg_console && info->fix.type != FB_TYPE_TEXT) { - if (fbcon_softback_size) { - if (!softback_buf) { - softback_buf = (unsigned long)kmalloc(fbcon_softback_size, GFP_KERNEL); - if (!softback_buf) { - fbcon_softback_size = 0; - softback_top = 0; - } - } - } else { - if (softback_buf) { - kfree((void *)softback_buf); - softback_buf = 0; - softback_top = 0; - } - } - if (softback_buf) - softback_in = softback_top = softback_curr = softback_buf; - softback_lines = 0; - } - - for (i = 0; i < MAX_NR_CONSOLES; i++) - if (i != con && fb_display[i].fb_info == p->fb_info && - fb_display[i].conp && fb_display[i].fontdata) - break; - - fbcon_free_font(p); - if (i < MAX_NR_CONSOLES) { - struct display *q = &fb_display[i]; - - if (fontwidthvalid(p,fontwidth(q))) { - /* If we are not the first console on this - fb, copy the font from that console */ - p->_fontwidth = q->_fontwidth; - p->_fontheight = q->_fontheight; - p->_fontwidthlog = q->_fontwidthlog; - p->_fontheightlog = q->_fontheightlog; - p->fontdata = q->fontdata; - p->userfont = q->userfont; - if (p->userfont) { - REFCOUNT(p->fontdata)++; - charcnt = FNTCHARCNT(p->fontdata); - } - con_copy_unimap(con, i); - } - } - - if (!p->fontdata) { - if (!p->fb_info->fontname[0] || - !(font = fbcon_find_font(p->fb_info->fontname))) - font = fbcon_get_default_font(p->var.xres, p->var.yres); - p->_fontwidth = font->width; - p->_fontheight = font->height; - p->fontdata = font->data; - fbcon_font_widths(p); - } - - if (!fontwidthvalid(p,fontwidth(p))) { -#if defined(CONFIG_FBCON_MAC) && defined(CONFIG_MAC) - if (MACH_IS_MAC) - /* ++Geert: hack to make 6x11 fonts work on mac */ - p->dispsw = &fbcon_mac; - else -#endif - { - /* ++Geert: changed from panic() to `correct and continue' */ - printk(KERN_ERR "fbcon_setup: No support for fontwidth %d\n", fontwidth(p)); - p->dispsw = &fbcon_dummy; - } - } - if (p->dispsw->set_font) - p->dispsw->set_font(p, fontwidth(p), fontheight(p)); - updatescrollmode(p); - - old_cols = conp->vc_cols; - old_rows = conp->vc_rows; - - nr_cols = p->var.xres/fontwidth(p); - nr_rows = p->var.yres/fontheight(p); - - if (logo) { - /* Need to make room for the logo */ - int cnt; - int step; - - logo_lines = (LOGO_H + fontheight(p) - 1) / fontheight(p); - q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows); - step = logo_lines * old_cols; - for (r = q - logo_lines * old_cols; r < q; r++) - if (scr_readw(r) != conp->vc_video_erase_char) - break; - if (r != q && nr_rows >= old_rows + logo_lines) { - save = kmalloc(logo_lines * nr_cols * 2, GFP_KERNEL); - if (save) { - int i = old_cols < nr_cols ? old_cols : nr_cols; - scr_memsetw(save, conp->vc_video_erase_char, logo_lines * nr_cols * 2); - r = q - step; - for (cnt = 0; cnt < logo_lines; cnt++, r += i) - scr_memcpyw(save + cnt * nr_cols, r, 2 * i); - r = q; - } - } - if (r == q) { - /* We can scroll screen down */ - r = q - step - old_cols; - for (cnt = old_rows - logo_lines; cnt > 0; cnt--) { - scr_memcpyw(r + step, r, conp->vc_size_row); - r -= old_cols; - } - if (!save) { - conp->vc_y += logo_lines; - conp->vc_pos += logo_lines * conp->vc_size_row; - } - } - scr_memsetw((unsigned short *)conp->vc_origin, - conp->vc_video_erase_char, - conp->vc_size_row * logo_lines); - } - - /* - * ++guenther: console.c:vc_allocate() relies on initializing - * vc_{cols,rows}, but we must not set those if we are only - * resizing the console. - */ - if (init) { - conp->vc_cols = nr_cols; - conp->vc_rows = nr_rows; - } - p->vrows = p->var.yres_virtual/fontheight(p); - if ((p->var.yres % fontheight(p)) && - (p->var.yres_virtual % fontheight(p) < p->var.yres % fontheight(p))) - p->vrows--; - conp->vc_can_do_color = p->var.bits_per_pixel != 1; - conp->vc_complement_mask = conp->vc_can_do_color ? 0x7700 : 0x0800; - if (charcnt == 256) { - conp->vc_hi_font_mask = 0; - p->fgshift = 8; - p->bgshift = 12; - p->charmask = 0xff; - } else { - conp->vc_hi_font_mask = 0x100; - if (conp->vc_can_do_color) - conp->vc_complement_mask <<= 1; - p->fgshift = 9; - p->bgshift = 13; - p->charmask = 0x1ff; - } - - if (p->dispsw == &fbcon_dummy) - printk(KERN_WARNING "fbcon_setup: type %d (aux %d, depth %d) not " - "supported\n", info->fix.type, info->fix.type_aux, - p->var.bits_per_pixel); - p->dispsw->setup(p); - - p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1; - p->bgcol = 0; - - if (!init) { - if (conp->vc_cols != nr_cols || conp->vc_rows != nr_rows) - vc_resize_con(nr_rows, nr_cols, con); - else if (CON_IS_VISIBLE(conp) && - vt_cons[conp->vc_num]->vc_mode == KD_TEXT) { - if (p->dispsw->clear_margins) - p->dispsw->clear_margins(conp, p, 0); - update_screen(con); - } - if (save) { - q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows); - scr_memcpyw(q, save, logo_lines * nr_cols * 2); - conp->vc_y += logo_lines; - conp->vc_pos += logo_lines * conp->vc_size_row; - kfree(save); - } - } - - if (logo) { - logo_shown = -2; - conp->vc_top = logo_lines; - } - - if (con == fg_console && softback_buf) { - int l = fbcon_softback_size / conp->vc_size_row; - if (l > 5) - softback_end = softback_buf + l * conp->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 would screw - the operation totally */ - softback_top = 0; - } - } -} - - -/* ====================================================================== */ - -/* fbcon_XXX routines - interface used by the world - * - * This system is now divided into two levels because of complications - * caused by hardware scrolling. Top level functions: - * - * fbcon_bmove(), fbcon_clear(), fbcon_putc() - * - * handles y values in range [0, scr_height-1] that correspond to real - * screen positions. y_wrap shift means that first line of bitmap may be - * anywhere on this display. These functions convert lineoffsets to - * bitmap offsets and deal with the wrap-around case by splitting blits. - * - * fbcon_bmove_physical_8() -- These functions fast implementations - * fbcon_clear_physical_8() -- of original fbcon_XXX fns. - * fbcon_putc_physical_8() -- (fontwidth != 8) may be added later - * - * WARNING: - * - * At the moment fbcon_putc() cannot blit across vertical wrap boundary - * Implies should only really hardware scroll in rows. Only reason for - * restriction is simplicity & efficiency at the moment. - */ - -static __inline__ int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos-rows; -} - - -static void fbcon_clear(struct vc_data *conp, int sy, int sx, int height, - int width) -{ - int unit = conp->vc_num; - struct display *p = &fb_display[unit]; - u_int y_break; - int redraw_cursor = 0; - - if (!p->can_soft_blank && console_blanked) - return; - - if (!height || !width) - return; - - if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) && - (sx <= p->cursor_x) && (p->cursor_x < sx+width)) { - cursor_undrawn(); - redraw_cursor = 1; - } - - /* Split blits that cross physical y_wrap boundary */ - - y_break = p->vrows-p->yscroll; - if (sy < y_break && sy+height-1 >= y_break) { - u_int b = y_break-sy; - p->dispsw->clear(conp, p, real_y(p, sy), sx, b, width); - p->dispsw->clear(conp, p, real_y(p, sy+b), sx, height-b, width); - } else - p->dispsw->clear(conp, p, real_y(p, sy), sx, height, width); - - if (redraw_cursor) - vbl_cursor_cnt = CURSOR_DRAW_DELAY; -} - - -static void fbcon_putc(struct vc_data *conp, int c, int ypos, int xpos) -{ - int unit = conp->vc_num; - struct display *p = &fb_display[unit]; - int redraw_cursor = 0; - - if (!p->can_soft_blank && console_blanked) - return; - - if (vt_cons[unit]->vc_mode != KD_TEXT) - return; - - if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) { - cursor_undrawn(); - redraw_cursor = 1; - } - - p->dispsw->putc(conp, p, c, real_y(p, ypos), xpos); - - if (redraw_cursor) - vbl_cursor_cnt = CURSOR_DRAW_DELAY; -} - - -static void fbcon_putcs(struct vc_data *conp, const unsigned short *s, int count, - int ypos, int xpos) -{ - int unit = conp->vc_num; - struct display *p = &fb_display[unit]; - int redraw_cursor = 0; - - if (!p->can_soft_blank && console_blanked) - return; - - if (vt_cons[unit]->vc_mode != KD_TEXT) - return; - - if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) && - (p->cursor_x < (xpos + count))) { - cursor_undrawn(); - redraw_cursor = 1; - } - p->dispsw->putcs(conp, p, s, count, real_y(p, ypos), xpos); - if (redraw_cursor) - vbl_cursor_cnt = CURSOR_DRAW_DELAY; -} - - -static void fbcon_cursor(struct vc_data *conp, int mode) -{ - int unit = conp->vc_num; - struct display *p = &fb_display[unit]; - int y = conp->vc_y; - - if (mode & CM_SOFTBACK) { - mode &= ~CM_SOFTBACK; - if (softback_lines) { - if (y + softback_lines >= conp->vc_rows) - mode = CM_ERASE; - else - y += softback_lines; - } - } else if (softback_lines) - fbcon_set_origin(conp); - - /* do we have a hardware cursor ? */ - if (p->dispsw->cursor) { - p->cursor_x = conp->vc_x; - p->cursor_y = y; - p->dispsw->cursor(p, mode, p->cursor_x, real_y(p, p->cursor_y)); - return; - } - - /* Avoid flickering if there's no real change. */ - if (p->cursor_x == conp->vc_x && p->cursor_y == y && - (mode == CM_ERASE) == !cursor_on) - return; - - cursor_on = 0; - if (cursor_drawn) - p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); - - p->cursor_x = conp->vc_x; - p->cursor_y = y; - - switch (mode) { - case CM_ERASE: - cursor_drawn = 0; - break; - case CM_MOVE: - case CM_DRAW: - if (cursor_drawn) - p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); - vbl_cursor_cnt = CURSOR_DRAW_DELAY; - cursor_on = 1; - break; - } -} - - -static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp) -{ - struct display *p; - - if (!cursor_on) - return; - - if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) { - p = &fb_display[fg_console]; - if (p->dispsw->revc) - p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); - cursor_drawn ^= 1; - vbl_cursor_cnt = cursor_blink_rate; - } -} - -static int scrollback_phys_max = 0; -static int scrollback_max = 0; -static int scrollback_current = 0; - -static __inline__ void ywrap_up(int unit, struct vc_data *conp, - struct display *p, int count) -{ - p->yscroll += count; - if (p->yscroll >= p->vrows) /* Deal with wrap */ - p->yscroll -= p->vrows; - p->var.xoffset = 0; - p->var.yoffset = p->yscroll*fontheight(p); - p->var.vmode |= FB_VMODE_YWRAP; - p->fb_info->updatevar(unit, p->fb_info); - scrollback_max += count; - if (scrollback_max > scrollback_phys_max) - scrollback_max = scrollback_phys_max; - scrollback_current = 0; -} - - -static __inline__ void ywrap_down(int unit, struct vc_data *conp, - struct display *p, int count) -{ - p->yscroll -= count; - if (p->yscroll < 0) /* Deal with wrap */ - p->yscroll += p->vrows; - p->var.xoffset = 0; - p->var.yoffset = p->yscroll*fontheight(p); - p->var.vmode |= FB_VMODE_YWRAP; - p->fb_info->updatevar(unit, p->fb_info); - scrollback_max -= count; - if (scrollback_max < 0) - scrollback_max = 0; - scrollback_current = 0; -} - - -static __inline__ void ypan_up(int unit, struct vc_data *conp, - struct display *p, int count) -{ - p->yscroll += count; - if (p->yscroll > p->vrows-conp->vc_rows) { - p->dispsw->bmove(p, p->vrows-conp->vc_rows, 0, 0, 0, - conp->vc_rows, conp->vc_cols); - p->yscroll -= p->vrows-conp->vc_rows; - } - p->var.xoffset = 0; - p->var.yoffset = p->yscroll*fontheight(p); - p->var.vmode &= ~FB_VMODE_YWRAP; - p->fb_info->updatevar(unit, p->fb_info); - if (p->dispsw->clear_margins) - p->dispsw->clear_margins(conp, p, 1); - scrollback_max += count; - if (scrollback_max > scrollback_phys_max) - scrollback_max = scrollback_phys_max; - scrollback_current = 0; -} - - -static __inline__ void ypan_down(int unit, struct vc_data *conp, - struct display *p, int count) -{ - p->yscroll -= count; - if (p->yscroll < 0) { - p->dispsw->bmove(p, 0, 0, p->vrows-conp->vc_rows, 0, - conp->vc_rows, conp->vc_cols); - p->yscroll += p->vrows-conp->vc_rows; - } - p->var.xoffset = 0; - p->var.yoffset = p->yscroll*fontheight(p); - p->var.vmode &= ~FB_VMODE_YWRAP; - p->fb_info->updatevar(unit, p->fb_info); - if (p->dispsw->clear_margins) - p->dispsw->clear_margins(conp, p, 1); - scrollback_max -= count; - if (scrollback_max < 0) - scrollback_max = 0; - scrollback_current = 0; -} - -static void fbcon_redraw_softback(struct vc_data *conp, struct display *p, long delta) -{ - unsigned short *d, *s; - unsigned long n; - int line = 0; - int count = conp->vc_rows; - - d = (u16 *)softback_curr; - if (d == (u16 *)softback_in) - d = (u16 *)conp->vc_origin; - n = softback_curr + delta * conp->vc_size_row; - softback_lines -= delta; - if (delta < 0) { - if (softback_curr < softback_top && n < softback_buf) { - n += softback_end - softback_buf; - if (n < softback_top) { - softback_lines -= (softback_top - n) / conp->vc_size_row; - n = softback_top; - } - } else if (softback_curr >= softback_top && n < softback_top) { - softback_lines -= (softback_top - n) / conp->vc_size_row; - n = softback_top; - } - } else { - if (softback_curr > softback_in && n >= softback_end) { - n += softback_buf - softback_end; - if (n > softback_in) { - n = softback_in; - softback_lines = 0; - } - } else if (softback_curr <= softback_in && n > softback_in) { - n = softback_in; - softback_lines = 0; - } - } - if (n == softback_curr) - return; - softback_curr = n; - s = (u16 *)softback_curr; - if (s == (u16 *)softback_in) - s = (u16 *)conp->vc_origin; - while (count--) { - unsigned short *start; - unsigned short *le; - unsigned short c; - int x = 0; - unsigned short attr = 1; - - start = s; - le = advance_row(s, 1); - do { - c = scr_readw(s); - if (attr != (c & 0xff00)) { - attr = c & 0xff00; - if (s > start) { - p->dispsw->putcs(conp, p, start, s - start, - real_y(p, line), x); - x += s - start; - start = s; - } - } - if (c == scr_readw(d)) { - if (s > start) { - p->dispsw->putcs(conp, p, start, s - start, - real_y(p, line), x); - x += s - start + 1; - start = s + 1; - } else { - x++; - start++; - } - } - s++; - d++; - } while (s < le); - if (s > start) - p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); - line++; - if (d == (u16 *)softback_end) - d = (u16 *)softback_buf; - if (d == (u16 *)softback_in) - d = (u16 *)conp->vc_origin; - if (s == (u16 *)softback_end) - s = (u16 *)softback_buf; - if (s == (u16 *)softback_in) - s = (u16 *)conp->vc_origin; - } -} - -static void fbcon_redraw(struct vc_data *conp, struct display *p, - int line, int count, int offset) -{ - unsigned short *d = (unsigned short *) - (conp->vc_origin + conp->vc_size_row * line); - unsigned short *s = d + offset; - - while (count--) { - unsigned short *start = s; - unsigned short *le = advance_row(s, 1); - unsigned short c; - int x = 0; - unsigned short attr = 1; - - do { - c = scr_readw(s); - if (attr != (c & 0xff00)) { - attr = c & 0xff00; - if (s > start) { - p->dispsw->putcs(conp, p, start, s - start, - real_y(p, line), x); - x += s - start; - start = s; - } - } - if (c == scr_readw(d)) { - if (s > start) { - p->dispsw->putcs(conp, p, start, s - start, - real_y(p, line), x); - x += s - start + 1; - start = s + 1; - } else { - x++; - start++; - } - } - scr_writew(c, d); - console_conditional_schedule(); - s++; - d++; - } while (s < le); - if (s > start) - p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); - console_conditional_schedule(); - if (offset > 0) - line++; - else { - line--; - /* NOTE: We subtract two lines from these pointers */ - s -= conp->vc_size_row; - d -= conp->vc_size_row; - } - } -} - -/** - * fbcon_redraw_clear - clear area of the screen - * @conp: stucture pointing to current active virtual console - * @p: display structure - * @sy: starting Y coordinate - * @sx: starting X coordinate - * @height: height of area to clear - * @width: width of area to clear - * - * Clears a specified area of the screen. All dimensions are in - * pixels. - * - */ - -void fbcon_redraw_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) -{ - int x, y; - for (y=0; y<height; y++) - for (x=0; x<width; x++) - fbcon_putc(conp, ' ', sy+y, sx+x); -} - - -/** - * fbcon_redraw_bmove - copy area of screen to another area - * @p: display structure - * @sy: origin Y coordinate - * @sx: origin X coordinate - * @dy: destination Y coordinate - * @dx: destination X coordinate - * @h: height of area to copy - * @w: width of area to copy - * - * Copies an area of the screen to another area of the same screen. - * All dimensions are in pixels. - * - * Note that this function cannot be used together with ypan or - * ywrap. - * - */ - -void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h, int w) -{ - if (sy != dy) - panic("fbcon_redraw_bmove width sy != dy"); - /* h will be always 1, but it does not matter if we are more generic */ - - while (h-- > 0) { - struct vc_data *conp = p->conp; - unsigned short *d = (unsigned short *) - (conp->vc_origin + conp->vc_size_row * dy + dx * 2); - unsigned short *s = d + (dx - sx); - unsigned short *start = d; - unsigned short *ls = d; - unsigned short *le = d + w; - unsigned short c; - int x = dx; - unsigned short attr = 1; - - do { - c = scr_readw(d); - if (attr != (c & 0xff00)) { - attr = c & 0xff00; - if (d > start) { - p->dispsw->putcs(conp, p, start, d - start, dy, x); - x += d - start; - start = d; - } - } - if (s >= ls && s < le && c == scr_readw(s)) { - if (d > start) { - p->dispsw->putcs(conp, p, start, d - start, dy, x); - x += d - start + 1; - start = d + 1; - } else { - x++; - start++; - } - } - s++; - d++; - } while (d < le); - if (d > start) - p->dispsw->putcs(conp, p, start, d - start, dy, x); - sy++; - dy++; - } -} - -static inline void fbcon_softback_note(struct vc_data *conp, int t, int count) -{ - unsigned short *p; - - if (conp->vc_num != fg_console) - return; - p = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row); - - while (count) { - scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row); - count--; - p = advance_row(p, 1); - softback_in += conp->vc_size_row; - if (softback_in == softback_end) - softback_in = softback_buf; - if (softback_in == softback_top) { - softback_top += conp->vc_size_row; - if (softback_top == softback_end) - softback_top = softback_buf; - } - } - softback_curr = softback_in; -} - -static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, - int count) -{ - int unit = conp->vc_num; - struct display *p = &fb_display[unit]; - int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL); - - if (!p->can_soft_blank && console_blanked) - return 0; - - if (!count || vt_cons[unit]->vc_mode != KD_TEXT) - return 0; - - fbcon_cursor(conp, CM_ERASE); - - /* - * ++Geert: Only use ywrap/ypan if the console is in text mode - * ++Andrew: Only use ypan on hardware text mode when scrolling the - * whole screen (prevents flicker). - */ - - switch (dir) { - case SM_UP: - if (count > conp->vc_rows) /* Maximum realistic size */ - count = conp->vc_rows; - if (softback_top) - fbcon_softback_note(conp, t, count); - if (logo_shown >= 0) goto redraw_up; - switch (p->scrollmode & __SCROLL_YMASK) { - case __SCROLL_YMOVE: - p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count, - conp->vc_cols); - p->dispsw->clear(conp, p, b-count, 0, count, - conp->vc_cols); - break; - - case __SCROLL_YWRAP: - if (b-t-count > 3*conp->vc_rows>>2) { - if (t > 0) - fbcon_bmove(conp, 0, 0, count, 0, t, - conp->vc_cols); - ywrap_up(unit, conp, p, count); - if (conp->vc_rows-b > 0) - fbcon_bmove(conp, b-count, 0, b, 0, - conp->vc_rows-b, conp->vc_cols); - } else if (p->scrollmode & __SCROLL_YPANREDRAW) - goto redraw_up; - else - fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, - conp->vc_cols); - fbcon_clear(conp, b-count, 0, count, conp->vc_cols); - break; - - case __SCROLL_YPAN: - if (( p->yscroll + count <= 2 * (p->vrows - conp->vc_rows)) && - (( !scroll_partial && (b-t == conp->vc_rows)) || - ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2)))) { - if (t > 0) - fbcon_bmove(conp, 0, 0, count, 0, t, - conp->vc_cols); - ypan_up(unit, conp, p, count); - if (conp->vc_rows-b > 0) - fbcon_bmove(conp, b-count, 0, b, 0, - conp->vc_rows-b, conp->vc_cols); - } else if (p->scrollmode & __SCROLL_YPANREDRAW) - goto redraw_up; - else - fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, - conp->vc_cols); - fbcon_clear(conp, b-count, 0, count, conp->vc_cols); - break; - - case __SCROLL_YREDRAW: - redraw_up: - fbcon_redraw(conp, p, t, b-t-count, count*conp->vc_cols); - p->dispsw->clear(conp, p, real_y(p, b-count), 0, - count, conp->vc_cols); - scr_memsetw((unsigned short *)(conp->vc_origin + - conp->vc_size_row * (b-count)), - conp->vc_video_erase_char, - conp->vc_size_row * count); - return 1; - } - break; - - case SM_DOWN: - if (count > conp->vc_rows) /* Maximum realistic size */ - count = conp->vc_rows; - switch (p->scrollmode & __SCROLL_YMASK) { - case __SCROLL_YMOVE: - p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count, - conp->vc_cols); - p->dispsw->clear(conp, p, t, 0, - count, conp->vc_cols); - break; - - case __SCROLL_YWRAP: - if (b-t-count > 3*conp->vc_rows>>2) { - if (conp->vc_rows-b > 0) - fbcon_bmove(conp, b, 0, b-count, 0, - conp->vc_rows-b, conp->vc_cols); - ywrap_down(unit, conp, p, count); - if (t > 0) - fbcon_bmove(conp, count, 0, 0, 0, t, - conp->vc_cols); - } else if (p->scrollmode & __SCROLL_YPANREDRAW) - goto redraw_down; - else - fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, - conp->vc_cols); - fbcon_clear(conp, t, 0, count, conp->vc_cols); - break; - - case __SCROLL_YPAN: - if (( count-p->yscroll <= p->vrows-conp->vc_rows) && - (( !scroll_partial && (b-t == conp->vc_rows)) || - ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2)))) { - if (conp->vc_rows-b > 0) - fbcon_bmove(conp, b, 0, b-count, 0, - conp->vc_rows-b, conp->vc_cols); - ypan_down(unit, conp, p, count); - if (t > 0) - fbcon_bmove(conp, count, 0, 0, 0, t, - conp->vc_cols); - } else if (p->scrollmode & __SCROLL_YPANREDRAW) - goto redraw_down; - else - fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, - conp->vc_cols); - fbcon_clear(conp, t, 0, count, conp->vc_cols); - break; - - case __SCROLL_YREDRAW: - redraw_down: - fbcon_redraw(conp, p, b - 1, b-t-count, -count*conp->vc_cols); - p->dispsw->clear(conp, p, real_y(p, t), 0, - count, conp->vc_cols); - scr_memsetw((unsigned short *)(conp->vc_origin + - conp->vc_size_row * t), - conp->vc_video_erase_char, - conp->vc_size_row * count); - return 1; - } - } - return 0; -} - - -static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, - int height, int width) -{ - int unit = conp->vc_num; - struct display *p = &fb_display[unit]; - - if (!p->can_soft_blank && console_blanked) - return; - - if (!width || !height) - return; - - 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))) - fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK); - - /* Split blits that cross physical y_wrap case. - * Pathological case involves 4 blits, better to use recursive - * code rather than unrolled case - * - * Recursive invocations don't need to erase the cursor over and - * over again, so we use fbcon_bmove_rec() - */ - fbcon_bmove_rec(p, sy, sx, dy, dx, height, width, p->vrows-p->yscroll); -} - -static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx, - int height, int width, u_int y_break) -{ - u_int b; - - if (sy < y_break && sy+height > y_break) { - b = y_break-sy; - if (dy < sy) { /* Avoid trashing self */ - fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break); - fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break); - } else { - fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break); - fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break); - } - return; - } - - if (dy < y_break && dy+height > y_break) { - b = y_break-dy; - if (dy < sy) { /* Avoid trashing self */ - fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break); - fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break); - } else { - fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break); - fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break); - } - return; - } - p->dispsw->bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, width); -} - - -static int fbcon_switch(struct vc_data *conp) -{ - int unit = conp->vc_num; - struct display *p = &fb_display[unit]; - struct fb_info *info = p->fb_info; - - if (softback_top) { - int l = fbcon_softback_size / conp->vc_size_row; - if (softback_lines) - fbcon_set_origin(conp); - softback_top = softback_curr = softback_in = softback_buf; - softback_lines = 0; - - if (l > 5) - softback_end = softback_buf + l * conp->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 would screw - the operation totally */ - softback_top = 0; - } - } - if (logo_shown >= 0) { - struct vc_data *conp2 = vc_cons[logo_shown].d; - - if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows) - conp2->vc_top = 0; - logo_shown = -1; - } - p->var.yoffset = p->yscroll = 0; - switch (p->scrollmode & __SCROLL_YMASK) { - case __SCROLL_YWRAP: - scrollback_phys_max = p->vrows-conp->vc_rows; - break; - case __SCROLL_YPAN: - scrollback_phys_max = p->vrows-2*conp->vc_rows; - if (scrollback_phys_max < 0) - scrollback_phys_max = 0; - break; - default: - scrollback_phys_max = 0; - break; - } - scrollback_max = 0; - scrollback_current = 0; - - if (info && info->switch_con) - (*info->switch_con)(unit, info); - if (p->dispsw->clear_margins && vt_cons[unit]->vc_mode == KD_TEXT) - p->dispsw->clear_margins(conp, p, 0); - if (logo_shown == -2) { - logo_shown = fg_console; - fbcon_show_logo(); /* This is protected above by initmem_freed */ - update_region(fg_console, - conp->vc_origin + conp->vc_size_row * conp->vc_top, - conp->vc_size_row * (conp->vc_bottom - conp->vc_top) / 2); - return 0; - } - return 1; -} - - -static int fbcon_blank(struct vc_data *conp, int blank) -{ - struct display *p = &fb_display[conp->vc_num]; - struct fb_info *info = p->fb_info; - - if (blank < 0) /* Entering graphics mode */ - return 0; - - fbcon_cursor(p->conp, blank ? CM_ERASE : CM_DRAW); - - if (!p->can_soft_blank) { - if (blank) { - if (info->fix.visual == FB_VISUAL_MONO01) { - if (info->screen_base) - fb_memset255(info->screen_base, - p->var.xres_virtual*p->var.yres_virtual* - p->var.bits_per_pixel>>3); - } else { - unsigned short oldc; - u_int height; - u_int y_break; - - oldc = conp->vc_video_erase_char; - conp->vc_video_erase_char &= p->charmask; - height = conp->vc_rows; - y_break = p->vrows-p->yscroll; - if (height > y_break) { - p->dispsw->clear(conp, p, real_y(p, 0), 0, y_break, conp->vc_cols); - p->dispsw->clear(conp, p, real_y(p, y_break), 0, height-y_break, conp->vc_cols); - } else - p->dispsw->clear(conp, p, real_y(p, 0), 0, height, conp->vc_cols); - conp->vc_video_erase_char = oldc; - } - return 0; - } else { - /* Tell console.c that it has to restore the screen itself */ - return 1; - } - } - if (info->fbops->fb_blank) - (*info->fbops->fb_blank)(blank, info); - return 0; -} - -static void fbcon_free_font(struct display *p) -{ - if (p->userfont && p->fontdata && - (--REFCOUNT(p->fontdata) == 0)) - kfree(p->fontdata - FONT_EXTRA_WORDS*sizeof(int)); - p->fontdata = NULL; - p->userfont = 0; -} - -static inline int fbcon_get_font(int unit, struct console_font_op *op) -{ - struct display *p = &fb_display[unit]; - u8 *data = op->data; - u8 *fontdata = p->fontdata; - int i, j; - -#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY - if (fontwidth(p) != 8) return -EINVAL; -#endif - op->width = fontwidth(p); - op->height = fontheight(p); - op->charcount = (p->charmask == 0x1ff) ? 512 : 256; - if (!op->data) return 0; - - if (op->width <= 8) { - j = fontheight(p); - for (i = 0; i < op->charcount; i++) { - memcpy(data, fontdata, j); - memset(data+j, 0, 32-j); - data += 32; - fontdata += j; - } - } -#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY - else if (op->width <= 16) { - j = fontheight(p) * 2; - for (i = 0; i < op->charcount; i++) { - memcpy(data, fontdata, j); - memset(data+j, 0, 64-j); - data += 64; - fontdata += j; - } - } else if (op->width <= 24) { - for (i = 0; i < op->charcount; i++) { - for (j = 0; j < fontheight(p); j++) { - *data++ = fontdata[0]; - *data++ = fontdata[1]; - *data++ = fontdata[2]; - fontdata += sizeof(u32); - } - memset(data, 0, 3*(32-j)); - data += 3 * (32 - j); - } - } else { - j = fontheight(p) * 4; - for (i = 0; i < op->charcount; i++) { - memcpy(data, fontdata, j); - memset(data+j, 0, 128-j); - data += 128; - fontdata += j; - } - } -#endif - return 0; -} - -static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int userfont) -{ - struct display *p = &fb_display[unit]; - int resize; - int w = op->width; - int h = op->height; - int cnt; - char *old_data = NULL; - - if (!fontwidthvalid(p,w)) { - if (userfont && op->op != KD_FONT_OP_COPY) - kfree(data - FONT_EXTRA_WORDS*sizeof(int)); - return -ENXIO; - } - - if (CON_IS_VISIBLE(p->conp) && softback_lines) - fbcon_set_origin(p->conp); - - resize = (w != fontwidth(p)) || (h != fontheight(p)); - if (p->userfont) - old_data = p->fontdata; - if (userfont) - cnt = FNTCHARCNT(data); - else - cnt = 256; - p->fontdata = data; - if ((p->userfont = userfont)) - REFCOUNT(data)++; - p->_fontwidth = w; - p->_fontheight = h; - if (p->conp->vc_hi_font_mask && cnt == 256) { - p->conp->vc_hi_font_mask = 0; - if (p->conp->vc_can_do_color) - p->conp->vc_complement_mask >>= 1; - p->fgshift--; - p->bgshift--; - p->charmask = 0xff; - - /* ++Edmund: reorder the attribute bits */ - if (p->conp->vc_can_do_color) { - struct vc_data *conp = p->conp; - unsigned short *cp = (unsigned short *) conp->vc_origin; - int count = conp->vc_screenbuf_size/2; - unsigned short c; - for (; count > 0; count--, cp++) { - c = scr_readw(cp); - scr_writew(((c & 0xfe00) >> 1) | (c & 0xff), cp); - } - c = conp->vc_video_erase_char; - conp->vc_video_erase_char = ((c & 0xfe00) >> 1) | (c & 0xff); - conp->vc_attr >>= 1; - } - - } else if (!p->conp->vc_hi_font_mask && cnt == 512) { - p->conp->vc_hi_font_mask = 0x100; - if (p->conp->vc_can_do_color) - p->conp->vc_complement_mask <<= 1; - p->fgshift++; - p->bgshift++; - p->charmask = 0x1ff; - - /* ++Edmund: reorder the attribute bits */ - { - struct vc_data *conp = p->conp; - unsigned short *cp = (unsigned short *) conp->vc_origin; - int count = conp->vc_screenbuf_size/2; - unsigned short c; - for (; count > 0; count--, cp++) { - unsigned short newc; - c = scr_readw(cp); - if (conp->vc_can_do_color) - newc = ((c & 0xff00) << 1) | (c & 0xff); - else - newc = c & ~0x100; - scr_writew(newc, cp); - } - c = conp->vc_video_erase_char; - if (conp->vc_can_do_color) { - conp->vc_video_erase_char = ((c & 0xff00) << 1) | (c & 0xff); - conp->vc_attr <<= 1; - } else - conp->vc_video_erase_char = c & ~0x100; - } - - } - fbcon_font_widths(p); - - if (resize) { - struct vc_data *conp = p->conp; - /* reset wrap/pan */ - p->var.xoffset = p->var.yoffset = p->yscroll = 0; - p->vrows = p->var.yres_virtual/h; - if ((p->var.yres % h) && (p->var.yres_virtual % h < p->var.yres % h)) - p->vrows--; - updatescrollmode(p); - vc_resize_con( p->var.yres/h, p->var.xres/w, unit ); - if (CON_IS_VISIBLE(conp) && softback_buf) { - int l = fbcon_softback_size / conp->vc_size_row; - if (l > 5) - softback_end = softback_buf + l * conp->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 would screw - the operation totally */ - softback_top = 0; - } - } - } else if (CON_IS_VISIBLE(p->conp) && vt_cons[unit]->vc_mode == KD_TEXT) { - if (p->dispsw->clear_margins) - p->dispsw->clear_margins(p->conp, p, 0); - update_screen(unit); - } - - if (old_data && (--REFCOUNT(old_data) == 0)) - kfree(old_data - FONT_EXTRA_WORDS*sizeof(int)); - - return 0; -} - -static inline int fbcon_copy_font(int unit, struct console_font_op *op) -{ - struct display *od, *p = &fb_display[unit]; - int h = op->height; - - if (h < 0 || !vc_cons_allocated( h )) - return -ENOTTY; - if (h == unit) - return 0; /* nothing to do */ - od = &fb_display[h]; - if (od->fontdata == p->fontdata) - return 0; /* already the same font... */ - op->width = fontwidth(od); - op->height = fontheight(od); - return fbcon_do_set_font(unit, op, od->fontdata, od->userfont); -} - -static inline int fbcon_set_font(int unit, struct console_font_op *op) -{ - int w = op->width; - int h = op->height; - int size = h; - int i, k; - u8 *new_data, *data = op->data, *p; - -#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY - if (w != 8) - return -EINVAL; -#endif - if ((w <= 0) || (w > 32) || (op->charcount != 256 && op->charcount != 512)) - return -EINVAL; - - if (w > 8) { - if (w <= 16) - size *= 2; - else - size *= 4; - } - size *= op->charcount; - - if (!(new_data = kmalloc(FONT_EXTRA_WORDS*sizeof(int)+size, GFP_USER))) - return -ENOMEM; - new_data += FONT_EXTRA_WORDS*sizeof(int); - FNTSIZE(new_data) = size; - FNTCHARCNT(new_data) = op->charcount; - REFCOUNT(new_data) = 0; /* usage counter */ - p = new_data; - if (w <= 8) { - for (i = 0; i < op->charcount; i++) { - memcpy(p, data, h); - data += 32; - p += h; - } - } -#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY - else if (w <= 16) { - h *= 2; - for (i = 0; i < op->charcount; i++) { - memcpy(p, data, h); - data += 64; - p += h; - } - } else if (w <= 24) { - for (i = 0; i < op->charcount; i++) { - int j; - for (j = 0; j < h; j++) { - memcpy(p, data, 3); - p[3] = 0; - data += 3; - p += sizeof(u32); - } - data += 3*(32 - h); - } - } else { - h *= 4; - for (i = 0; i < op->charcount; i++) { - memcpy(p, data, h); - data += 128; - 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 */ - k = 0; - while (p > new_data) k += *--(u32 *)p; - FNTSUM(new_data) = k; - /* Check if the same font is on some other console already */ - for (i = 0; i < MAX_NR_CONSOLES; i++) { - if (fb_display[i].userfont && - fb_display[i].fontdata && - FNTSUM(fb_display[i].fontdata) == k && - FNTSIZE(fb_display[i].fontdata) == size && - fontwidth(&fb_display[i]) == w && - !memcmp(fb_display[i].fontdata, new_data, size)) { - kfree(new_data - FONT_EXTRA_WORDS*sizeof(int)); - new_data = fb_display[i].fontdata; - break; - } - } - return fbcon_do_set_font(unit, op, new_data, 1); -} - -static inline int fbcon_set_def_font(int unit, struct console_font_op *op) -{ - char name[MAX_FONT_NAME]; - struct fbcon_font_desc *f; - struct display *p = &fb_display[unit]; - - if (!op->data) - f = fbcon_get_default_font(p->var.xres, p->var.yres); - else if (strncpy_from_user(name, op->data, MAX_FONT_NAME-1) < 0) - return -EFAULT; - else { - name[MAX_FONT_NAME-1] = 0; - if (!(f = fbcon_find_font(name))) - return -ENOENT; - } - op->width = f->width; - op->height = f->height; - return fbcon_do_set_font(unit, op, f->data, 0); -} - -static int fbcon_font_op(struct vc_data *conp, struct console_font_op *op) -{ - int unit = conp->vc_num; - - switch (op->op) { - case KD_FONT_OP_SET: - return fbcon_set_font(unit, op); - case KD_FONT_OP_GET: - return fbcon_get_font(unit, op); - case KD_FONT_OP_SET_DEFAULT: - return fbcon_set_def_font(unit, op); - case KD_FONT_OP_COPY: - return fbcon_copy_font(unit, op); - default: - return -ENOSYS; - } -} - -static u16 palette_red[16]; -static u16 palette_green[16]; -static u16 palette_blue[16]; - -static struct fb_cmap palette_cmap = { - 0, 16, palette_red, palette_green, palette_blue, NULL -}; - -static int fbcon_set_palette(struct vc_data *conp, unsigned char *table) -{ - int unit = conp->vc_num; - struct display *p = &fb_display[unit]; - int i, j, k; - u8 val; - - if (!conp->vc_can_do_color || (!p->can_soft_blank && console_blanked)) - return -EINVAL; - for (i = j = 0; i < 16; i++) { - k = table[i]; - val = conp->vc_palette[j++]; - palette_red[k] = (val<<8)|val; - val = conp->vc_palette[j++]; - palette_green[k] = (val<<8)|val; - val = conp->vc_palette[j++]; - palette_blue[k] = (val<<8)|val; - } - if (p->var.bits_per_pixel <= 4) - palette_cmap.len = 1<<p->var.bits_per_pixel; - else - palette_cmap.len = 16; - palette_cmap.start = 0; - return p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, unit, p->fb_info); -} - -static u16 *fbcon_screen_pos(struct vc_data *conp, int offset) -{ - 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 unsigned long fbcon_getxy(struct vc_data *conp, unsigned long pos, int *px, int *py) -{ - 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; -} - -/* As we might be inside of softback, we may work with non-contiguous buffer, - that's why we have to use a separate routine. */ -static void fbcon_invert_region(struct vc_data *conp, u16 *p, int cnt) -{ - while (cnt--) { - u16 a = scr_readw(p); - if (!conp->vc_can_do_color) - a ^= 0x0800; - else if (conp->vc_hi_font_mask == 0x100) - a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4); - else - a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4); - scr_writew(a, p++); - if (p == (u16 *)softback_end) - p = (u16 *)softback_buf; - if (p == (u16 *)softback_in) - p = (u16 *)conp->vc_origin; - } -} - -static int fbcon_scrolldelta(struct vc_data *conp, int lines) -{ - int unit, offset, limit, scrollback_old; - struct display *p; - - unit = fg_console; - p = &fb_display[unit]; - if (softback_top) { - if (conp->vc_num != unit) - return 0; - if (vt_cons[unit]->vc_mode != KD_TEXT || !lines) - return 0; - if (logo_shown >= 0) { - struct vc_data *conp2 = vc_cons[logo_shown].d; - - if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows) - conp2->vc_top = 0; - if (logo_shown == unit) { - unsigned long p, q; - int i; - - p = softback_in; - q = conp->vc_origin + logo_lines * conp->vc_size_row; - for (i = 0; i < logo_lines; i++) { - if (p == softback_top) break; - if (p == softback_buf) p = softback_end; - p -= conp->vc_size_row; - q -= conp->vc_size_row; - scr_memcpyw((u16 *)q, (u16 *)p, conp->vc_size_row); - } - softback_in = p; - update_region(unit, conp->vc_origin, logo_lines * conp->vc_cols); - } - logo_shown = -1; - } - fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK); - fbcon_redraw_softback(conp, p, lines); - fbcon_cursor(conp, CM_DRAW|CM_SOFTBACK); - return 0; - } - - if (!scrollback_phys_max) - return -ENOSYS; - - scrollback_old = scrollback_current; - scrollback_current -= lines; - if (scrollback_current < 0) - scrollback_current = 0; - else if (scrollback_current > scrollback_max) - scrollback_current = scrollback_max; - if (scrollback_current == scrollback_old) - return 0; - - if (!p->can_soft_blank && - (console_blanked || vt_cons[unit]->vc_mode != KD_TEXT || !lines)) - return 0; - fbcon_cursor(conp, CM_ERASE); - - offset = p->yscroll-scrollback_current; - limit = p->vrows; - switch (p->scrollmode && __SCROLL_YMASK) { - case __SCROLL_YWRAP: - p->var.vmode |= FB_VMODE_YWRAP; - break; - case __SCROLL_YPAN: - limit -= conp->vc_rows; - p->var.vmode &= ~FB_VMODE_YWRAP; - break; - } - if (offset < 0) - offset += limit; - else if (offset >= limit) - offset -= limit; - p->var.xoffset = 0; - p->var.yoffset = offset*fontheight(p); - p->fb_info->updatevar(unit, p->fb_info); - if (!scrollback_current) - fbcon_cursor(conp, CM_DRAW); - return 0; -} - -static int fbcon_set_origin(struct vc_data *conp) -{ - if (softback_lines && !console_blanked) - fbcon_scrolldelta(conp, softback_lines); - return 0; -} - -static inline unsigned safe_shift(unsigned d,int n) -{ - return n<0 ? d>>-n : d<<n; -} - -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; - int depth = p->var.bits_per_pixel; - int line = p->next_line; - unsigned char *fb = info->screen_base; - unsigned char *logo; - unsigned char *dst, *src; - int i, j, n, x1, y1, x; - int logo_depth, done = 0; - - /* Return if the frame buffer is not mapped */ - if (!fb) - return 0; - - /* - * Set colors if visual is PSEUDOCOLOR and we have enough colors, or for - * DIRECTCOLOR - * We don't have to set the colors for the 16-color logo, since that logo - * uses the standard VGA text console palette - */ - if ((info->fix.visual == FB_VISUAL_PSEUDOCOLOR && depth >= 8) || - (info->fix.visual == FB_VISUAL_DIRECTCOLOR && depth >= 24)) - 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]; - } - info->fbops->fb_set_cmap(&palette_cmap, 1, fg_console, info); - } - - if (depth >= 8) { - logo = linux_logo; - logo_depth = 8; - } - else if (depth >= 4) { - logo = linux_logo16; - logo_depth = 4; - } - else { - logo = linux_logo_bw; - logo_depth = 1; - } - - if (info->fbops->fb_rasterimg) - info->fbops->fb_rasterimg(info, 1); - - for (x = 0; x < num_online_cpus() * (LOGO_W + 8) && - x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) { - -#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \ - defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS) - if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - unsigned int val; /* max. depth 32! */ - int bdepth; - int redshift, greenshift, blueshift; - - /* Bug: Doesn't obey msb_right ... (who needs that?) */ - redshift = p->var.red.offset; - greenshift = p->var.green.offset; - blueshift = p->var.blue.offset; - - if (depth >= 24 && (depth % 8) == 0) { - /* have at least 8 bits per color */ - src = logo; - bdepth = depth/8; - for( y1 = 0; y1 < LOGO_H; y1++ ) { - dst = fb + y1*line + x*bdepth; - for( x1 = 0; x1 < LOGO_W; x1++, src++ ) { - val = (*src << redshift) | - (*src << greenshift) | - (*src << blueshift); - if (bdepth == 4 && !((long)dst & 3)) { - /* Some cards require 32bit access */ - fb_writel (val, dst); - dst += 4; - } else if (bdepth == 2 && !((long)dst & 1)) { - /* others require 16bit access */ - fb_writew (val,dst); - dst +=2; - } else { -#ifdef __LITTLE_ENDIAN - for( i = 0; i < bdepth; ++i ) -#else - for( i = bdepth-1; i >= 0; --i ) -#endif - fb_writeb (val >> (i*8), dst++); - } - } - } - } - else if (depth >= 12 && depth <= 23) { - /* have 4..7 bits per color, using 16 color image */ - unsigned int pix; - src = linux_logo16; - bdepth = (depth+7)/8; - for( y1 = 0; y1 < LOGO_H; y1++ ) { - dst = fb + y1*line + x*bdepth; - for( x1 = 0; x1 < LOGO_W/2; x1++, src++ ) { - pix = *src >> 4; /* upper nibble */ - val = (pix << redshift) | - (pix << greenshift) | - (pix << blueshift); -#ifdef __LITTLE_ENDIAN - for( i = 0; i < bdepth; ++i ) -#else - for( i = bdepth-1; i >= 0; --i ) -#endif - fb_writeb (val >> (i*8), dst++); - pix = *src & 0x0f; /* lower nibble */ - val = (pix << redshift) | - (pix << greenshift) | - (pix << blueshift); -#ifdef __LITTLE_ENDIAN - for( i = 0; i < bdepth; ++i ) -#else - for( i = bdepth-1; i >= 0; --i ) -#endif - fb_writeb (val >> (i*8), dst++); - } - } - } - done = 1; - } -#endif -#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \ - defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS) - if ((depth % 8 == 0) && (info->fix.visual == FB_VISUAL_TRUECOLOR)) { - /* Modes without color mapping, needs special data transformation... */ - unsigned int val; /* max. depth 32! */ - int bdepth = depth/8; - unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; - unsigned char redmask, greenmask, bluemask; - int redshift, greenshift, blueshift; - - /* Bug: Doesn't obey msb_right ... (who needs that?) */ - redmask = mask[p->var.red.length < 8 ? p->var.red.length : 8]; - greenmask = mask[p->var.green.length < 8 ? p->var.green.length : 8]; - bluemask = mask[p->var.blue.length < 8 ? p->var.blue.length : 8]; - redshift = p->var.red.offset - (8-p->var.red.length); - greenshift = p->var.green.offset - (8-p->var.green.length); - blueshift = p->var.blue.offset - (8-p->var.blue.length); - - src = logo; - for( y1 = 0; y1 < LOGO_H; y1++ ) { - dst = fb + y1*line + x*bdepth; - for( x1 = 0; x1 < LOGO_W; x1++, src++ ) { - val = safe_shift((linux_logo_red[*src-32] & redmask), redshift) | - safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) | - safe_shift((linux_logo_blue[*src-32] & bluemask), blueshift); - if (bdepth == 4 && !((long)dst & 3)) { - /* Some cards require 32bit access */ - fb_writel (val, dst); - dst += 4; - } else if (bdepth == 2 && !((long)dst & 1)) { - /* others require 16bit access */ - fb_writew (val,dst); - dst +=2; - } else { -#ifdef __LITTLE_ENDIAN - for( i = 0; i < bdepth; ++i ) -#else - for( i = bdepth-1; i >= 0; --i ) -#endif - fb_writeb (val >> (i*8), dst++); - } - } - } - done = 1; - } -#endif -#if defined(CONFIG_FBCON_CFB4) - if (depth == 4 && info->fix.type == FB_TYPE_PACKED_PIXELS) { - src = logo; - for( y1 = 0; y1 < LOGO_H; y1++) { - dst = fb + y1*line + x/2; - for( x1 = 0; x1 < LOGO_W/2; x1++) { - u8 q = *src++; - q = (q << 4) | (q >> 4); - fb_writeb (q, dst++); - } - } - done = 1; - } -#endif -#if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FB_SBUS) - if (depth == 8 && info->fix.type == FB_TYPE_PACKED_PIXELS) { - /* depth 8 or more, packed, with color registers */ - - src = logo; - for( y1 = 0; y1 < LOGO_H; y1++ ) { - dst = fb + y1*line + x; - for( x1 = 0; x1 < LOGO_W; x1++ ) - fb_writeb (*src++, dst++); - } - done = 1; - } -#endif -#if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_ILBM) || \ - defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \ - defined(CONFIG_FBCON_IPLAN2P8) - if (depth >= 2 && (info->fix.type == FB_TYPE_PLANES || - info->fix.type == FB_TYPE_INTERLEAVED_PLANES)) { - /* planes (normal or interleaved), with color registers */ - int bit; - unsigned char val, mask; - int plane = p->next_plane; - -#if defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \ - defined(CONFIG_FBCON_IPLAN2P8) - int line_length = info->fix.line_length; - - /* for support of Atari interleaved planes */ -#define MAP_X(x) (line_length ? (x) : ((x) & ~1)*depth + ((x) & 1)) -#else -#define MAP_X(x) (x) -#endif - /* extract a bit from the source image */ -#define BIT(p,pix,bit) (p[pix*logo_depth/8] & \ - (1 << ((8-((pix*logo_depth)&7)-logo_depth) + bit))) - - src = logo; - for( y1 = 0; y1 < LOGO_H; y1++ ) { - for( x1 = 0; x1 < LOGO_LINE; x1++, src += logo_depth ) { - dst = fb + y1*line + MAP_X(x/8+x1); - for( bit = 0; bit < logo_depth; bit++ ) { - val = 0; - for( mask = 0x80, i = 0; i < 8; mask >>= 1, i++ ) { - if (BIT( src, i, bit )) - val |= mask; - } - *dst = val; - dst += plane; - } - } - } - - /* fill remaining planes */ - if (depth > logo_depth) { - for( y1 = 0; y1 < LOGO_H; y1++ ) { - for( x1 = 0; x1 < LOGO_LINE; x1++ ) { - dst = fb + y1*line + MAP_X(x/8+x1) + logo_depth*plane; - for( i = logo_depth; i < depth; i++, dst += plane ) - *dst = 0x00; - } - } - } - done = 1; - break; - } -#endif -#if defined(CONFIG_FBCON_MFB) || defined(CONFIG_FBCON_AFB) || \ - defined(CONFIG_FBCON_ILBM) || defined(CONFIG_FBCON_HGA) - - if (depth == 1 && (info->fix.type == FB_TYPE_PACKED_PIXELS || - info->fix.type == FB_TYPE_PLANES || - info->fix.type == FB_TYPE_INTERLEAVED_PLANES)) { - - /* monochrome */ - unsigned char inverse = p->inverse || info->fix.visual == FB_VISUAL_MONO01 - ? 0x00 : 0xff; - - int is_hga = !strncmp(p->fb_info->modename, "HGA", 3); - /* can't use simply memcpy because need to apply inverse */ - for( y1 = 0; y1 < LOGO_H; y1++ ) { - src = logo + y1*LOGO_LINE; - if (is_hga) - dst = fb + (y1%4)*8192 + (y1>>2)*line + x/8; - else - dst = fb + y1*line + x/8; - for( x1 = 0; x1 < LOGO_LINE; ++x1 ) - fb_writeb(*src++ ^ inverse, dst++); - } - done = 1; - } -#endif -#if defined(CONFIG_FBCON_VGA_PLANES) - if (depth == 4 && info->fix.type == FB_TYPE_VGA_PLANES) { - outb_p(1,0x3ce); outb_p(0xf,0x3cf); - outb_p(3,0x3ce); outb_p(0,0x3cf); - outb_p(5,0x3ce); outb_p(0,0x3cf); - - src = logo; - for (y1 = 0; y1 < LOGO_H; y1++) { - for (x1 = 0; x1 < LOGO_W / 2; x1++) { - dst = fb + y1*line + x1/4 + x/8; - - outb_p(0,0x3ce); - outb_p(*src >> 4,0x3cf); - outb_p(8,0x3ce); - outb_p(1 << (7 - x1 % 4 * 2),0x3cf); - fb_readb (dst); - fb_writeb (0, dst); - - outb_p(0,0x3ce); - outb_p(*src & 0xf,0x3cf); - outb_p(8,0x3ce); - outb_p(1 << (7 - (1 + x1 % 4 * 2)),0x3cf); - fb_readb (dst); - fb_writeb (0, dst); - - src++; - } - } - done = 1; - } -#endif - } - - if (p->fb_info->fbops->fb_rasterimg) - p->fb_info->fbops->fb_rasterimg(p->fb_info, 0); - - /* Modes not yet supported: packed pixels with depth != 8 (does such a - * thing exist in reality?) */ - - return done ? (LOGO_H + fontheight(p) - 1) / fontheight(p) : 0 ; -} - -/* - * The console `switch' structure for the frame buffer based console - */ - -const struct consw fb_con = { - .con_startup = fbcon_startup, - .con_init = fbcon_init, - .con_deinit = fbcon_deinit, - .con_clear = fbcon_clear, - .con_putc = fbcon_putc, - .con_putcs = fbcon_putcs, - .con_cursor = fbcon_cursor, - .con_scroll = fbcon_scroll, - .con_bmove = fbcon_bmove, - .con_switch = fbcon_switch, - .con_blank = fbcon_blank, - .con_font_op = fbcon_font_op, - .con_set_palette = fbcon_set_palette, - .con_scrolldelta = fbcon_scrolldelta, - .con_set_origin = fbcon_set_origin, - .con_invert_region = fbcon_invert_region, - .con_screen_pos = fbcon_screen_pos, - .con_getxy = fbcon_getxy, -}; - - -/* - * Dummy Low Level Operations - */ - -static void fbcon_dummy_op(void) {} - -#define DUMMY (void *)fbcon_dummy_op - -struct display_switch fbcon_dummy = { - .setup = DUMMY, - .bmove = DUMMY, - .clear = DUMMY, - .putc = DUMMY, - .putcs = DUMMY, - .revc = DUMMY, -}; - - -/* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(fb_display); -EXPORT_SYMBOL(fbcon_redraw_bmove); -EXPORT_SYMBOL(fbcon_redraw_clear); -EXPORT_SYMBOL(fbcon_dummy); -EXPORT_SYMBOL(fb_con); - -MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbgen.c b/drivers/video/fbgen.c deleted file mode 100644 index e13783ed31d8..000000000000 --- a/drivers/video/fbgen.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * linux/drivers/video/fbgen.c -- Generic routines for frame buffer devices - * - * Created 3 Jan 1998 by Geert Uytterhoeven - * - * 2001 - Documented with DocBook - * - Brad Douglas <brad@neruo.com> - * - * 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/string.h> -#include <linux/tty.h> -#include <linux/fb.h> -#include <linux/slab.h> - -#include <asm/uaccess.h> -#include <asm/io.h> - -#include <video/fbcon.h> -#include <video/fbcon-mfb.h> -#include <video/fbcon-cfb2.h> -#include <video/fbcon-cfb4.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-cfb24.h> -#include <video/fbcon-cfb32.h> -#include "fbcon-accel.h" - -int gen_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) -{ - int err; - - if (con < 0 || (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo)))) { - if (!info->fbops->fb_check_var) { - *var = info->var; - return 0; - } - - if ((err = info->fbops->fb_check_var(var, info))) - return err; - - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { - info->var = *var; - - if (con == info->currcon) { - if (info->fbops->fb_set_par) - info->fbops->fb_set_par(info); - - if (info->fbops->fb_pan_display) - info->fbops->fb_pan_display(&info->var, con, info); - - gen_set_disp(con, info); - fb_set_cmap(&info->cmap, 1, info); - } - - if (info->changevar) - info->changevar(con); - } - } - return 0; -} - -int gen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) -{ - fb_copy_cmap (&info->cmap, cmap, kspc ? 0 : 2); - return 0; -} - -int gen_set_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) -{ - struct display *disp = (con < 0) ? info->disp : (fb_display + con); - struct fb_cmap *dcmap = &disp->cmap; - int err = 0; - - /* No colormap allocated ? */ - if (!dcmap->len) { - int size = info->cmap.len; - - err = fb_alloc_cmap(dcmap, size, 0); - } - - - if (!err && con == info->currcon) { - err = fb_set_cmap(cmap, kspc, info); - dcmap = &info->cmap; - } - - if (!err) - fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1); - return err; -} - -int fbgen_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *info) -{ - int xoffset = var->xoffset; - int yoffset = var->yoffset; - int err; - - if (xoffset < 0 || yoffset < 0 || - xoffset + info->var.xres > info->var.xres_virtual || - yoffset + info->var.yres > info->var.yres_virtual) - return -EINVAL; - if (con == info->currcon) { - if (info->fbops->fb_pan_display) { - if ((err = info->fbops->fb_pan_display(var, con, info))) - return err; - } else - return -EINVAL; - } - info->var.xoffset = var->xoffset; - info->var.yoffset = var->yoffset; - if (var->vmode & FB_VMODE_YWRAP) - info->var.vmode |= FB_VMODE_YWRAP; - else - info->var.vmode &= ~FB_VMODE_YWRAP; - return 0; -} - - -/* ---- Helper functions --------------------------------------------------- */ - -void gen_set_disp(int con, struct fb_info *info) -{ - struct display *display = (con < 0) ? info->disp : (fb_display + con); - - if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - display->can_soft_blank = info->fbops->fb_blank ? 1 : 0; - display->dispsw_data = NULL; - } else { - display->can_soft_blank = 0; - display->dispsw_data = info->pseudo_palette; - } - display->var = info->var; - - /* - * If we are setting all the virtual consoles, also set - * the defaults used to create new consoles. - */ - if (con < 0 || info->var.activate & FB_ACTIVATE_ALL) - info->disp->var = info->var; - - if (info->var.bits_per_pixel == 24) { -#ifdef FBCON_HAS_CFB24 - display->scrollmode = SCROLL_YREDRAW; - display->dispsw = &fbcon_cfb24; - return; -#endif - } - -#ifdef FBCON_HAS_ACCEL - display->scrollmode = SCROLL_YNOMOVE; - display->dispsw = &fbcon_accel; -#else - display->dispsw = &fbcon_dummy; -#endif - return; -} - -/** - * do_install_cmap - install the current colormap - * @con: virtual console number - * @info: generic frame buffer info structure - * - * Installs the current colormap for virtual console @con on - * device @info. - * - */ - -void do_install_cmap(int con, struct fb_info *info) -{ - if (con != info->currcon) - return; - if (fb_display[con].cmap.len) - fb_set_cmap(&fb_display[con].cmap, 1, info); - else { - int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256; - fb_set_cmap(fb_default_cmap(size), 1, info); - } -} - -int gen_update_var(int con, struct fb_info *info) -{ - struct display *disp = (con < 0) ? info->disp : (fb_display + con); - int err; - - if (con == info->currcon) { - info->var.xoffset = disp->var.xoffset; - info->var.yoffset = disp->var.yoffset; - info->var.vmode = disp->var.vmode; - if (info->fbops->fb_pan_display) { - if ((err = info->fbops->fb_pan_display(&info->var, con, info))) - return err; - } - } - return 0; -} - -int gen_switch(int con, struct fb_info *info) -{ - struct display *disp; - struct fb_cmap *cmap; - - if (info->currcon >= 0) { - disp = fb_display + info->currcon; - - /* - * Save the old colormap and graphics mode. - */ - disp->var = info->var; - if (disp->cmap.len) - fb_copy_cmap(&info->cmap, &disp->cmap, 0); - } - - info->currcon = con; - disp = fb_display + con; - - /* - * Install the new colormap and change the graphics mode. By default - * fbcon sets all the colormaps and graphics modes to the default - * values at bootup. - * - * Really, we want to set the colormap size depending on the - * depth of the new grpahics mode. For now, we leave it as its - * default 256 entry. - */ - if (disp->cmap.len) - cmap = &disp->cmap; - else - cmap = fb_default_cmap(1 << disp->var.bits_per_pixel); - - fb_copy_cmap(cmap, &info->cmap, 0); - - disp->var.activate = FB_ACTIVATE_NOW; - info->fbops->fb_set_var(&disp->var, con, info); - return 0; -} - -/** - * fbgen_blank - blank the screen - * @blank: boolean, 0 unblank, 1 blank - * @info: frame buffer info structure - * - * Blank the screen on device @info. - * - */ - -int fbgen_blank(int blank, struct fb_info *info) -{ - struct fb_cmap cmap; - u16 black[16]; - - if (info->fbops->fb_blank && !info->fbops->fb_blank(blank, info)) - return 0; - if (blank) { - memset(black, 0, 16*sizeof(u16)); - cmap.red = black; - cmap.green = black; - cmap.blue = black; - cmap.transp = NULL; - cmap.start = 0; - cmap.len = 16; - fb_set_cmap(&cmap, 1, info); - } else - do_install_cmap(info->currcon, info); - return 0; -} - -/* generic frame buffer operations */ -EXPORT_SYMBOL(gen_set_var); -EXPORT_SYMBOL(gen_get_cmap); -EXPORT_SYMBOL(gen_set_cmap); -EXPORT_SYMBOL(fbgen_pan_display); -/* helper functions */ -EXPORT_SYMBOL(do_install_cmap); -EXPORT_SYMBOL(gen_update_var); -EXPORT_SYMBOL(gen_switch); -EXPORT_SYMBOL(fbgen_blank); - -MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 9115118e9d77..27dc6417cddd 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -24,7 +24,6 @@ #include <linux/mm.h> #include <linux/mman.h> #include <linux/tty.h> -#include <linux/console.h> #include <linux/init.h> #include <linux/proc_fs.h> #ifdef CONFIG_KMOD @@ -42,8 +41,9 @@ #include <asm/pgtable.h> #include <linux/fb.h> -#include <video/fbcon.h> - +#ifdef CONFIG_FRAMEBUFFER_CONSOLE +#include "console/fbcon.h" +#endif /* * Frame buffer device initialization and setup routines */ @@ -130,9 +130,9 @@ extern int stifb_init(void); extern int stifb_setup(char*); extern int pmagbafb_init(void); extern int pmagbbfb_init(void); -extern void maxinefb_init(void); +extern int maxinefb_init(void); extern int tx3912fb_init(void); -extern void tx3912fb_setup(char*); +extern int tx3912fb_setup(char*); extern int radeonfb_init(void); extern int radeonfb_setup(char*); extern int e1355fb_init(void); @@ -356,11 +356,6 @@ static int num_pref_init_funcs __initdata = 0; struct fb_info *registered_fb[FB_MAX]; int num_registered_fb; -extern int fbcon_softback_size; - -static int first_fb_vc; -static int last_fb_vc = MAX_NR_CONSOLES-1; -static int fbcon_is_default = 1; #ifdef CONFIG_FB_OF static int ofonly __initdata = 0; @@ -376,8 +371,8 @@ static int fbmem_read_proc(char *buf, char **start, off_t offset, for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && len < 4000; fi++) if (*fi) clen += sprintf(buf + clen, "%d %s\n", - GET_FB_IDX((*fi)->node), - (*fi)->modename); + minor((*fi)->node), + (*fi)->fix.id); *start = buf + offset; if (clen > offset) clen -= offset; @@ -391,12 +386,15 @@ fb_read(struct file *file, char *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; struct inode *inode = file->f_dentry->d_inode; - int fbidx = GET_FB_IDX(inode->i_rdev); + int fbidx = minor(inode->i_rdev); struct fb_info *info = registered_fb[fbidx]; if (!info || ! info->screen_base) return -ENODEV; + if (info->fbops->fb_read) + return info->fbops->fb_read(file, buf, count, ppos); + if (p >= info->fix.smem_len) return 0; if (count >= info->fix.smem_len) @@ -420,13 +418,16 @@ fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; struct inode *inode = file->f_dentry->d_inode; - int fbidx = GET_FB_IDX(inode->i_rdev); + int fbidx = minor(inode->i_rdev); struct fb_info *info = registered_fb[fbidx]; int err; if (!info || !info->screen_base) return -ENODEV; + if (info->fbops->fb_write) + return info->fbops->fb_write(file, buf, count, ppos); + if (p > info->fix.smem_len) return -ENOSPC; if (count >= info->fix.smem_len) @@ -459,17 +460,91 @@ static void try_to_load(int fb) } #endif /* CONFIG_KMOD */ +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 || + 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; + } + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + if (var->vmode & FB_VMODE_YWRAP) + info->var.vmode |= FB_VMODE_YWRAP; + else + info->var.vmode &= ~FB_VMODE_YWRAP; + return 0; +} + +int fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + int err; + + if (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { + if (!info->fbops->fb_check_var) { + *var = info->var; + return 0; + } + + if ((err = info->fbops->fb_check_var(var, info))) + return err; + + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + info->var = *var; + + if (info->fbops->fb_set_par) + info->fbops->fb_set_par(info); + + fb_pan_display(&info->var, info); + + fb_set_cmap(&info->cmap, 1, info); + } + } + return 0; +} + +int +fb_blank(int blank, struct fb_info *info) +{ + u16 black[info->cmap.len]; + struct fb_cmap cmap; + + if (info->fbops->fb_blank && !info->fbops->fb_blank(blank, info)) + return 0; + if (blank) { + memset(black, 0, info->cmap.len * sizeof(u16)); + cmap.red = cmap.green = cmap.blue = black; + if (info->cmap.transp) + cmap.transp = black; + cmap.start = info->cmap.start; + cmap.len = info->cmap.len; + } else + cmap = info->cmap; + return fb_set_cmap(&cmap, 1, info); +} + static int fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int fbidx = GET_FB_IDX(inode->i_rdev); + int fbidx = minor(inode->i_rdev); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; - struct fb_cmap cmap; struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; +#ifdef CONFIG_FRAMEBUFFER_CONSOLE struct fb_con2fbmap con2fb; +#endif + struct fb_cmap cmap; int i; if (! fb) @@ -481,11 +556,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case FBIOPUT_VSCREENINFO: if (copy_from_user(&var, (void *) arg, sizeof(var))) return -EFAULT; - i = var.activate & FB_ACTIVATE_ALL - ? set_all_vcs(fbidx, fb, &var, info) - : fb->fb_set_var(&var, PROC_CONSOLE(info), info); - if (i) - return i; + i = fb_set_var(&var, info); + if (i) return i; if (copy_to_user((void *) arg, &var, sizeof(var))) return -EFAULT; return 0; @@ -494,21 +566,20 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case FBIOPUTCMAP: if (copy_from_user(&cmap, (void *) arg, sizeof(cmap))) return -EFAULT; - return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(info), info)); + return (fb_set_cmap(&cmap, 0, info)); case FBIOGETCMAP: if (copy_from_user(&cmap, (void *) arg, sizeof(cmap))) return -EFAULT; - return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(info), info)); + fb_copy_cmap(&info->cmap, &cmap, 0); case FBIOPAN_DISPLAY: if (copy_from_user(&var, (void *) arg, sizeof(var))) return -EFAULT; - if (fb->fb_pan_display == NULL) - return (var.xoffset || var.yoffset) ? -EINVAL : 0; - if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(info), info))) + if ((i = fb_pan_display(&var, info))) return i; if (copy_to_user((void *) arg, &var, sizeof(var))) return -EFAULT; return i; +#ifdef CONFIG_FRAMEBUFFER_CONSOLE case FBIOGET_CON2FBMAP: if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb))) return -EFAULT; @@ -537,22 +608,20 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, for (i = 0; i < MAX_NR_CONSOLES; i++) set_con2fb_map(i, con2fb.framebuffer); return 0; +#endif /* CONFIG_FRAMEBUFFER_CONSOLE */ case FBIOBLANK: - if (fb->fb_blank == NULL) - return -EINVAL; - return fb->fb_blank(arg, info); + return fb_blank(arg, info); default: if (fb->fb_ioctl == NULL) return -EINVAL; - return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(info), - info); + return fb->fb_ioctl(inode, file, cmd, arg, info); } } static int fb_mmap(struct file *file, struct vm_area_struct * vma) { - int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev); + int fbidx = minor(file->f_dentry->d_inode->i_rdev); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; unsigned long off; @@ -648,28 +717,10 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) #endif /* !sparc32 */ } -#if 1 /* to go away in 2.5.0 */ -int GET_FB_IDX(kdev_t rdev) -{ - int fbidx = minor(rdev); - if (fbidx >= 32) { - int newfbidx = fbidx >> 5; - static int warned; - if (!(warned & (1<<newfbidx))) { - warned |= 1<<newfbidx; - printk("Warning: Remapping obsolete /dev/fb* minor %d to %d\n", - fbidx, newfbidx); - } - fbidx = newfbidx; - } - return fbidx; -} -#endif - static int fb_open(struct inode *inode, struct file *file) { - int fbidx = GET_FB_IDX(inode->i_rdev); + int fbidx = minor(inode->i_rdev); struct fb_info *info; int res = 0; @@ -679,12 +730,12 @@ fb_open(struct inode *inode, struct file *file) #endif /* CONFIG_KMOD */ if (!(info = registered_fb[fbidx])) return -ENODEV; - if (info->fbops->owner) - __MOD_INC_USE_COUNT(info->fbops->owner); + if (!try_module_get(info->fbops->owner)) + return -ENODEV; if (info->fbops->fb_open) { res = info->fbops->fb_open(info,1); - if (res && info->fbops->owner) - __MOD_DEC_USE_COUNT(info->fbops->owner); + if (res) + module_put(info->fbops->owner); } return res; } @@ -692,15 +743,14 @@ fb_open(struct inode *inode, struct file *file) static int fb_release(struct inode *inode, struct file *file) { - int fbidx = GET_FB_IDX(inode->i_rdev); + int fbidx = minor(inode->i_rdev); struct fb_info *info; lock_kernel(); info = registered_fb[fbidx]; if (info->fbops->fb_release) info->fbops->fb_release(info,1); - if (info->fbops->owner) - __MOD_DEC_USE_COUNT(info->fbops->owner); + module_put(info->fbops->owner); unlock_kernel(); return 0; } @@ -731,10 +781,8 @@ static struct file_operations fb_fops = { int register_framebuffer(struct fb_info *fb_info) { - int i, j; char name_buf[12]; - static int fb_ever_opened[FB_MAX]; - static int first = 1; + int i; if (num_registered_fb == FB_MAX) return -ENXIO; @@ -744,35 +792,10 @@ register_framebuffer(struct fb_info *fb_info) break; fb_info->node = mk_kdev(FB_MAJOR, i); registered_fb[i] = fb_info; - if (!fb_ever_opened[i]) { - struct module *owner = fb_info->fbops->owner; - /* - * We assume initial frame buffer devices can be opened this - * many times - */ - for (j = 0; j < MAX_NR_CONSOLES; j++) - if (con2fb_map[j] == i) { - if (owner) - __MOD_INC_USE_COUNT(owner); - if (!fb_info->fbops->fb_open) - continue; - if (!fb_info->fbops->fb_open(fb_info,0)) - continue; - if (owner) - __MOD_DEC_USE_COUNT(owner); - } - fb_ever_opened[i] = 1; - } - - if (first) { - first = 0; - take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); - } - sprintf (name_buf, "fb/%d", i); + sprintf(name_buf, "fb/%d", i); devfs_register(NULL, name_buf, DEVFS_FL_DEFAULT, - FB_MAJOR, i, S_IFCHR | S_IRUGO | S_IWUGO, - &fb_fops, NULL); - + FB_MAJOR, i, S_IFCHR | S_IRUGO | S_IWUGO, + &fb_fops, NULL); return 0; } @@ -790,12 +813,9 @@ register_framebuffer(struct fb_info *fb_info) int unregister_framebuffer(struct fb_info *fb_info) { - int i, j; + int i; - i = GET_FB_IDX(fb_info->node); - for (j = 0; j < MAX_NR_CONSOLES; j++) - if (con2fb_map[j] == i) - return -EBUSY; + i = minor(fb_info->node); if (!registered_fb[i]) return -EINVAL; devfs_remove("fb/%d", i); @@ -821,7 +841,7 @@ fbmem_init(void) create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL); - devfs_mk_dir (NULL, "fb", NULL); + devfs_mk_dir(NULL, "fb", NULL); if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) printk("unable to get major %d for fb devs\n", FB_MAJOR); @@ -862,44 +882,7 @@ int __init video_setup(char *options) if (!options || !*options) return 0; - - if (!strncmp(options, "scrollback:", 11)) { - options += 11; - if (*options) { - fbcon_softback_size = simple_strtoul(options, &options, 0); - if (*options == 'k' || *options == 'K') { - fbcon_softback_size *= 1024; - options++; - } - if (*options != ',') - return 0; - options++; - } else - return 0; - } - - if (!strncmp(options, "map:", 4)) { - options += 4; - if (*options) - for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) { - if (!options[j]) - j = 0; - con2fb_map[i] = (options[j++]-'0') % FB_MAX; - } - return 0; - } - - if (!strncmp(options, "vc:", 3)) { - options += 3; - if (*options) - first_fb_vc = simple_strtoul(options, &options, 10) - 1; - if (first_fb_vc < 0) - first_fb_vc = 0; - if (*options++ == '-') - last_fb_vc = simple_strtoul(options, &options, 10) - 1; - fbcon_is_default = 0; - } - + #ifdef CONFIG_FB_OF if (!strcmp(options, "ofonly")) { ofonly = 1; @@ -947,8 +930,5 @@ EXPORT_SYMBOL(register_framebuffer); EXPORT_SYMBOL(unregister_framebuffer); EXPORT_SYMBOL(registered_fb); EXPORT_SYMBOL(num_registered_fb); -#if 1 /* to go away in 2.5.0 */ -EXPORT_SYMBOL(GET_FB_IDX); -#endif MODULE_LICENSE("GPL"); diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 05ed2f341c12..4ce6d78cd212 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -21,8 +21,6 @@ #include <linux/zorro.h> #include <asm/io.h> -#include <video/fbcon.h> - /* * Some technical notes: * @@ -133,7 +131,6 @@ static volatile unsigned char *fm2fb_reg; static struct fb_info fb_info; static u32 pseudo_palette[17]; -static struct display display; static struct fb_fix_screeninfo fb_fix __initdata = { .smem_len = FRAMEMASTER_REG, @@ -176,14 +173,12 @@ static int fm2fb_blank(int blank, struct fb_info *info); static struct fb_ops fm2fb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = fm2fb_setcolreg, .fb_blank = fm2fb_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; /* @@ -264,7 +259,6 @@ int __init fm2fb_init(void) if (fm2fb_mode == -1) fm2fb_mode = FM2FB_MODE_PAL; - strcpy(fb_info.modename, fb_fix.id); fb_info.node = NODEV; fb_info.fbops = &fm2fb_ops; fb_info.var = fb_var_modes[fm2fb_mode]; @@ -274,19 +268,12 @@ int __init fm2fb_init(void) fb_info.flags = FBINFO_FLAG_DEFAULT; /* The below feilds will go away !!!! */ - fb_info.currcon = -1; - strcpy(fb_info.modename, fb_info.fix.id); - fb_info.disp = &display; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_alloc_cmap(&fb_info.cmap, 16, 0); - gen_set_disp(-1, &fb_info); - if (register_framebuffer(&fb_info) < 0) return -EINVAL; - printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), fb_fix.id); + printk("fb%d: %s frame buffer device\n", minor(fb_info.node), fb_fix.id); return 0; } return -ENXIO; diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index 6ee7d7d0fe1c..2e37b7d58852 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c @@ -31,8 +31,6 @@ #include <asm/io.h> #include <asm/jazz.h> -#include <video/fbcon.h> - /* * Various defines for the G364 */ @@ -74,34 +72,33 @@ #define MON_ID_REG 0xe4100000 /* unused */ #define RESET_REG 0xe4180000 /* Write only */ -static struct display disp; static struct fb_info fb_info; static struct fb_fix_screeninfo fb_fix __initdata = { - .id = "G364 8plane", - .smem_start = 0x40000000, /* physical address */ - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_PSEUDOCOLOR, - .ypanstep = 1, - .accel = FB_ACCEL_NONE, + .id = "G364 8plane", + .smem_start = 0x40000000, /* physical address */ + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .ypanstep = 1, + .accel = FB_ACCEL_NONE, }; static struct fb_var_screeninfo fb_var __initdata = { - .bits_per_pixel =8, - .red = { 0, 8, 0 }, - green: { 0, 8, 0 }, - blue: { 0, 8, 0 }, - activate:FB_ACTIVATE_NOW, - height: -1, - width: -1, - pixclock:39722, - left_margin: 40, - right_margin: 24, - upper_margin: 32, - lower_margin: 11, - hsync_len: 96, - vsync_len: 2, - vmode: FB_VMODE_NONINTERLACED, + .bits_per_pixel = 8, + .red = { 0, 8, 0 }, + .green = { 0, 8, 0 }, + .blue = { 0, 8, 0 }, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .pixclock = 39722, + .left_margin = 40, + .right_margin = 24, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 96, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED, }; /* @@ -109,29 +106,29 @@ static struct fb_var_screeninfo fb_var __initdata = { */ int g364fb_init(void); -static int g364fb_pan_display(struct fb_var_screeninfo *var, int con, +static int g364fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static int g364fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); +static int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor); static int g364fb_blank(int blank, struct fb_info *info); static struct fb_ops g364fb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = g364fb_setcolreg, .fb_pan_display = g364fb_pan_display, .fb_blank = g364fb_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = g364fb_cursor, }; -void fbcon_g364fb_cursor(struct display *p, int mode, int x, int y) +int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { - switch (mode) { + + switch (cursor->enable) { case CM_ERASE: *(unsigned int *) CTLA_REG |= CURS_TOGGLE; break; @@ -141,9 +138,10 @@ void fbcon_g364fb_cursor(struct display *p, int mode, int x, int y) *(unsigned int *) CTLA_REG &= ~CURS_TOGGLE; *(unsigned int *) CURS_POS_REG = ((x * fontwidth(p)) << 12) | ((y * fontheight(p)) - - p->var.yoffset); + info->var.yoffset); break; } + return 0; } /* @@ -151,7 +149,7 @@ void fbcon_g364fb_cursor(struct display *p, int mode, int x, int y) * * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int g364fb_pan_display(struct fb_var_screeninfo *var, int con, +static int g364fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { if (var->xoffset || var->yoffset + var->yres > var->yres_virtual) @@ -239,7 +237,6 @@ int __init g364fb_init(void) fb_fix.smem_len = (1 << (mem * 2)) * 512 * 1024; fb_var.yres_virtual = fb_fix.smem_len / fb_var.xres; - strcpy(fb_info.modename, fb_fix.id); fb_info.node = NODEV; fb_info.fbops = &g364fb_ops; fb_info.screen_base = (char *) G364_MEM_BASE; /* virtual kernel address */ @@ -247,21 +244,10 @@ int __init g364fb_init(void) fb_info.fix = fb_fix; fb_info.flags = FBINFO_FLAG_DEFAULT; - fb_info.disp = &disp; - fb_info.currcon = -1; - fb_info.fontname[0] = '\0'; - fb_info.changevar = NULL; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; - fb_alloc_cmap(&fb_info.cmap, 255, 0); - gen_set_disp(-1, &fb_info); if (register_framebuffer(&fb_info) < 0) return -EINVAL; - - printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), - fb_info.fix.id); return 0; } diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index c4e3f35c9124..54f70f95ff07 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c @@ -7,6 +7,8 @@ * * History: * + * - Revision 0.1.8 (23 Oct 2002): Ported to new framebuffer api. + * * - Revision 0.1.7 (23 Jan 2001): fix crash resulting from MDA only cards * being detected as Hercules. (Paul G.) * - Revision 0.1.6 (17 Aug 2000): new style structs @@ -18,8 +20,6 @@ * - Revision 0.1.3 (22 Jan 2000): modified for the new fb_info structure * screen is cleared after rmmod * virtual resolutions - * kernel parameter 'video=hga:font:{fontname}' - * module parameter 'font={fontname}' * module parameter 'nologo={0|1}' * the most important: boot logo :) * - Revision 0.1.0 (6 Dec 1999): faster scrolling and minor fixes @@ -44,16 +44,10 @@ #include <linux/ioport.h> #include <asm/io.h> #include <asm/vga.h> -#include <video/fbcon.h> -#include <video/fbcon-hga.h> - -#ifdef MODULE #define INCLUDE_LINUX_LOGO_DATA #include <linux/linux_logo.h> -#endif /* MODULE */ - #if 0 #define DPRINTK(args...) printk(KERN_DEBUG __FILE__": " ##args) #else @@ -71,9 +65,15 @@ static unsigned long hga_vram_base; /* Base of video memory */ static unsigned long hga_vram_len; /* Size of video memory */ +#define HGA_ROWADDR(row) ((row%4)*8192 + (row>>2)*90) #define HGA_TXT 0 #define HGA_GFX 1 +static inline u8* rowaddr(struct fb_info *info, u_int row) +{ + return info->screen_base + HGA_ROWADDR(row); +} + static int hga_mode = -1; /* 0 = txt, 1 = gfx mode */ static enum { TYPE_HERC, TYPE_HERCPLUS, TYPE_HERCCOLOR } hga_type; @@ -111,58 +111,35 @@ static spinlock_t hga_reg_lock = SPIN_LOCK_UNLOCKED; /* Framebuffer driver structures */ static struct fb_var_screeninfo hga_default_var = { - .xres = 720, - .yres = 348, - .xres_virtual = 720, - .yres_virtual = 348, - .xoffset = 0, - .yoffset = 0, - .bits_per_pixel =1, - .grayscale = 0, - .red = {0, 1, 0}, - .green = {0, 1, 0}, - .blue = {0, 1, 0}, - .transp = {0, 0, 0}, - .nonstd = 0, /* (FB_NONSTD_HGA ?) */ - .activate = 0, - .height = -1, - .width = -1, - .accel_flags = 0, - /* pixclock */ - /* left_margin, right_margin */ - /* upper_margin, lower_margin */ - /* hsync_len, vsync_len */ - /* sync */ - /* vmode */ + .xres = 720, + .yres = 348, + .xres_virtual = 720, + .yres_virtual = 348, + .bits_per_pixel = 1, + .red = {0, 1, 0}, + .green = {0, 1, 0}, + .blue = {0, 1, 0}, + .transp = {0, 0, 0}, + .height = -1, + .width = -1, }; static struct fb_fix_screeninfo hga_fix = { - .id = "HGA", - .smem_start = (unsigned long) NULL, - .smem_len = 0, - .type = FB_TYPE_PACKED_PIXELS, /* (not sure) */ - .type_aux = 0, /* (not sure) */ - .visual = FB_VISUAL_MONO10, - .xpanstep = 8, - .ypanstep = 8, - .ywrapstep = 0, - .line_length = 90, - .mmio_start = 0, - .mmio_len = 0, - .accel = FB_ACCEL_NONE + .id = "HGA", + .type = FB_TYPE_PACKED_PIXELS, /* (not sure) */ + .visual = FB_VISUAL_MONO10, + .xpanstep = 8, + .ypanstep = 8, + .line_length = 90, + .accel = FB_ACCEL_NONE }; static struct fb_info fb_info; -static struct display disp; /* Don't assume that tty1 will be the initial current console. */ static int release_io_port = 0; static int release_io_ports = 0; - -#ifdef MODULE -static char *font = NULL; static int nologo = 0; -#endif /* ------------------------------------------------------------------------- * @@ -205,8 +182,6 @@ static void hga_clear_screen(void) isa_memset_io(hga_vram_base, fillchar, hga_vram_len); } - -#ifdef MODULE static void hga_txt_mode(void) { unsigned long flags; @@ -237,7 +212,6 @@ static void hga_txt_mode(void) hga_mode = HGA_TXT; spin_unlock_irqrestore(&hga_reg_lock, flags); } -#endif /* MODULE */ static void hga_gfx_mode(void) { @@ -270,18 +244,16 @@ static void hga_gfx_mode(void) spin_unlock_irqrestore(&hga_reg_lock, flags); } -#ifdef MODULE -static void hga_show_logo(void) +static void hga_show_logo(struct fb_info *info) { - int x, y; unsigned long dest = hga_vram_base; char *logo = linux_logo_bw; + int x, y; + for (y = 134; y < 134 + 80 ; y++) /* this needs some cleanup */ for (x = 0; x < 10 ; x++) - isa_writeb(~*(logo++), - (dest + (y%4)*8192 + (y>>2)*90 + x + 40)); + isa_writeb(~*(logo++),(dest + HGA_ROWADDR(y) + x + 40)); } -#endif /* MODULE */ static void hga_pan(unsigned int xoffset, unsigned int yoffset) { @@ -380,98 +352,34 @@ static int __init hga_card_detect(void) return 1; } -/* ------------------------------------------------------------------------- * - * - * dispsw functions - * - * ------------------------------------------------------------------------- */ - /** - * hga_set_var - set the user defined part of the display - * @var:new video mode - * @con:unused + * hgafb_open - open the framebuffer device * @info:pointer to fb_info object containing info for current hga board - * - * This function is called for changing video modes. Since HGA cards have - * only one fixed mode we have not much to do. After checking input - * parameters @var is copied to @info->var and @info->changevar is called. - * A zero is returned on success and %-EINVAL for failure. - * - * FIXME: - * This is the most mystical function (at least for me). - * What is the exact specification of xxx_set_var()? - * Should it handle xoffset, yoffset? Should it do panning? - * What does vmode mean? + * @int:open by console system or userland. */ -int hga_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +static int hgafb_open(struct fb_info *info, int init) { - CHKINFO(-EINVAL); - DPRINTK("hga_set_var: con:%d, activate:%x, info:0x%x, fb_info:%x\n", con, var->activate, (unsigned)info, (unsigned)&fb_info); - - if (var->xres != 720 || var->yres != 348 || - var->xres_virtual != 720 || - var->yres_virtual < 348 || var->yres_virtual > 348 + 16 || - var->bits_per_pixel != 1 || var->grayscale != 0) { - return -EINVAL; - } - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { - info->var = *var; - if (info->changevar) - (*info->changevar)(con); - } + hga_gfx_mode(); + hga_clear_screen(); + if (!nologo) hga_show_logo(info); return 0; } /** - * hga_getcolreg - read color registers - * @regno:register index to read out - * @red:red value - * @green:green value - * @blue:blue value - * @transp:transparency value - * @info:unused - * - * This callback function is used to read the color registers of a HGA - * board. Since we have only two fixed colors, RGB values are 0x0000 - * for register0 and 0xaaaa for register1. - * A zero is returned on success and 1 for failure. + * hgafb_open - open the framebuffer device + * @info:pointer to fb_info object containing info for current hga board + * @int:open by console system or userland. */ -static int hga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp, struct fb_info *info) +static int hgafb_release(struct fb_info *info, int init) { - if (regno == 0) { - *red = *green = *blue = 0x0000; - *transp = 0; - } else if (regno == 1) { - *red = *green = *blue = 0xaaaa; - *transp = 0; - } else - return 1; + hga_txt_mode(); + hga_clear_screen(); return 0; } /** - * hga_get_cmap - get the colormap - * @cmap:struct fb_cmap to fill in - * @kspc:called from kernel space? - * @con:unused - * @info:pointer to fb_info object containing info for current hga board - * - * This wrapper function passes it's input parameters to fb_get_cmap(). - * Callback function hga_getcolreg() is used to read the color registers. - */ - -int hga_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) -{ - CHKINFO(-EINVAL); - DPRINTK("hga_get_cmap: con:%d\n", con); - return fb_get_cmap(cmap, kspc, hga_getcolreg, info); -} - -/** * hgafb_setcolreg - set color registers * @regno:register index to set * @red:red value, unused @@ -496,7 +404,6 @@ static int hgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, /** * hga_pan_display - pan or wrap the display * @var:contains new xoffset, yoffset and vmode values - * @con:unused * @info:pointer to fb_info object containing info for current hga board * * This function looks only at xoffset, yoffset and the %FB_VMODE_YWRAP @@ -505,12 +412,8 @@ static int hgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, * A zero is returned on success and %-EINVAL for failure. */ -int hga_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *info) +int hgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - CHKINFO(-EINVAL); - DPRINTK("pan_disp: con:%d, wrap:%d, xoff:%d, yoff:%d\n", con, var->vmode & FB_VMODE_YWRAP, var->xoffset, var->yoffset); - if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual || @@ -524,13 +427,6 @@ int hga_pan_display(struct fb_var_screeninfo *var, int con, } hga_pan(var->xoffset, var->yoffset); - - info->var.xoffset = var->xoffset; - info->var.yoffset = var->yoffset; - if (var->vmode & FB_VMODE_YWRAP) - info->var.vmode |= FB_VMODE_YWRAP; - else - info->var.vmode &= ~FB_VMODE_YWRAP; return 0; } @@ -549,93 +445,92 @@ int hga_pan_display(struct fb_var_screeninfo *var, int con, static int hgafb_blank(int blank_mode, struct fb_info *info) { - CHKINFO( ); - DPRINTK("hgafb_blank: blank_mode:%d, info:%x, fb_info:%x\n", blank_mode, (unsigned)info, (unsigned)&fb_info); - hga_blank(blank_mode); return 0; } +static void hgafb_fillrect(struct fb_info *info, struct fb_fillrect *rect) +{ + u_int rows, y; + u8 *dest; + + y = rect->dy; + + for (rows = rect->height; rows--; y++) { + dest = rowaddr(info, y) + (rect->dx >> 3); + switch (rect->rop) { + case ROP_COPY: + //fb_memset(dest, rect->color, (rect->width >> 3)); + break; + case ROP_XOR: + *dest = ~*dest; + break; + } + } +} + +static void hgafb_copyarea(struct fb_info *info, struct fb_copyarea *area) +{ + u_int rows, y1, y2; + u8 *src, *dest; + + if (area->dy <= area->sy) { + y1 = area->sy; + y2 = area->dy; + + for (rows = area->height; rows--; ) { + src = rowaddr(info, y1) + (area->sx >> 3); + dest = rowaddr(info, y2) + (area->dx >> 3); + //fb_memmove(dest, src, (area->width >> 3)); + y1++; + y2++; + } + } else { + y1 = area->sy + area->height - 1; + y2 = area->dy + area->height - 1; + + for (rows = area->height; rows--;) { + src = rowaddr(info, y1) + (area->sx >> 3); + dest = rowaddr(info, y2) + (area->dx >> 3); + //fb_memmove(dest, src, (area->width >> 3)); + y1--; + y2--; + } + } +} + +static void hgafb_imageblit(struct fb_info *info, struct fb_image *image) +{ + u8 *dest, *cdat = image->data; + u_int rows, y = image->dy; + u8 d; + + for (rows = image->height; rows--; y++) { + d = *cdat++; + dest = rowaddr(info, y) + (image->dx >> 3); + *dest = d; + } +} + + static struct fb_ops hgafb_ops = { .owner = THIS_MODULE, - .fb_set_var = hga_set_var, - .fb_get_cmap = hga_get_cmap, - .fb_set_cmap = gen_set_cmap, + .fb_open = hgafb_open, + .fb_release = hgafb_release, .fb_setcolreg = hgafb_setcolreg, - .fb_pan_display = hga_pan_display, + .fb_pan_display = hgafb_pan_display, .fb_blank = hgafb_blank, + .fb_fillrect = cfb_fillrect, //hgafb_fillrect, + .fb_copyarea = cfb_copyarea, //hgafb_copyarea, + .fb_imageblit = cfb_imageblit,//hgafb_imageblit, }; - /* ------------------------------------------------------------------------- * * * Functions in fb_info * * ------------------------------------------------------------------------- */ -/** - * hgafbcon_switch - switch console - * @con:new console to switch to - * @info:pointer to fb_info object containing info for current hga board - * - * This function should install a new colormap and change the video mode. - * Since we have fixed colors and only one video mode we have nothing to - * do. - * Only console administration is done but it should go to fbcon.c IMHO. - * A zero is returned on success and %-EINVAL for failure. - */ - -static int hgafbcon_switch(int con, struct fb_info *info) -{ - CHKINFO(-EINVAL); - DPRINTK("hgafbcon_switch: currcon:%d, con:%d, info:%x, fb_info:%x\n", info->currcon, con, (unsigned)info, (unsigned)&fb_info); - - /* Save the colormap and video mode */ -#if 0 /* Not necessary in hgafb, we use fixed colormap */ - fb_copy_cmap(&info->cmap, &fb_display[info->currcon].cmap, 0); -#endif - - if (info->currcon != -1) /* this check is absolute necessary! */ - memcpy(&fb_display[info->currcon].var, &info->var, - sizeof(struct fb_var_screeninfo)); - - /* Install a new colormap and change the video mode. By default fbcon - * sets all the colormaps and video modes to the default values at - * bootup. - */ -#if 0 - fb_copy_cmap(&fb_display[con].cmap, &info->cmap, 0); - fb_set_cmap(&info->cmap, 1, info); -#endif - - memcpy(&info->var, &fb_display[con].var, - sizeof(struct fb_var_screeninfo)); - /* hga_set_var(&info->var, con, &fb_info); is it necessary? */ - info->currcon = con; - - /* Hack to work correctly with XF86_Mono */ - hga_gfx_mode(); - return 0; -} - -/** - * hgafbcon_updatevar - update the user defined part of the display - * @con:console to update or -1 when no consoles defined on this fb - * @info:pointer to fb_info object containing info for current hga board - * - * This function is called when @var is changed by fbcon.c without calling - * hga_set_var(). It usually means scrolling. hga_pan_display() is called - * to update the hardware and @info->var. - * A zero is returned on success and %-EINVAL for failure. - */ - -static int hgafbcon_updatevar(int con, struct fb_info *info) -{ - CHKINFO(-EINVAL); - DPRINTK("hga_update_var: con:%d, info:%x, fb_info:%x\n", con, (unsigned)info, (unsigned)&fb_info); - return (con < 0) ? -EINVAL : hga_pan_display(&fb_display[con].var, con, info); -} - /* ------------------------------------------------------------------------- */ /* @@ -652,35 +547,9 @@ int __init hgafb_init(void) printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n", hga_type_name, hga_vram_len/1024); - hga_gfx_mode(); - hga_clear_screen(); -#ifdef MODULE - if (!nologo) hga_show_logo(); -#endif /* MODULE */ - hga_fix.smem_start = VGA_MAP_MEM(hga_vram_base); hga_fix.smem_len = hga_vram_len; - disp.var = hga_default_var; - disp.visual = hga_fix.visual; - disp.type = hga_fix.type; - disp.type_aux = hga_fix.type_aux; - disp.ypanstep = hga_fix.ypanstep; - disp.ywrapstep = hga_fix.ywrapstep; - disp.line_length = hga_fix.line_length; - disp.can_soft_blank = 1; - disp.inverse = 0; -#ifdef FBCON_HAS_HGA - disp.dispsw = &fbcon_hga; -#else -#warning HGAFB will not work as a console! - disp.dispsw = &fbcon_dummy; -#endif - disp.dispsw_data = NULL; - - disp.scrollmode = SCROLL_YREDRAW; - - strcpy (fb_info.modename, hga_fix.id); fb_info.node = NODEV; fb_info.flags = FBINFO_FLAG_DEFAULT; fb_info.var = hga_default_var; @@ -692,20 +561,12 @@ int __init hgafb_init(void) fb_info.monspecs.dpms = 0; fb_info.fbops = &hgafb_ops; fb_info.screen_base = (char *)hga_fix.smem_start; - fb_info.disp = &disp; - fb_info.currcon = 1; - fb_info.changevar = NULL; - fb_info.switch_con = hgafbcon_switch; - fb_info.updatevar = hgafbcon_updatevar; - fb_info.pseudo_palette = NULL; /* ??? */ - fb_info.par = NULL; if (register_framebuffer(&fb_info) < 0) return -EINVAL; printk(KERN_INFO "fb%d: %s frame buffer device\n", - GET_FB_IDX(fb_info.node), fb_info.modename); - + minor(fb_info.node), fb_info.fix.id); return 0; } @@ -713,49 +574,21 @@ int __init hgafb_init(void) * Setup */ -#ifndef MODULE int __init hgafb_setup(char *options) { - /* - * Parse user speficied options - * `video=hga:font:VGA8x16' or - * `video=hga:font:SUN8x16' recommended - * Other supported fonts: VGA8x8, Acorn8x8, PEARL8x8 - * More different fonts can be used with the `setfont' utility. - */ - - char *this_opt; - - fb_info.fontname[0] = '\0'; - - if (!options || !*options) - return 0; - - while ((this_opt = strsep(&options, ","))) { - if (!strncmp(this_opt, "font:", 5)) - strcpy(fb_info.fontname, this_opt+5); - } return 0; } -#endif /* !MODULE */ - - - /* - * Cleanup - */ #ifdef MODULE -static void hgafb_cleanup(struct fb_info *info) +static void __exit hgafb_exit(void) { hga_txt_mode(); hga_clear_screen(); - unregister_framebuffer(info); + unregister_framebuffer(&fb_info); if (release_io_ports) release_region(0x3b0, 12); if (release_io_port) release_region(0x3bf, 1); } -#endif /* MODULE */ - - +#endif /* ------------------------------------------------------------------------- * @@ -763,29 +596,14 @@ static void hgafb_cleanup(struct fb_info *info) * * ------------------------------------------------------------------------- */ -#ifdef MODULE -int init_module(void) -{ - if (font) - strncpy(fb_info.fontname, font, sizeof(fb_info.fontname)-1); - else - fb_info.fontname[0] = '\0'; - - return hgafb_init(); -} - -void cleanup_module(void) -{ - hgafb_cleanup(&fb_info); -} - MODULE_AUTHOR("Ferenc Bakonyi (fero@drama.obuda.kando.hu)"); MODULE_DESCRIPTION("FBDev driver for Hercules Graphics Adaptor"); MODULE_LICENSE("GPL"); -MODULE_PARM(font, "s"); -MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (VGA8x8, VGA8x16, SUN8x16, Acorn8x8, PEARL8x8) (default=none)"); MODULE_PARM(nologo, "i"); MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)"); -#endif /* MODULE */ +#ifdef MODULE +module_init(hgafb_init); +module_exit(hgafb_exit); +#endif diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index a18844098a6c..2fd15b181731 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -29,8 +29,6 @@ #include <asm/io.h> #include <asm/hd64461.h> -#include <video/fbcon.h> - static struct fb_var_screeninfo hitfb_var __initdata = { .activate = FB_ACTIVATE_NOW, .height = -1, @@ -46,7 +44,6 @@ static struct fb_fix_screeninfo hitfb_fix __initdata = { }; static u16 pseudo_palette[17]; -static struct display display; struct fb_info fb_info; static int hitfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) @@ -125,15 +122,13 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green, static struct fb_ops hitfb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_check_var = hitfb_check_var, .fb_set_par = hitfb_set_par, .fb_setcolreg = hitfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; int __init hitfb_init(void) @@ -167,24 +162,16 @@ int __init hitfb_init(void) fb_info.pseudo_palette = pseudo_palette; fb_info.flags = FBINFO_FLAG_DEFAULT; - strcpy(fb_info.modename, fb_info.fix.id); - fb_info.currcon = -1; - fb_info.disp = &display; - fb_info.changevar = NULL; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_info.screen_base = (void *) hitfb_fix.smem_start; size = (fb_info.var.bits_per_pixel == 8) ? 256 : 16; fb_alloc_cmap(&fb_info.cmap, size, 0); - gen_set_var(&fb_info.var, -1, &fb_info); - if (register_framebuffer(&fb_info) < 0) return -EINVAL; printk(KERN_INFO "fb%d: %s frame buffer device\n", - GET_FB_IDX(fb_info.node), fb_info.fix.id); + minor(fb_info.node), fb_info.fix.id); return 0; } diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index e3fed03b4445..595a226a56f3 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -19,8 +19,6 @@ #include <asm/blinken.h> #include <asm/hwtest.h> -#include <video/fbcon.h> - static struct fb_info fb_info; unsigned long fb_regs; @@ -67,8 +65,6 @@ static struct fb_var_screeninfo hpfb_defined = { .vmode = FB_VMODE_NONINTERLACED, }; -static struct display display; - /* * Set the palette. This may not work on all boards but only experimentation * will tell. @@ -105,13 +101,11 @@ void hpfb_copyarea(struct fb_info *info, struct fb_copyarea *area) static struct fb_ops hpfb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = hpfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = hpfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; #define TOPCAT_FBOMSB 0x5d @@ -163,16 +157,8 @@ int __init hpfb_init_one(unsigned long base) fb_info.fix = hpfb_fix; fb_info.screen_base = (char *)hpfb_fix.smem_start; // FIXME - /* The below feilds will go away !!!! */ - fb_info.currcon = -1; - strcpy(fb_info.modename, fb_info.fix.id); - fb_info.disp = &display; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_alloc_cmap(&fb_info.cmap, 256, 0); - gen_set_disp(-1, &fb_info); - if (register_framebuffer(&fb_info) < 0) return 1; return 0; diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index a906dcbee668..f72ab497c041 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -39,13 +39,9 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/fb.h> -#include <linux/selection.h> -#include <linux/console.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/nvram.h> -#include <linux/kd.h> -#include <linux/vt_kern.h> #include <asm/io.h> @@ -54,16 +50,7 @@ #include <asm/pcic.h> #endif -#include <video/fbcon.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-cfb24.h> -#include <video/fbcon-cfb32.h> - -#include "iga.h" - -static char igafb_name[16] = "IGA 1682"; -static char fontname[40] __initdata = { 0 }; +#include <video/iga.h> struct pci_mmap_map { unsigned long voff; @@ -73,35 +60,18 @@ struct pci_mmap_map { unsigned long prot_mask; }; -struct fb_info_iga { - struct fb_info fb_info; - unsigned long frame_buffer_phys; - char *frame_buffer; - unsigned long io_base_phys; - unsigned long io_base; - u32 total_vram; - struct pci_mmap_map *mmap_map; - struct { u_short blue, green, red, pad; } palette[256]; - int video_cmap_len; - struct display disp; - struct display_switch dispsw; - union { -#ifdef FBCON_HAS_CFB16 - u16 cfb16[16]; -#endif -#ifdef FBCON_HAS_CFB24 - u32 cfb24[16]; -#endif -#ifdef FBCON_HAS_CFB32 - u32 cfb32[16]; -#endif - } fbcon_cmap; -#ifdef __sparc__ - u8 open; - u8 mmaped; - int vtconsole; - int consolecnt; -#endif +struct iga_par { + struct pci_mmap_map *mmap_map; + unsigned long frame_buffer_phys; + unsigned long io_base; +}; + +struct fb_info fb_info; + +struct fb_fix_screeninfo igafb_fix __initdata = { + .id = "IGA 1682", + .type = FB_TYPE_PACKED_PIXELS; + .mmio_len = 1000; }; struct fb_var_screeninfo default_var = { @@ -142,21 +112,21 @@ struct fb_var_screeninfo default_var_1280x1024 __initdata = { * * On sparc we happen to access I/O with memory mapped functions too. */ -#define pci_inb(info, reg) readb(info->io_base+(reg)) -#define pci_outb(info, val, reg) writeb(val, info->io_base+(reg)) +#define pci_inb(par, reg) readb(par->io_base+(reg)) +#define pci_outb(par, val, reg) writeb(val, par->io_base+(reg)) -static inline unsigned int iga_inb(struct fb_info_iga *info, - unsigned int reg, unsigned int idx ) +static inline unsigned int iga_inb(struct iga_par *par, unsigned int reg, + unsigned int idx) { - pci_outb(info, idx, reg); - return pci_inb(info, reg + 1); + pci_outb(par, idx, reg); + return pci_inb(par, reg + 1); } -static inline void iga_outb(struct fb_info_iga *info, unsigned char val, +static inline void iga_outb(struct iga_par *par, unsigned char val, unsigned int reg, unsigned int idx ) { - pci_outb(info, idx, reg); - pci_outb(info, val, reg+1); + pci_outb(par, idx, reg); + pci_outb(par, val, reg+1); } #endif /* __sparc__ */ @@ -165,20 +135,19 @@ static inline void iga_outb(struct fb_info_iga *info, unsigned char val, * Very important functionality for the JavaEngine1 computer: * make screen border black (usign special IGA registers) */ -static void iga_blank_border(struct fb_info_iga *info) +static void iga_blank_border(struct iga_par *par) { int i; - #if 0 /* * PROM does this for us, so keep this code as a reminder * about required read from 0x3DA and writing of 0x20 in the end. */ - (void) pci_inb(info, 0x3DA); /* required for every access */ - pci_outb(info, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL); - (void) pci_inb(info, IGA_ATTR_CTL+1); - pci_outb(info, 0x38, IGA_ATTR_CTL); - pci_outb(info, 0x20, IGA_ATTR_CTL); /* re-enable visual */ + (void) pci_inb(par, 0x3DA); /* required for every access */ + pci_outb(par, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL); + (void) pci_inb(par, IGA_ATTR_CTL+1); + pci_outb(par, 0x38, IGA_ATTR_CTL); + pci_outb(par, 0x20, IGA_ATTR_CTL); /* re-enable visual */ #endif /* * This does not work as it was designed because the overscan @@ -186,68 +155,19 @@ static void iga_blank_border(struct fb_info_iga *info) * overscan changes color. */ for (i=0; i < 3; i++) - iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i); -} - - -/* - * Frame buffer device API - */ - -static int igafb_update_var(int con, struct fb_info *info) -{ - return 0; -} - -static int igafb_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *info) -{ - struct fb_info_iga *fb = (struct fb_info_iga*)info; - - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - strcpy(fix->id, igafb_name); - - fix->smem_start = (unsigned long) fb->frame_buffer; - fix->smem_len = fb->total_vram; - fix->xpanstep = 0; - fix->ypanstep = 0; - fix->ywrapstep = 0; - - fix->type = FB_TYPE_PACKED_PIXELS; - fix->type_aux = 0; - fix->line_length = default_var.xres * (default_var.bits_per_pixel/8); - fix->visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR - : FB_VISUAL_DIRECTCOLOR; - return 0; -} - -static int igafb_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) -{ - if(con == -1) - memcpy(var, &default_var, sizeof(struct fb_var_screeninfo)); - else - *var = fb_display[con].var; - return 0; -} - -static int igafb_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) -{ - memcpy(var, &default_var, sizeof(struct fb_var_screeninfo)); - return 0; + iga_outb(par, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i); } #ifdef __sparc__ static int igafb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) { - struct fb_info_iga *fb = (struct fb_info_iga *)info; + struct iga_par *par = (struct iga_par *)info->par; unsigned int size, page, map_size = 0; unsigned long map_offset = 0; int i; - if (!fb->mmap_map) + if (!par->mmap_map) return -ENXIO; size = vma->vm_end - vma->vm_start; @@ -258,9 +178,9 @@ static int igafb_mmap(struct fb_info *info, struct file *file, /* Each page, see which map applies */ for (page = 0; page < size; ) { map_size = 0; - for (i = 0; fb->mmap_map[i].size; i++) { - unsigned long start = fb->mmap_map[i].voff; - unsigned long end = start + fb->mmap_map[i].size; + for (i = 0; par->mmap_map[i].size; i++) { + unsigned long start = par->mmap_map[i].voff; + unsigned long end = start + par->mmap_map[i].size; unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page; if (start > offset) @@ -268,8 +188,8 @@ static int igafb_mmap(struct fb_info *info, struct file *file, if (offset >= end) continue; - map_size = fb->mmap_map[i].size - (offset - start); - map_offset = fb->mmap_map[i].poff + (offset - start); + map_size = par->mmap_map[i].size - (offset - start); + map_offset = par->mmap_map[i].poff + (offset - start); break; } if (!map_size) { @@ -279,8 +199,8 @@ static int igafb_mmap(struct fb_info *info, struct file *file, if (page + map_size > size) map_size = size - page; - pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask); - pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag; + pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask); + pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag; if (remap_page_range(vma, vma->vm_start + page, map_offset, map_size, vma->vm_page_prot)) @@ -293,46 +213,13 @@ static int igafb_mmap(struct fb_info *info, struct file *file, return -EINVAL; vma->vm_flags |= VM_IO; - - if (!fb->mmaped) { - int lastconsole = 0; - - if (info->display_fg) - lastconsole = info->display_fg->vc_num; - fb->mmaped = 1; - if (fb->consolecnt && fb_display[lastconsole].fb_info ==info) { - fb->vtconsole = lastconsole; - vt_cons[lastconsole]->vc_mode = KD_GRAPHICS; - } - } return 0; } #endif /* __sparc__ */ - -static int iga_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *fb_info) -{ - /* - * Read a single color register and split it into colors/transparent. - * Return != 0 for invalid regno. - */ - struct fb_info_iga *info = (struct fb_info_iga*) fb_info; - - if (regno >= info->video_cmap_len) - return 1; - - *red = info->palette[regno].red; - *green = info->palette[regno].green; - *blue = info->palette[regno].blue; - *transp = 0; - return 0; -} - static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, - struct fb_info *fb_info) + struct fb_info *info) { /* * Set a single color register. The values supplied are @@ -340,221 +227,100 @@ static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green, * (according to the entries in the `var' structure). Return * != 0 for invalid regno. */ - - struct fb_info_iga *info = (struct fb_info_iga*) fb_info; + struct iga_par *par = (struct iga_par *)info->par; - if (regno >= info->video_cmap_len) + if (regno >= info->cmap.len) return 1; - info->palette[regno].red = red; - info->palette[regno].green = green; - info->palette[regno].blue = blue; - - pci_outb(info, regno, DAC_W_INDEX); - pci_outb(info, red, DAC_DATA); - pci_outb(info, green, DAC_DATA); - pci_outb(info, blue, DAC_DATA); + pci_outb(par, regno, DAC_W_INDEX); + pci_outb(par, red, DAC_DATA); + pci_outb(par, green, DAC_DATA); + pci_outb(par, blue, DAC_DATA); if (regno < 16) { - switch (default_var.bits_per_pixel) { -#ifdef FBCON_HAS_CFB16 + switch (info->var.bits_per_pixel) { case 16: - info->fbcon_cmap.cfb16[regno] = + info->pseudo_palette[regno] = (regno << 10) | (regno << 5) | regno; break; -#endif -#ifdef FBCON_HAS_CFB24 case 24: - info->fbcon_cmap.cfb24[regno] = + info->pseudo_palette[regno] = (regno << 16) | (regno << 8) | regno; break; -#endif -#ifdef FBCON_HAS_CFB32 case 32: { int i; i = (regno << 8) | regno; - info->fbcon_cmap.cfb32[regno] = (i << 16) | i; + info->pseudo_palette[regno] = (i << 16) | i; } break; -#endif } } return 0; } -static int igafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *fb_info) -{ - struct fb_info_iga *info = (struct fb_info_iga*) fb_info; - - if (con == fb_info->currcon) /* current console? */ - return fb_get_cmap(cmap, kspc, iga_getcolreg, &info->fb_info); - else if (fb_display[con].cmap.len) /* non default colormap? */ - fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); - else - fb_copy_cmap(fb_default_cmap(info->video_cmap_len), - cmap, kspc ? 0 : 2); - return 0; -} - /* * Framebuffer option structure */ static struct fb_ops igafb_ops = { - .owner = THIS_MODULE, - .fb_get_fix = igafb_get_fix, - .fb_get_var = igafb_get_var, - .fb_set_var = igafb_set_var, - .fb_get_cmap = igafb_get_cmap, - .fb_set_cmap = gen_set_cmap, - .fb_setcolreg = igafb_setcolreg, + .owner = THIS_MODULE, + .fb_setcolreg = igafb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, #ifdef __sparc__ - .fb_mmap = igafb_mmap, + .fb_mmap = igafb_mmap, #endif }; -static void igafb_set_disp(int con, struct fb_info_iga *info) -{ - struct fb_fix_screeninfo fix; - struct display *display; - struct display_switch *sw; - - if (con >= 0) - display = &fb_display[con]; - else - display = &info->disp; /* used during initialization */ - - igafb_get_fix(&fix, con, &info->fb_info); - - memset(display, 0, sizeof(struct display)); - display->visual = fix.visual; - display->type = fix.type; - display->type_aux = fix.type_aux; - display->ypanstep = fix.ypanstep; - display->ywrapstep = fix.ywrapstep; - display->line_length = fix.line_length; - display->next_line = fix.line_length; - display->can_soft_blank = 0; - display->inverse = 0; - igafb_get_var(&display->var, -1, &info->fb_info); - - switch (default_var.bits_per_pixel) { -#ifdef FBCON_HAS_CFB8 - case 8: - sw = &fbcon_cfb8; - break; -#endif -#ifdef FBCON_HAS_CFB16 - case 15: - case 16: - sw = &fbcon_cfb16; - display->dispsw_data = info->fbcon_cmap.cfb16; - break; -#endif -#ifdef FBCON_HAS_CFB24 - case 24: - sw = &fbcon_cfb24; - display->dispsw_data = info->fbcon_cmap.cfb24; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case 32: - sw = &fbcon_cfb32; - display->dispsw_data = info->fbcon_cmap.cfb32; - break; -#endif - default: - printk(KERN_WARNING "igafb_set_disp: unknown resolution %d\n", - default_var.bits_per_pixel); - return; - } - memcpy(&info->dispsw, sw, sizeof(*sw)); - display->dispsw = &info->dispsw; - - display->scrollmode = SCROLL_YREDRAW; - info->dispsw.bmove = fbcon_redraw_bmove; -} - -static int igafb_switch(int con, struct fb_info *fb_info) -{ - struct fb_info_iga *info = (struct fb_info_iga*) fb_info; - - /* Do we have to save the colormap? */ - if (fb_display[fb_info->currcon].cmap.len) - fb_get_cmap(&fb_display[fb_info->currcon].cmap, 1, - iga_getcolreg, fb_info); - - fb_info->currcon = con; - /* Install new colormap */ - do_install_cmap(con, fb_info); - igafb_update_var(con, fb_info); - return 1; -} - -static int __init iga_init(struct fb_info_iga *info) +static int __init iga_init(struct fb_info *info, struct iga_par *par) { - char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) + char vramsz = iga_inb(par, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) & MEM_SIZE_ALIAS; + int video_cmap_len; + switch (vramsz) { case MEM_SIZE_1M: - info->total_vram = 0x100000; + info->fix.smem_len = 0x100000; break; case MEM_SIZE_2M: - info->total_vram = 0x200000; + info->fix.smem_len = 0x200000; break; case MEM_SIZE_4M: case MEM_SIZE_RESERVED: - info->total_vram = 0x400000; + info->fix.smem_len = 0x400000; break; } - if (default_var.bits_per_pixel > 8) { - info->video_cmap_len = 16; - } else { - info->video_cmap_len = 256; - } - { - int j, k; - for (j = 0; j < 16; j++) { - k = color_table[j]; - info->palette[j].red = default_red[k]; - info->palette[j].green = default_grn[k]; - info->palette[j].blue = default_blu[k]; - } - } + if (info->var.bits_per_pixel > 8) + video_cmap_len = 16; + else + video_cmap_len = 256; - strcpy(info->fb_info.modename, igafb_name); - info->fb_info.node = NODEV; - info->fb_info.fbops = &igafb_ops; - info->fb_info.disp = &info->disp; - info->fb_info.screen_base = info->frame_buffer; - info->fb_info.currcon = -1; - strcpy(info->fb_info.fontname, fontname); - info->fb_info.changevar = NULL; - info->fb_info.switch_con = &igafb_switch; - info->fb_info.updatevar = &igafb_update_var; - info->fb_info.flags=FBINFO_FLAG_DEFAULT; - - igafb_set_disp(-1, info); - - if (register_framebuffer(&info->fb_info) < 0) + info->node = NODEV; + info->fbops = &igafb_ops; + info->flags = FBINFO_FLAG_DEFAULT; + + fb_alloc_cmap(info->cmap, video_cmap_len, 0); + + if (register_framebuffer(info) < 0) return 0; printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]\n", - GET_FB_IDX(info->fb_info.node), igafb_name, - info->frame_buffer_phys, info->total_vram >> 20); + minor(info->node), info->fix.id, + par->frame_buffer_phys, info->fix.smem_len >> 20); - iga_blank_border(info); + iga_blank_border(par); return 1; } int __init igafb_init(void) { - struct pci_dev *pdev; - struct fb_info_iga *info; - unsigned long addr; extern int con_is_present(void); - int iga2000 = 0; + struct fb_info *info; + struct pci_dev *pdev; + struct iga_par *par; + unsigned long addr; + int size, iga2000 = 0; /* Do not attach when we have a serial console. */ if (!con_is_present()) @@ -573,13 +339,18 @@ int __init igafb_init(void) } iga2000 = 1; } + + size = sizeof(struct fb_info) + sizeof(struct iga_par) + sizeof(u32)*16; - info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC); + info = kmalloc(size, GFP_ATOMIC); if (!info) { - printk("igafb_init: can't alloc fb_info_iga\n"); + printk("igafb_init: can't alloc fb_info\n"); return -ENOMEM; } - memset(info, 0, sizeof(struct fb_info_iga)); + memset(info, 0, size); + + par = (struct iga_par *) (info + 1); + if ((addr = pdev->resource[0].start) == 0) { printk("igafb_init: no memory start\n"); @@ -587,13 +358,13 @@ int __init igafb_init(void) return -ENXIO; } - if ((info->frame_buffer = ioremap(addr, 1024*1024*2)) == 0) { + if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) { printk("igafb_init: can't remap %lx[2M]\n", addr); kfree(info); return -ENXIO; } - info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK; + par->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK; #ifdef __sparc__ /* @@ -616,14 +387,14 @@ int __init igafb_init(void) * I/O addresses are. */ if (iga2000) { - info->io_base_phys = info->frame_buffer_phys | 0x00800000; + igafb_fix.mmio_start = par->frame_buffer_phys | 0x00800000; } else { - info->io_base_phys = 0x30000000; /* XXX */ + igafb_fix.mmio_start = 0x30000000; /* XXX */ } - if ((info->io_base = (int) ioremap(info->io_base_phys, 0x1000)) == 0) { - printk("igafb_init: can't remap %lx[4K]\n", info->io_base_phys); - iounmap((void *)info->frame_buffer); - kfree(info); + if ((par->io_base = (int) ioremap(igafb_fix.mmio_start, igafb_fix.smem_len)) == 0) { + printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start); + iounmap((void *)info->screen_base); + kfree(info); return -ENXIO; } @@ -635,16 +406,16 @@ int __init igafb_init(void) * one additional region with size == 0. */ - info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC); - if (!info->mmap_map) { + par->mmap_map = kmalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC); + if (!par->mmap_map) { printk("igafb_init: can't alloc mmap_map\n"); - iounmap((void *)info->io_base); - iounmap(info->frame_buffer); - kfree(info); + iounmap((void *)par->io_base); + iounmap(info->screen_base); + kfree(info); return -ENOMEM; } - memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map)); + memset(par->mmap_map, 0, 4 * sizeof(*par->mmap_map)); /* * Set default vmode and cmode from PROM properties. @@ -691,12 +462,19 @@ int __init igafb_init(void) } #endif - - if (!iga_init(info)) { - iounmap((void *)info->io_base); - iounmap(info->frame_buffer); - if (info->mmap_map) - kfree(info->mmap_map); + igafb_fix.smem_start = (unsigned long) info->screen_base; + igafb_fix.line_length = default_var.xres*(default_var.bits_per_pixel/8); + igafb_fix.visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; + + info->var = default_var; + info->fix = igafb_fix; + info->pseudo_palette = (void *)(par + 1); + + if (!iga_init(info, par)) { + iounmap((void *)par->io_base); + iounmap(info->screen_base); + if (par->mmap_map) + kfree(par->mmap_map); kfree(info); } @@ -706,18 +484,18 @@ int __init igafb_init(void) */ /* First region is for video memory */ - info->mmap_map[0].voff = 0x0; - info->mmap_map[0].poff = info->frame_buffer_phys & PAGE_MASK; - info->mmap_map[0].size = info->total_vram & PAGE_MASK; - info->mmap_map[0].prot_mask = SRMMU_CACHE; - info->mmap_map[0].prot_flag = SRMMU_WRITE; + par->mmap_map[0].voff = 0x0; + par->mmap_map[0].poff = par->frame_buffer_phys & PAGE_MASK; + par->mmap_map[0].size = info->fix.smem_len & PAGE_MASK; + par->mmap_map[0].prot_mask = SRMMU_CACHE; + par->mmap_map[0].prot_flag = SRMMU_WRITE; /* Second region is for I/O ports */ - info->mmap_map[1].voff = info->frame_buffer_phys & PAGE_MASK; - info->mmap_map[1].poff = info->io_base_phys & PAGE_MASK; - info->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */ - info->mmap_map[1].prot_mask = SRMMU_CACHE; - info->mmap_map[1].prot_flag = SRMMU_WRITE; + par->mmap_map[1].voff = par->frame_buffer_phys & PAGE_MASK; + par->mmap_map[1].poff = info->fix.smem_start & PAGE_MASK; + par->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */ + par->mmap_map[1].prot_mask = SRMMU_CACHE; + par->mmap_map[1].prot_flag = SRMMU_WRITE; #endif /* __sparc__ */ return 0; @@ -731,17 +509,6 @@ int __init igafb_setup(char *options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { - if (!strncmp(this_opt, "font:", 5)) { - char *p; - int i; - - p = this_opt + 5; - for (i = 0; i < sizeof(fontname) - 1; i++) - if (!*p || *p == ' ' || *p == ',') - break; - memcpy(fontname, this_opt + 5, i); - fontname[i] = 0; - } } return 0; } diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index ac64a23248a2..40447a960a52 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -772,7 +772,7 @@ set_imstt_regvals (struct fb_info_imstt *p, u_int bpp) static inline void set_offset (struct display *disp, struct fb_info_imstt *p) { - __u32 off = disp->var.yoffset * (disp->line_length >> 3) + __u32 off = disp->var.yoffset * (p->info.fix.line_length >> 3) + ((disp->var.xoffset * (disp->var.bits_per_pixel >> 3)) >> 3); out_le32(&p->dc_regs[SSR], off); } @@ -1020,7 +1020,7 @@ imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int heig width *= Bpp; width--; - line_pitch = disp->line_length; + line_pitch = p->info.fix.line_length; bltctl = 0x05; sp = line_pitch << 16; cnt = height << 16; @@ -1068,7 +1068,7 @@ imsttfbcon_clear (struct vc_data *conp, struct display *disp, bgc |= (bgc << 16); Bpp = disp->var.bits_per_pixel >> 3, - line_pitch = disp->line_length; + line_pitch = p->info.fix.line_length; sy *= fontheight(disp); sy *= line_pitch; @@ -1099,7 +1099,7 @@ imsttfbcon_revc (struct display *disp, int sx, int sy) __u32 Bpp, line_pitch, height, width; Bpp = disp->var.bits_per_pixel >> 3, - line_pitch = disp->line_length; + line_pitch = p->info.fix.line_length; height = fontheight(disp); width = fontwidth(disp) * Bpp; @@ -1246,28 +1246,6 @@ imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue, return 0; } -static int -imsttfb_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *info) -{ - struct fb_info_imstt *p = (struct fb_info_imstt *)info; - struct fb_var_screeninfo *var = &fb_display[con].var; - - *fix = p->fix; - fix->visual = var->bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR - : FB_VISUAL_DIRECTCOLOR; - fix->line_length = var->xres * (var->bits_per_pixel >> 3); - - return 0; -} - -static int -imsttfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info) -{ - *var = fb_display[con].var; - - return 0; -} - static void set_dispsw (struct display *disp, struct fb_info_imstt *p) { @@ -1354,16 +1332,7 @@ set_disp (struct display *disp, struct fb_info_imstt *p) set_dispsw(disp, p); - disp->visual = disp->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR - : FB_VISUAL_DIRECTCOLOR; - disp->visual = p->fix.visual; - disp->type = p->fix.type; - disp->type_aux = p->fix.type_aux; - disp->line_length = disp->var.xres * (disp->var.bits_per_pixel >> 3); disp->can_soft_blank = 1; - disp->inverse = inverse; - disp->ypanstep = 1; - disp->ywrapstep = 0; if (accel) { disp->scrollmode = SCROLL_YNOMOVE; if (disp->var.yres == disp->var.yres_virtual) { @@ -1625,8 +1594,6 @@ static struct pci_driver imsttfb_pci_driver = { static struct fb_ops imsttfb_ops = { .owner = THIS_MODULE, - .fb_get_fix = imsttfb_get_fix, - .fb_get_var = imsttfb_get_var, .fb_set_var = imsttfb_set_var, .fb_get_cmap = imsttfb_get_cmap, .fb_set_cmap = gen_set_cmap, diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 252cf713c4a2..f589222abde0 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -40,8 +40,6 @@ #include <asm/io.h> #include <asm/machw.h> -#include <video/fbcon.h> - /* Common DAC base address for the LC, RBV, Valkyrie, and IIvx */ #define DAC_BASE 0x50f24000 @@ -173,7 +171,6 @@ static struct fb_fix_screeninfo macfb_fix = { .accel = FB_ACCEL_NONE, }; -static struct display disp; static struct fb_info fb_info; static u32 pseudo_palette[17]; static int inverse = 0; @@ -225,7 +222,7 @@ static int dafb_setpalette (unsigned int regno, unsigned int red, local_irq_save(flags); - /* fbcon will set an entire colourmap, but X won't. Hopefully + /* fbdev will set an entire colourmap, but X won't. Hopefully this should accomodate both of them */ if (regno != lastreg+1) { int i; @@ -588,21 +585,17 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green, static struct fb_ops macfb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = macfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; void __init macfb_setup(char *options, int *ints) { char *this_opt; - fb_info.fontname[0] = '\0'; - if (!options || !*options) return; @@ -611,8 +604,6 @@ void __init macfb_setup(char *options, int *ints) if (! strcmp(this_opt, "inverse")) inverse=1; - else if (!strncmp(this_opt, "font:", 5)) - strcpy(fb_info.fontname, this_opt+5); /* This means "turn on experimental CLUT code" */ else if (!strcmp(this_opt, "vidtest")) vidtest=1; @@ -952,27 +943,20 @@ void __init macfb_init(void) break; } - strcpy(fb_info.modename, macfb_fix.id); - fb_info.changevar = NULL; fb_info.node = NODEV; fb_info.fbops = &macfb_ops; fb_info.var = macfb_defined; fb_info.fix = macfb_fix; - fb_info.currcon = -1; - fb_info.disp = &disp; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_info.pseudo_palette = pseudo_palette; fb_info.flags = FBINFO_FLAG_DEFAULT; fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); - gen_set_disp(-1, &fb_info); if (register_framebuffer(&fb_info) < 0) return; printk("fb%d: %s frame buffer device\n", - GET_FB_IDX(fb_info.node), fb_info.fix.id); + minor(fb_info.node), fb_info.fix.id); } MODULE_LICENSE("GPL"); diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c index ee713a98a79d..3cd1145a6c66 100644 --- a/drivers/video/macmodes.c +++ b/drivers/video/macmodes.c @@ -20,8 +20,7 @@ #include <linux/fb.h> #include <linux/string.h> -#include <video/fbcon.h> -#include <video/macmodes.h> +#include "macmodes.h" /* * MacOS video mode definitions diff --git a/include/video/macmodes.h b/drivers/video/macmodes.h index 232f5a09a499..232f5a09a499 100644 --- a/include/video/macmodes.h +++ b/drivers/video/macmodes.h diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c index 63d70448e783..f984722caa89 100644 --- a/drivers/video/matrox/i2c-matroxfb.c +++ b/drivers/video/matrox/i2c-matroxfb.c @@ -120,7 +120,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, b->mask.data = data; b->mask.clock = clock; b->adapter = matrox_i2c_adapter_template; - sprintf(b->adapter.name, name, GET_FB_IDX(minfo->fbcon.node)); + sprintf(b->adapter.name, name, minor(minfo->fbcon.node)); b->adapter.data = b; b->adapter.algo_data = &b->bac; b->bac = matrox_i2c_algo_template; diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 477039b3fb8b..3a988123e654 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1872,12 +1872,12 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ goto failVideoIO; } printk("fb%d: %s frame buffer device\n", - GET_FB_IDX(ACCESS_FBINFO(fbcon.node)), ACCESS_FBINFO(fbcon.modename)); + minor(ACCESS_FBINFO(fbcon.node)), ACCESS_FBINFO(fbcon.modename)); if (ACCESS_FBINFO(fbcon.currcon) < 0) { /* there is no console on this fb... but we have to initialize hardware * until someone tells me what is proper thing to do */ printk(KERN_INFO "fb%d: initializing hardware\n", - GET_FB_IDX(ACCESS_FBINFO(fbcon.node))); + minor(ACCESS_FBINFO(fbcon.node))); matroxfb_set_var(&vesafb_defined, -1, &ACCESS_FBINFO(fbcon)); } return 0; diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 56c7c7a02583..70a63cb5f097 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -816,7 +816,7 @@ static int matroxfb_dh_registerfb(struct matroxfb_dh_fb_info* m2info) { return -1; } printk(KERN_INFO "matroxfb_crtc2: secondary head of fb%u was registered as fb%u\n", - GET_FB_IDX(ACCESS_FBINFO(fbcon.node)), GET_FB_IDX(m2info->fbcon.node)); + minor(ACCESS_FBINFO(fbcon.node)), minor(m2info->fbcon.node)); m2info->fbcon_registered = 1; return 0; #undef minfo @@ -839,7 +839,7 @@ static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) { printk(KERN_ERR "matroxfb_crtc2: Expect kernel crash after module unload.\n"); return; } - id = GET_FB_IDX(m2info->fbcon.node); + id = minor(m2info->fbcon.node); unregister_framebuffer(&m2info->fbcon); kfree(m2info->fbcon.disp); /* return memory back to primary head */ diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c index 6e1fd2f76347..efe82be7f367 100644 --- a/drivers/video/maxinefb.c +++ b/drivers/video/maxinefb.c @@ -34,7 +34,6 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/fb.h> -#include <video/fbcon.h> #include "maxinefb.h" /* bootinfo.h defines the machine type values, needed when checking */ @@ -42,27 +41,29 @@ #include <asm/bootinfo.h> static struct fb_info fb_info; -static struct display disp; static struct fb_var_screeninfo maxinefb_defined = { - .xres = 1024, - .yres = 768, - .xres_virtual = 1024, - .yres_virtual = 768, - .bits_per_pixel =8, - .activate = FB_ACTIVATE_NOW, - .height = -1, - .width = -1, - .vmode = FB_VMODE_NONINTERLACED, + .xres = 1024, + .yres = 768, + .xres_virtual = 1024, + .yres_virtual = 768, + .bits_per_pixel = 8, + .red.length = 8, + .green.length = 8, + .blue.length = 8, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .vmode = FB_VMODE_NONINTERLACED, }; static struct fb_fix_screeninfo maxinefb_fix = { - .id = "Maxine onboard graphics 1024x768x8", - .smem_len = (1024*768), - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_PSEUDOCOLOR, - .line_length = 1024, -} + .id = "Maxine onboard graphics 1024x768x8", + .smem_len = (1024*768), + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .line_length = 1024, +}; /* Reference to machine type set in arch/mips/dec/prom/identify.c, KM */ extern unsigned long mips_machtype; @@ -112,13 +113,11 @@ static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green, static struct fb_ops maxinefb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = maxinefb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; int __init maxinefb_init(void) @@ -156,23 +155,14 @@ int __init maxinefb_init(void) */ } - /* Let there be consoles... */ - - strcpy(fb_info.modename, "Maxine onboard graphics 1024x768x8"); - fb_info.changevar = NULL; fb_info.node = NODEV; fb_info.fbops = &maxinefb_ops; fb_info.screen_base = (char *) maxinefb_fix.smem_start; fb_info.var = maxinefb_defined; fb_info.fix = maxinefb_fix; - fb_info.disp = &disp; - fb_info.currcon = -1; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_info.flags = FBINFO_FLAG_DEFAULT; fb_alloc_cmap(&fb_info.cmap, 256, 0); - gen_set_disp(-1, &fb_info); if (register_framebuffer(&fb_info) < 0) return 1; diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 16d0aeb9184d..5dd60c82914f 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -16,8 +16,6 @@ #include <linux/fb.h> #include <linux/sched.h> -#include <video/fbcon.h> - #undef DEBUG #define name_matches(v, s, l) \ @@ -277,7 +275,7 @@ static int __init my_atoi(const char *name) int __fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, const struct fb_videomode *mode, unsigned int bpp) { - int err; + int err = 1; DPRINTK("Trying mode %s %dx%d-%d@%d\n", mode->name ? mode->name : "noname", mode->xres, mode->yres, bpp, mode->refresh); @@ -298,7 +296,8 @@ int __fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, var->vsync_len = mode->vsync_len; var->sync = mode->sync; var->vmode = mode->vmode; - err = info->fbops->fb_set_var(var, PROC_CONSOLE(info), info); + if (info->fbops->fb_check_var) + err = info->fbops->fb_check_var(var, info); var->activate &= ~FB_ACTIVATE_TEST; return !err; } diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 08174b35099a..1b50a75f5f1e 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1,7 +1,7 @@ /* * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver * - * Copyright (c) 2001 Denis Oliver Kropp <dok@convergence.de> + * Copyright (c) 2001-2002 Denis Oliver Kropp <dok@directfb.org> * * * Card specific code is based on XFree86's neomagic driver. @@ -11,6 +11,16 @@ * Public License. See the file COPYING in the main directory of this * archive for more details. * + * + * 0.4.1 + * - Cosmetic changes (dok) + * + * 0.4 + * - Toshiba Libretto support, allow modes larger than LCD size if + * LCD is disabled, keep BIOS settings if internal/external display + * haven't been enabled explicitly + * (Thomas J. Moore <dark@mama.indstate.edu>) + * * 0.3.3 * - Porting over to new fbdev api. (jsimmons) * @@ -56,6 +66,10 @@ #include <linux/fb.h> #include <linux/pci.h> #include <linux/init.h> +#ifdef CONFIG_TOSHIBA +#include <linux/toshiba.h> +extern int tosh_smm(SMMRegisters *regs); +#endif #include <asm/io.h> #include <asm/irq.h> @@ -67,20 +81,18 @@ #include <asm/mtrr.h> #endif -#include <video/fbcon.h> #include <video/neomagic.h> -#define NEOFB_VERSION "0.3.3" - -struct neofb_par default_par; +#define NEOFB_VERSION "0.4.1" /* --------------------------------------------------------------------- */ -static int disabled = 0; -static int internal = 0; -static int external = 0; -static int nostretch = 0; -static int nopciburst = 0; +static int disabled; +static int internal; +static int external; +static int libretto; +static int nostretch; +static int nopciburst; #ifdef MODULE @@ -94,6 +106,8 @@ MODULE_PARM(internal, "i"); MODULE_PARM_DESC(internal, "Enable output on internal LCD Display."); MODULE_PARM(external, "i"); MODULE_PARM_DESC(external, "Enable output on external CRT."); +MODULE_PARM(libretto, "i"); +MODULE_PARM_DESC(libretto, "Force Libretto 100/110 800x480 LCD."); MODULE_PARM(nostretch, "i"); MODULE_PARM_DESC(nostretch, "Disable stretching of modes smaller than LCD."); @@ -450,15 +464,17 @@ static void vgaHWRestore(const struct fb_info *info, /* * Hardware Acceleration for Neo2200+ */ -static inline void neo2200_wait_idle(struct neofb_par *par) +static inline int neo2200_sync(struct fb_info *info) { + struct neofb_par *par = (struct neofb_par *) info->par; int waitcycles; while (par->neo2200->bltStat & 1) waitcycles++; + return 0; } -static inline void neo2200_wait_fifo(struct neofb_par *par, +static inline void neo2200_wait_fifo(struct fb_info *info, int requested_fifo_space) { // ndev->neo.waitfifo_calls++; @@ -484,17 +500,17 @@ static inline void neo2200_wait_fifo(struct neofb_par *par, neo_fifo_space -= requested_fifo_space; */ - neo2200_wait_idle(par); + neo2200_sync(info); } -static inline void neo2200_accel_init(struct fb_info *fb, +static inline void neo2200_accel_init(struct fb_info *info, struct fb_var_screeninfo *var) { - struct neofb_par *par = (struct neofb_par *) fb->par; + struct neofb_par *par = (struct neofb_par *) info->par; Neo2200 *neo2200 = par->neo2200; u32 bltMod, pitch; - neo2200_wait_idle(par); + neo2200_sync(info); switch (var->bits_per_pixel) { case 8: @@ -551,8 +567,9 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) timings.sync = var->sync; /* Is the mode larger than the LCD panel? */ - if ((var->xres > par->NeoPanelWidth) || - (var->yres > par->NeoPanelHeight)) { + if (par->internal_display && + ((var->xres > par->NeoPanelWidth) || + (var->yres > par->NeoPanelHeight))) { printk(KERN_INFO "Mode (%dx%d) larger than the LCD panel (%dx%d)\n", var->xres, var->yres, par->NeoPanelWidth, @@ -561,23 +578,27 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) } /* Is the mode one of the acceptable sizes? */ - switch (var->xres) { - case 1280: - if (var->yres == 1024) - mode_ok = 1; - break; - case 1024: - if (var->yres == 768) - mode_ok = 1; - break; - case 800: - if (var->yres == 600) - mode_ok = 1; - break; - case 640: - if (var->yres == 480) - mode_ok = 1; - break; + if (!par->internal_display) + mode_ok = 1; + else { + switch (var->xres) { + case 1280: + if (var->yres == 1024) + mode_ok = 1; + break; + case 1024: + if (var->yres == 768) + mode_ok = 1; + break; + case 800: + if (var->yres == (par->libretto ? 480 : 600)) + mode_ok = 1; + break; + case 640: + if (var->yres == 480) + mode_ok = 1; + break; + } } if (!mode_ok) { @@ -674,6 +695,10 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (var->yoffset + var->yres > var->yres_virtual) var->yoffset = var->yres_virtual - var->yres; + var->nonstd = 0; + var->height = -1; + var->width = -1; + if (var->bits_per_pixel >= 24 || !par->neo2200) var->accel_flags &= ~FB_ACCELF_TEXT; return 0; @@ -1165,10 +1190,9 @@ static void neofb_update_start(struct fb_info *info, /* * Pan or Wrap the Display */ -static int neofb_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *fb) +static int neofb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) { - struct fb_info *info = (struct fb_info *) fb; u_int y_bottom; y_bottom = var->yoffset; @@ -1178,19 +1202,18 @@ static int neofb_pan_display(struct fb_var_screeninfo *var, int con, if (var->xoffset > (var->xres_virtual - var->xres)) return -EINVAL; - if (y_bottom > fb->var.yres_virtual) + if (y_bottom > info->var.yres_virtual) return -EINVAL; neofb_update_start(info, var); - fb->var.xoffset = var->xoffset; - fb->var.yoffset = var->yoffset; + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) - fb->var.vmode |= FB_VMODE_YWRAP; + info->var.vmode |= FB_VMODE_YWRAP; else - fb->var.vmode &= ~FB_VMODE_YWRAP; - + info->var.vmode &= ~FB_VMODE_YWRAP; return 0; } @@ -1239,10 +1262,8 @@ static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, /* * (Un)Blank the display. */ -static int neofb_blank(int blank, struct fb_info *fb) +static int neofb_blank(int blank, struct fb_info *info) { - // struct fb_info *info = (struct fb_info *)fb; - /* * Blank the screen if blank_mode != 0, else unblank. If * blank == NULL then the caller blanks by setting the CLUT @@ -1261,6 +1282,17 @@ static int neofb_blank(int blank, struct fb_info *fb) switch (blank) { case 4: /* powerdown - both sync lines down */ +#ifdef CONFIG_TOSHIBA + /* attempt to turn off backlight on toshiba; also turns off external */ + { + SMMRegisters regs; + + regs.eax = 0xff00; /* HCI_SET */ + regs.ebx = 0x0002; /* HCI_BACKLIGHT */ + regs.ecx = 0x0000; /* HCI_DISABLE */ + tosh_smm(®s); + } +#endif break; case 3: /* hsync off */ break; @@ -1269,13 +1301,24 @@ static int neofb_blank(int blank, struct fb_info *fb) case 1: /* just software blanking of screen */ break; default: /* case 0, or anything else: unblank */ +#ifdef CONFIG_TOSHIBA + /* attempt to re-enable backlight/external on toshiba */ + { + SMMRegisters regs; + + regs.eax = 0xff00; /* HCI_SET */ + regs.ebx = 0x0002; /* HCI_BACKLIGHT */ + regs.ecx = 0x0001; /* HCI_ENABLE */ + tosh_smm(®s); + } +#endif break; } return 0; } static void -neo2200fb_fillrect(struct fb_info *info, struct fb_fillrect *rect) +neo2200_fillrect(struct fb_info *info, struct fb_fillrect *rect) { struct neofb_par *par = (struct neofb_par *) info->par; u_long dst, rop; @@ -1283,7 +1326,7 @@ neo2200fb_fillrect(struct fb_info *info, struct fb_fillrect *rect) dst = rect->dx + rect->dy * info->var.xres_virtual; rop = rect->rop ? 0x060000 : 0x0c0000; - neo2200_wait_fifo(par, 4); + neo2200_wait_fifo(info, 4); /* set blt control */ par->neo2200->bltCntl = NEO_BC3_FIFO_EN | @@ -1309,7 +1352,7 @@ neo2200fb_fillrect(struct fb_info *info, struct fb_fillrect *rect) } static void -neo2200fb_copyarea(struct fb_info *info, struct fb_copyarea *area) +neo2200_copyarea(struct fb_info *info, struct fb_copyarea *area) { struct neofb_par *par = (struct neofb_par *) info->par; u_long src, dst, bltCntl; @@ -1337,7 +1380,7 @@ neo2200fb_copyarea(struct fb_info *info, struct fb_copyarea *area) area->dx * (info->var.bits_per_pixel >> 3) + area->dy * info->fix.line_length; - neo2200_wait_fifo(par, 4); + neo2200_wait_fifo(info, 4); /* set blt control */ par->neo2200->bltCntl = bltCntl; @@ -1349,11 +1392,11 @@ neo2200fb_copyarea(struct fb_info *info, struct fb_copyarea *area) } static void -neo2200fb_imageblit(struct fb_info *info, struct fb_image *image) +neo2200_imageblit(struct fb_info *info, struct fb_image *image) { struct neofb_par *par = (struct neofb_par *) info->par; - neo2200_wait_idle(par); + neo2200_sync(info); switch (info->var.bits_per_pixel) { case 8: @@ -1385,98 +1428,140 @@ neo2200fb_imageblit(struct fb_info *info, struct fb_image *image) (image->width * image->height) >> 3); } +static void +neofb_fillrect(struct fb_info *info, struct fb_fillrect *rect) +{ + if (info->var.accel_flags == FB_ACCELF_TEXT) + neo2200_fillrect(info, rect); + else + cfb_fillrect(info, rect); +} + +static void +neofb_copyarea(struct fb_info *info, struct fb_copyarea *area) +{ + if (info->var.accel_flags == FB_ACCELF_TEXT) + neo2200_copyarea(info, area); + else + cfb_copyarea(info, area); +} + +static void +neofb_imageblit(struct fb_info *info, struct fb_image *image) +{ + if (info->var.accel_flags == FB_ACCELF_TEXT) + neo2200_imageblit(info, image); + else + cfb_imageblit(info, image); +} + static struct fb_ops neofb_ops = { .owner = THIS_MODULE, .fb_check_var = neofb_check_var, .fb_set_par = neofb_set_par, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = neofb_setcolreg, .fb_pan_display = neofb_pan_display, .fb_blank = neofb_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, + .fb_sync = neo2200_sync, + .fb_fillrect = neofb_fillrect, + .fb_copyarea = neofb_copyarea, + .fb_imageblit = neofb_imageblit, + .fb_cursor = soft_cursor, }; /* --------------------------------------------------------------------- */ static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = { - accel_flags: FB_ACCELF_TEXT, - xres: 640, - yres: 480, - xres_virtual: 640, - yres_virtual: 30000, - bits_per_pixel: 8, - pixclock: 39722, - left_margin: 48, - right_margin: 16, - upper_margin: 33, - lower_margin: 10, - hsync_len: 96, - vsync_len: 2, - vmode: FB_VMODE_NONINTERLACED + .accel_flags = FB_ACCELF_TEXT, + .xres = 640, + .yres = 480, + .xres_virtual = 640, + .yres_virtual = 30000, + .bits_per_pixel = 8, + .pixclock = 39722, + .left_margin = 48, + .right_margin = 16, + .upper_margin = 33, + .lower_margin = 10, + .hsync_len = 96, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED }; static struct fb_var_screeninfo __devinitdata neofb_var800x600x8 = { - accel_flags: FB_ACCELF_TEXT, - xres: 800, - yres: 600, - xres_virtual: 800, - yres_virtual: 30000, - bits_per_pixel: 8, - pixclock: 25000, - left_margin: 88, - right_margin: 40, - upper_margin: 23, - lower_margin: 1, - hsync_len: 128, - vsync_len: 4, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - vmode: FB_VMODE_NONINTERLACED + .accel_flags = FB_ACCELF_TEXT, + .xres = 800, + .yres = 600, + .xres_virtual = 800, + .yres_virtual = 30000, + .bits_per_pixel = 8, + .pixclock = 25000, + .left_margin = 88, + .right_margin = 40, + .upper_margin = 23, + .lower_margin = 1, + .hsync_len = 128, + .vsync_len = 4, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED +}; + +static struct fb_var_screeninfo __devinitdata neofb_var800x480x8 = { + .accel_flags = FB_ACCELF_TEXT, + .xres = 800, + .yres = 480, + .xres_virtual = 800, + .yres_virtual = 30000, + .bits_per_pixel = 8, + .pixclock = 25000, + .left_margin = 88, + .right_margin = 40, + .upper_margin = 23, + .lower_margin = 1, + .hsync_len = 128, + .vsync_len = 4, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED }; static struct fb_var_screeninfo __devinitdata neofb_var1024x768x8 = { - accel_flags: FB_ACCELF_TEXT, - xres: 1024, - yres: 768, - xres_virtual: 1024, - yres_virtual: 30000, - bits_per_pixel: 8, - pixclock: 15385, - left_margin: 160, - right_margin: 24, - upper_margin: 29, - lower_margin: 3, - hsync_len: 136, - vsync_len: 6, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - vmode: FB_VMODE_NONINTERLACED + .accel_flags = FB_ACCELF_TEXT, + .xres = 1024, + .yres = 768, + .xres_virtual = 1024, + .yres_virtual = 30000, + .bits_per_pixel = 8, + .pixclock = 15385, + .left_margin = 160, + .right_margin = 24, + .upper_margin = 29, + .lower_margin = 3, + .hsync_len = 136, + .vsync_len = 6, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED }; #ifdef NOT_DONE static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = { - accel_flags: FB_ACCELF_TEXT, - xres: 1280, - yres: 1024, - xres_virtual: 1280, - yres_virtual: 30000, - bits_per_pixel: 8, - pixclock: 9260, - left_margin: 248, - right_margin: 48, - upper_margin: 38, - lower_margin: 1, - hsync_len: 112, - vsync_len: 3, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - vmode: FB_VMODE_NONINTERLACED + .accel_flags = FB_ACCELF_TEXT, + .xres = 1280, + .yres = 1024, + .xres_virtual = 1280, + .yres_virtual = 30000, + .bits_per_pixel = 8, + .pixclock = 9260, + .left_margin = 248, + .right_margin = 48, + .upper_margin = 38, + .lower_margin = 1, + .hsync_len = 112, + .vsync_len = 3, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED }; #endif -static struct fb_var_screeninfo *neofb_var = NULL; - static int __devinit neo_map_mmio(struct fb_info *info, struct pci_dev *dev) { @@ -1581,6 +1666,7 @@ static void __devinit neo_unmap_video(struct fb_info *info) static int __devinit neo_init_hw(struct fb_info *info) { struct neofb_par *par = (struct neofb_par *) info->par; + unsigned char type, display; int videoRam = 896; int maxClock = 65000; int CursorMem = 1024; @@ -1588,7 +1674,6 @@ static int __devinit neo_init_hw(struct fb_info *info) int linearSize = 1024; int maxWidth = 1024; int maxHeight = 1024; - unsigned char type, display; int w; DBG("neo_init_hw"); @@ -1609,6 +1694,13 @@ static int __devinit neo_init_hw(struct fb_info *info) VGAwGR(0x09, 0x26); type = VGArGR(0x21); display = VGArGR(0x20); + if (!par->internal_display && !par->external_display) { + par->internal_display = display & 2 || !(display & 3) ? 1 : 0; + par->external_display = display & 1; + printk (KERN_INFO "Autodetected %s display\n", + par->internal_display && par->external_display ? "simultaneous" : + par->internal_display ? "internal" : "external"); + } /* Determine panel width -- used in NeoValidMode. */ w = VGArGR(0x20); @@ -1617,34 +1709,34 @@ static int __devinit neo_init_hw(struct fb_info *info) case 0x00: par->NeoPanelWidth = 640; par->NeoPanelHeight = 480; - neofb_var = &neofb_var640x480x8; + info->var = neofb_var640x480x8; break; case 0x01: par->NeoPanelWidth = 800; - par->NeoPanelHeight = 600; - neofb_var = &neofb_var800x600x8; + par->NeoPanelHeight = par->libretto ? 480 : 600; + info->var = par->libretto ? neofb_var800x480x8 : neofb_var800x600x8; break; case 0x02: par->NeoPanelWidth = 1024; par->NeoPanelHeight = 768; - neofb_var = &neofb_var1024x768x8; + info->var = neofb_var1024x768x8; break; case 0x03: /* 1280x1024 panel support needs to be added */ #ifdef NOT_DONE par->NeoPanelWidth = 1280; par->NeoPanelHeight = 1024; - neofb_var = &neofb_var1280x1024x8; + info->var = neofb_var1280x1024x8; break; #else printk(KERN_ERR - "neofb: Only 640x480, 800x600 and 1024x768 panels are currently supported\n"); + "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n"); return -1; #endif default: par->NeoPanelWidth = 640; par->NeoPanelHeight = 480; - neofb_var = &neofb_var640x480x8; + info->var = neofb_var640x480x8; break; } @@ -1750,30 +1842,24 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st struct fb_info *info; struct neofb_par *par; - info = kmalloc(sizeof(struct fb_info) + sizeof(struct display) + - sizeof(u32) * 16, GFP_KERNEL); + info = kmalloc(sizeof(struct fb_info) + sizeof(struct neofb_par) + + sizeof(u32) * 17, GFP_KERNEL); if (!info) return NULL; - memset(info, 0, sizeof(struct fb_info) + sizeof(struct display)); + memset(info, 0, sizeof(struct fb_info) + sizeof(struct neofb_par) + sizeof(u32) * 17); - par = &default_par; - memset(par, 0, sizeof(struct neofb_par)); + par = (struct neofb_par *) (info + 1); - info->currcon = -1; info->fix.accel = id->driver_data; par->pci_burst = !nopciburst; par->lcd_stretch = !nostretch; + par->libretto = libretto; - if (!internal && !external) { - par->internal_display = 1; - par->external_display = 0; - } else { - par->internal_display = internal; - par->external_display = external; - } + par->internal_display = internal; + par->external_display = external; switch (info->fix.accel) { case FB_ACCEL_NEOMAGIC_NM2070: @@ -1812,22 +1898,10 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st info->fix.ywrapstep = 0; info->fix.accel = id->driver_data; - info->var.nonstd = 0; - info->var.activate = FB_ACTIVATE_NOW; - info->var.height = -1; - info->var.width = -1; - info->var.accel_flags = 0; - - strcpy(info->modename, info->fix.id); - info->fbops = &neofb_ops; - info->changevar = NULL; - info->switch_con = gen_switch; - info->updatevar = gen_update_var; info->flags = FBINFO_FLAG_DEFAULT; info->par = par; - info->disp = (struct display *) (info + 1); - info->pseudo_palette = (void *) (info->disp + 1); + info->pseudo_palette = (void *) (par + 1); fb_alloc_cmap(&info->cmap, NR_PALETTE, 0); @@ -1881,8 +1955,6 @@ static int __devinit neofb_probe(struct pci_dev *dev, if (err) goto failed; - gen_set_var(neofb_var, -1, info); - /* * Calculate the hsync and vsync frequencies. Note that * we split the 1e12 constant up so that we can preserve @@ -1908,7 +1980,7 @@ static int __devinit neofb_probe(struct pci_dev *dev, goto failed; printk(KERN_INFO "fb%d: %s frame buffer device\n", - GET_FB_IDX(info->node), info->modename); + minor(info->node), info->fix.id); /* * Our driver data @@ -2008,7 +2080,6 @@ static void __exit neo_done(void) pci_unregister_driver(&neofb_driver); } - #ifndef MODULE /* ************************* init in-kernel code ************************** */ @@ -2036,6 +2107,8 @@ int __init neofb_setup(char *options) nostretch = 1; if (!strncmp(this_opt, "nopciburst", 10)) nopciburst = 1; + if (!strncmp(this_opt, "libretto", 8)) + libretto = 1; } return 0; diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 4186b17c0d67..f772815444b3 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -24,7 +24,6 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/fb.h> -#include <linux/selection.h> #include <linux/init.h> #include <linux/ioport.h> #include <asm/io.h> @@ -33,8 +32,7 @@ #include <asm/bootx.h> #endif -#include <video/fbcon.h> -#include <video/macmodes.h> +#include "macmodes.h" /* Supported palette hacks */ enum { @@ -83,14 +81,12 @@ static void offb_init_fb(const char *name, const char *full_name, static struct fb_ops offb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = offb_setcolreg, .fb_blank = offb_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; /* @@ -411,7 +407,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, return; } - size = sizeof(struct fb_info) + sizeof(struct display) + sizeof(u32) * 17; + size = sizeof(struct fb_info) + sizeof(u32) * 17; info = kmalloc(size, GFP_ATOMIC); @@ -528,24 +524,15 @@ static void __init offb_init_fb(const char *name, const char *full_name, strcpy(fix->id, "OFfb "); strncat(fix->id, full_name, sizeof(fix->id)); - strcpy(info->modename, fix->id); info->node = NODEV; info->fbops = &offb_ops; info->screen_base = ioremap(address, fix->smem_len); info->par = par; - info->disp = (struct display *) (info + 1); - info->pseudo_palette = (void *) (info->disp + 1); - info->currcon = -1; - info->fontname[0] = '\0'; - info->changevar = NULL; - info->switch_con = gen_switch; - info->updatevar = gen_update_var; + info->pseudo_palette = (void *) (info + 1); info->flags = FBINFO_FLAG_DEFAULT; fb_alloc_cmap(&info->cmap, 256, 0); - gen_set_disp(-1, info); - if (register_framebuffer(info) < 0) { kfree(info); release_mem_region(res_start, res_size); @@ -553,7 +540,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, } printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n", - GET_FB_IDX(info->node), full_name); + minor(info->node), full_name); } MODULE_LICENSE("GPL"); diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 3aea0686edee..1cdf67cfb4a2 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -58,14 +58,14 @@ struct fb_par_platinum { }; struct fb_info_platinum { - struct fb_info fb_info; - struct display disp; - struct fb_par_platinum default_par; - struct fb_par_platinum current_par; + struct fb_info info; + struct display display; /* Will disappear */ + struct fb_par_platinum par; struct { __u8 red, green, blue; } palette[256]; + u32 pseudo_palette[17]; volatile struct cmap_regs *cmap_regs; unsigned long cmap_regs_phys; @@ -80,42 +80,17 @@ struct fb_info_platinum { unsigned long total_vram; int clktype; int dactype; - - union { -#ifdef FBCON_HAS_CFB16 - u16 cfb16[16]; -#endif -#ifdef FBCON_HAS_CFB32 - u32 cfb32[16]; -#endif - } fbcon_cmap; }; /* * Frame buffer device API */ -static int platinum_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *fb); -static int platinum_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *fb); -static int platinum_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *fb); -static int platinum_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info); -static int platinum_set_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info); -static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *fb); -static int platinum_blank(int blank, struct fb_info *fb); - - -/* - * Interface to the low level console driver - */ - -static int platinum_switch(int con, struct fb_info *fb); -static int platinum_updatevar(int con, struct fb_info *fb); +static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); +static int platinumfb_blank(int blank_mode, struct fb_info *info); +static int platinumfb_set_par (struct fb_info *info); +static int platinumfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); /* * internal functions @@ -125,21 +100,14 @@ static void platinum_of_init(struct device_node *dp); static inline int platinum_vram_reqd(int video_mode, int color_mode); static int read_platinum_sense(struct fb_info_platinum *info); static void set_platinum_clock(struct fb_info_platinum *info); -static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_platinum *info); +static void platinum_set_hardware(struct fb_info_platinum *info, + const struct fb_par_platinum *par); static int platinum_par_to_var(struct fb_var_screeninfo *var, const struct fb_par_platinum *par, const struct fb_info_platinum *info); static int platinum_var_to_par(const struct fb_var_screeninfo *var, struct fb_par_platinum *par, const struct fb_info_platinum *info); -static int platinum_encode_fix(struct fb_fix_screeninfo *fix, - const struct fb_par_platinum *par, - const struct fb_info_platinum *info); -static void platinum_set_dispsw(struct display *disp, - struct fb_info_platinum *info, int cmode, - int accel); -static int platinum_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp, struct fb_info *fb); /* * Interface used by the world @@ -150,202 +118,65 @@ int platinum_setup(char*); static struct fb_ops platinumfb_ops = { .owner = THIS_MODULE, - .fb_get_fix = platinum_get_fix, - .fb_get_var = platinum_get_var, - .fb_set_var = platinum_set_var, - .fb_get_cmap = platinum_get_cmap, - .fb_set_cmap = platinum_set_cmap, - .fb_setcolreg = platinum_setcolreg, - .fb_blank = platinum_blank, + .fb_set_var = gen_set_var, + .fb_check_var = platinumfb_check_var, + .fb_set_par = platinumfb_set_par, + .fb_get_cmap = gen_get_cmap, + .fb_set_cmap = gen_set_cmap, + .fb_setcolreg = platinumfb_setcolreg, + .fb_blank = platinumfb_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, }; -static int platinum_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *fb) +/* + * Checks a var structure + */ +static int platinumfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info) { - const struct fb_info_platinum *info = (struct fb_info_platinum *)fb; + struct fb_info_platinum *p = (struct fb_info_platinum *) info; struct fb_par_platinum par; - - if (con == -1) - par = info->default_par; - else - platinum_var_to_par(&fb_display[con].var, &par, info); - - platinum_encode_fix(fix, &par, info); - return 0; -} - -static int platinum_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *fb) -{ - const struct fb_info_platinum *info = (struct fb_info_platinum *)fb; - - if (con == -1) - platinum_par_to_var(var, &info->default_par, info); - else - *var = fb_display[con].var; + int err; + + err = platinum_var_to_par(var, &par, p); + if (err) + return err; + platinum_par_to_var(var, &par, p); return 0; } -static void platinum_set_dispsw(struct display *disp, - struct fb_info_platinum *info, int cmode, - int accel) -{ - switch(cmode) { -#ifdef FBCON_HAS_CFB8 - case CMODE_8: - disp->dispsw = &fbcon_cfb8; - break; -#endif -#ifdef FBCON_HAS_CFB16 - case CMODE_16: - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = info->fbcon_cmap.cfb16; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case CMODE_32: - disp->dispsw = &fbcon_cfb32; - disp->dispsw_data = info->fbcon_cmap.cfb32; - break; -#endif - default: - disp->dispsw = &fbcon_dummy; - break; - } -} - -static int platinum_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *fb) +/* + * Applies current var to display + */ +static int platinumfb_set_par (struct fb_info *info) { - struct fb_info_platinum *info = (struct fb_info_platinum *) fb; - struct fb_par_platinum par; - struct display *display; - int oldxres, oldyres, oldvxres, oldvyres, oldbpp, err; - int activate = var->activate; + struct fb_info_platinum *p = (struct fb_info_platinum *) info; struct platinum_regvals *init; + struct fb_par_platinum par; + int err; - display = (con >= 0) ? &fb_display[con] : fb->disp; - - if((err = platinum_var_to_par(var, &par, info))) { - printk(KERN_ERR "platinum_set_var: error calling platinum_var_to_par: %d.\n", err); + if((err = platinum_var_to_par(&info->var, &par, p))) { + printk (KERN_ERR "platinumfb_set_par: error calling" + " platinum_var_to_par: %d.\n", err); return err; } - - platinum_par_to_var(var, &par, info); - - if ((activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) { - printk(KERN_INFO "platinum_set_var: Not activating.\n"); - return 0; - } - - init = platinum_reg_init[par.vmode-1]; - - oldxres = display->var.xres; - oldyres = display->var.yres; - oldvxres = display->var.xres_virtual; - oldvyres = display->var.yres_virtual; - oldbpp = display->var.bits_per_pixel; - display->var = *var; - - if (oldxres != var->xres || oldyres != var->yres || - oldvxres != var->xres_virtual || oldyres != var->yres_virtual || - oldbpp != var->bits_per_pixel) { - struct fb_fix_screeninfo fix; - - platinum_encode_fix(&fix, &par, info); - info->fb_info.screen_base = (char *) info->frame_buffer + init->fb_offset + 0x20; - display->visual = fix.visual; - display->type = fix.type; - display->type_aux = fix.type_aux; - display->ypanstep = fix.ypanstep; - display->ywrapstep = fix.ywrapstep; - display->line_length = fix.line_length; - display->can_soft_blank = 1; - display->inverse = 0; - platinum_set_dispsw(display, info, par.cmode, 0); - display->scrollmode = SCROLL_YREDRAW; - if (info->fb_info.changevar) - (*info->fb_info.changevar)(con); - } - - if (!info->fb_info.display_fg || - info->fb_info.display_fg->vc_num == con) - platinum_set_par(&par, info); - - if (oldbpp != var->bits_per_pixel) { - if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) - return err; - do_install_cmap(con, &info->fb_info); - } - - return 0; -} - -static int platinum_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) -{ - if (!info->display_fg || - info->display_fg->vc_num == con) /* current console? */ - return fb_get_cmap(cmap, kspc, platinum_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); - } - return 0; -} - -static int platinum_set_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) -{ - int err; - struct display *disp; - - if (con >= 0) - disp = &fb_display[con]; - else - disp = info->disp; - if (!disp->cmap.len) { /* no colormap allocated? */ - int size = disp->var.bits_per_pixel == 16 ? 32 : 256; - if ((err = fb_alloc_cmap(&disp->cmap, size, 0))) - return err; - } - - if (!info->display_fg || - info->display_fg->vc_num == con) /* current console? */ - return fb_set_cmap(cmap, kspc, info); - else - fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); - return 0; -} -static int platinum_switch(int con, struct fb_info *fb) -{ - struct fb_info_platinum *info = (struct fb_info_platinum *) fb; - struct fb_par_platinum par; - - if (fb_display[fb->currcon].cmap.len) - fb_get_cmap(&fb_display[fb->currcon].cmap, 1, platinum_getcolreg, - fb); - fb->currcon = con; + platinum_set_hardware(p, &par); - platinum_var_to_par(&fb_display[con].var, &par, info); - platinum_set_par(&par, info); - platinum_set_dispsw(&fb_display[con], info, par.cmode, 0); - do_install_cmap(con, fb); - - return 1; -} + init = platinum_reg_init[p->par.vmode-1]; + + info->screen_base = (char *) p->frame_buffer + init->fb_offset + 0x20; + info->fix.smem_start = (p->frame_buffer_phys) + init->fb_offset + 0x20; + info->fix.visual = (p->par.cmode == CMODE_8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; + info->fix.line_length = vmode_attrs[p->par.vmode-1].hres * (1<<p->par.cmode) + 0x20; -static int platinum_updatevar(int con, struct fb_info *fb) -{ - printk(KERN_ERR "platinum_updatevar is doing nothing yet.\n"); return 0; } -static int platinum_blank(int blank, struct fb_info *fb) +static int platinumfb_blank(int blank, struct fb_info *fb) { /* * Blank the screen if blank_mode != 0, else unblank. If blank == NULL @@ -375,26 +206,11 @@ static int platinum_blank(int blank, struct fb_info *fb) return 0; } -static int platinum_getcolreg(u_int regno, u_int *red, u_int *green, - u_int *blue, u_int *transp, struct fb_info *fb) -{ - struct fb_info_platinum *info = (struct fb_info_platinum *) fb; - - if (regno > 255) - return 1; - - *red = (info->palette[regno].red<<8) | info->palette[regno].red; - *green = (info->palette[regno].green<<8) | info->palette[regno].green; - *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue; - *transp = 0; - return 0; -} - -static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *fb) +static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) { - struct fb_info_platinum *info = (struct fb_info_platinum *) fb; - volatile struct cmap_regs *cmap_regs = info->cmap_regs; + struct fb_info_platinum *p = (struct fb_info_platinum *) info; + volatile struct cmap_regs *cmap_regs = p->cmap_regs; if (regno > 255) return 1; @@ -403,23 +219,30 @@ static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue, green >>= 8; blue >>= 8; - info->palette[regno].red = red; - info->palette[regno].green = green; - info->palette[regno].blue = blue; + p->palette[regno].red = red; + p->palette[regno].green = green; + p->palette[regno].blue = blue; out_8(&cmap_regs->addr, regno); /* tell clut what addr to fill */ out_8(&cmap_regs->lut, red); /* send one color channel at */ out_8(&cmap_regs->lut, green); /* a time... */ out_8(&cmap_regs->lut, blue); - if(regno < 16) { -#ifdef FBCON_HAS_CFB16 - info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | (regno << 0); -#endif -#ifdef FBCON_HAS_CFB32 - info->fbcon_cmap.cfb32[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno; -#endif + if (regno < 16) { + int i; + switch (p->par.cmode) { + case CMODE_16: + ((u16 *) (info->pseudo_palette))[regno] = + (regno << 10) | (regno << 5) | regno; + break; + case CMODE_32: + i = (regno << 8) | regno; + ((u32 *) (info->pseudo_palette))[regno] = + (i << 16) | i; + break; + } } + return 0; } @@ -439,7 +262,7 @@ static void set_platinum_clock(struct fb_info_platinum *info) volatile struct cmap_regs *cmap_regs = info->cmap_regs; struct platinum_regvals *init; - init = platinum_reg_init[info->current_par.vmode-1]; + init = platinum_reg_init[info->par.vmode-1]; STORE_D2(6, 0xc6); out_8(&cmap_regs->addr,3+32); @@ -461,7 +284,7 @@ static void set_platinum_clock(struct fb_info_platinum *info) /* Now how about actually saying, Make it so! */ /* Some things in here probably don't need to be done each time. */ -static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_platinum *info) +static void platinum_set_hardware(struct fb_info_platinum *info, const struct fb_par_platinum *par) { volatile struct platinum_regs *platinum_regs = info->platinum_regs; volatile struct cmap_regs *cmap_regs = info->cmap_regs; @@ -469,7 +292,7 @@ static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_p int i; int vmode, cmode; - info->current_par = *par; + info->par = *par; vmode = par->vmode; cmode = par->cmode; @@ -509,15 +332,52 @@ static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_p out_be32(&platinum_regs->reg[24].r, 0); /* turn display on */ } +/* + * Set misc info vars for this driver + */ +static void __init platinum_init_info(struct fb_info *info, struct fb_info_platinum *p) +{ + /* Fill fb_info */ + strcpy(info->modename, "platinum"); + info->currcon = -1; + info->par = &p->par; + info->node = NODEV; + info->fbops = &platinumfb_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 + 0x20; + info->changevar = NULL; + info->switch_con = gen_switch; + info->updatevar = gen_update_var; + + fb_alloc_cmap(&info->cmap, 256, 0); + + /* Fill fix common fields */ + strcpy(info->fix.id, "platinum"); + info->fix.mmio_start = p->platinum_regs_phys; + info->fix.mmio_len = 0x1000; + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.smem_start = p->frame_buffer_phys + 0x20; /* will be updated later */ + info->fix.smem_len = p->total_vram - 0x20; + info->fix.ywrapstep = 0; + info->fix.xpanstep = 0; + info->fix.ypanstep = 0; + info->fix.type_aux = 0; + info->fix.accel = FB_ACCEL_NONE; +} + -static int __init init_platinum(struct fb_info_platinum *info) +static int __init init_platinum(struct fb_info_platinum *p) { struct fb_var_screeninfo var; - struct display *disp; - int sense; - int j,k; + int sense, rc; - sense = read_platinum_sense(info); + sense = read_platinum_sense(p); printk(KERN_INFO "Monitor sense value = 0x%x, ", sense); if (default_vmode == VMODE_NVRAM) { @@ -538,44 +398,40 @@ static int __init init_platinum(struct fb_info_platinum *info) /* * Reduce the pixel size if we don't have enough VRAM. */ - while(default_cmode > CMODE_8 && platinum_vram_reqd(default_vmode, default_cmode) > info->total_vram) + while(default_cmode > CMODE_8 && platinum_vram_reqd(default_vmode, default_cmode) > p->total_vram) default_cmode--; printk("using video mode %d and color mode %d.\n", default_vmode, default_cmode); - mac_vmode_to_var(default_vmode, default_cmode, &var); - - if (platinum_var_to_par(&var, &info->default_par, info)) { - printk(KERN_ERR "platinumfb: can't set default video mode\n"); - return 0; + /* Setup default var */ + if (mac_vmode_to_var(default_vmode, default_cmode, &var) < 0) { + /* This shouldn't happen! */ + printk("mac_vmode_to_var(%d, %d,) failed\n", default_vmode, default_cmode); +try_again: + default_vmode = VMODE_640_480_60; + default_cmode = CMODE_8; + if (mac_vmode_to_var(default_vmode, default_cmode, &var) < 0) { + printk(KERN_ERR "platinumfb: mac_vmode_to_var() failed\n"); + return -ENXIO; + } } - disp = &info->disp; - - strcpy(info->fb_info.modename, "platinum"); - info->fb_info.node = NODEV; - info->fb_info.fbops = &platinumfb_ops; - info->fb_info.disp = disp; - info->fb_info.currcon = -1; - strcpy(info->fb_info.fontname, fontname); - info->fb_info.changevar = NULL; - info->fb_info.switch_con = &platinum_switch; - info->fb_info.updatevar = &platinum_updatevar; - info->fb_info.flags = FBINFO_FLAG_DEFAULT; - - for (j = 0; j < 16; j++) { - k = color_table[j]; - info->palette[j].red = default_red[k]; - info->palette[j].green = default_grn[k]; - info->palette[j].blue = default_blu[k]; - } - platinum_set_var(&var, -1, &info->fb_info); + /* Initialize info structure */ + platinum_init_info(&p->info, p); - if (register_framebuffer(&info->fb_info) < 0) + /* Apply default var */ + p->info.var = var; + var.activate = FB_ACTIVATE_NOW; + rc = gen_set_var(&var, -1, &p->info); + if (rc && (default_vmode != VMODE_640_480_60 || default_cmode != CMODE_8)) + goto try_again; + + /* Register with fbdev layer */ + if (register_framebuffer(&p->info) < 0) return 0; printk(KERN_INFO "fb%d: platinum frame buffer device\n", - GET_FB_IDX(info->fb_info.node)); + GET_FB_IDX(p->info.node)); return 1; } @@ -761,33 +617,6 @@ static int platinum_par_to_var(struct fb_var_screeninfo *var, return mac_vmode_to_var(par->vmode, par->cmode, var); } -static int platinum_encode_fix(struct fb_fix_screeninfo *fix, - const struct fb_par_platinum *par, - const struct fb_info_platinum *info) -{ - struct platinum_regvals *init; - - init = platinum_reg_init[par->vmode-1]; - - memset(fix, 0, sizeof(*fix)); - strcpy(fix->id, "platinum"); - fix->smem_start = (info->frame_buffer_phys) + init->fb_offset + 0x20; - fix->smem_len = (u32) info->total_vram; - fix->mmio_start = (info->platinum_regs_phys); - fix->mmio_len = 0x1000; - fix->type = FB_TYPE_PACKED_PIXELS; - fix->type_aux = 0; - fix->ywrapstep = 0; - fix->xpanstep = 0; - fix->ypanstep = 0; - fix->visual = (par->cmode == CMODE_8) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; - fix->line_length = vmode_attrs[par->vmode-1].hres * (1<<par->cmode) + 0x20; - - return 0; -} - - /* * Parse user speficied options (`video=platinumfb:') */ diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 168f4ec92505..2141b8d8a65a 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -2289,7 +2289,7 @@ int __init pm2fb_init(void) { return -EINVAL; } printk(KERN_INFO "fb%d: %s (%s), using %uK of video memory.\n", - GET_FB_IDX(fb_info.gen.info.node), + minor(fb_info.gen.info.node), board_table[fb_info.board].name, permedia2_name, (u32 )(fb_info.regions.fb_size>>10)); diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 0653a9650718..7bdc0abe61df 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c @@ -1647,7 +1647,7 @@ static void pm3fb_common_init(struct pm3fb_info *l_fb_info) pm3fb_write_mode(l_fb_info); printk("fb%d: %s, using %uK of video memory (%s)\n", - GET_FB_IDX(l_fb_info->gen.info.node), + minor(l_fb_info->gen.info.node), permedia3_name, (u32) (l_fb_info->fb_size >> 10), cardbase[l_fb_info->board_type].cardname); } diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index aba95ee840c4..18b756278fec 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -36,8 +36,6 @@ #include <asm/dec/tc.h> #include "pmag-ba-fb.h" -#include <video/fbcon.h> - struct pmag_ba_ramdac_regs { unsigned char addr_low; unsigned char pad0[3]; @@ -52,28 +50,30 @@ struct pmag_ba_ramdac_regs { * Max 3 TURBOchannel slots -> max 3 PMAG-BA :) */ static struct fb_info pmagba_fb_info[3]; -static struct display pmagba_disp[3]; static struct fb_var_screeninfo pmagbafb_defined = { - .xres = 1024, - .yres = 864, - .xres_virtual = 1024, - .yres_virtual = 864, - .bits_per_pixel =8, - .activate = FB_ACTIVATE_NOW, - .height = 274, - .width = 195, - .accel = FB_ACCEL_NONE, - .vmode = FB_VMODE_NONINTERLACED, -} + .xres = 1024, + .yres = 864, + .xres_virtual = 1024, + .yres_virtual = 864, + .bits_per_pixel = 8, + .red.length = 8, + .green.length = 8, + .blue.length = 8, + .activate = FB_ACTIVATE_NOW, + .height = 274, + .width = 195, + .accel = FB_ACCEL_NONE, + .vmode = FB_VMODE_NONINTERLACED, +}; static struct fb_fix_screeninfo pmagbafb_fix = { - .id = "PMAG-BA", - .smem_len = (1024 * 864), - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_PSEUDOCOLOR, - .line_length = 1024, -} + .id = "PMAG-BA", + .smem_len = (1024 * 864), + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .line_length = 1024, +}; /* * Turn hardware cursor off @@ -111,20 +111,17 @@ static int pmagbafb_setcolreg(unsigned regno, unsigned red, unsigned green, static struct fb_ops pmagbafb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = pmagbafb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, -} + .fb_cursor = soft_cursor, +}; int __init pmagbafb_init_one(int slot) { unsigned long base_addr = get_tc_base_addr(slot); struct fb_info *info = &pmagba_fb_info[slot]; - struct display *disp = &pmagba_disp[slot]; printk("PMAG-BA framebuffer in slot %d\n", slot); /* @@ -141,21 +138,14 @@ int __init pmagbafb_init_one(int slot) /* * Let there be consoles.. */ - strcpy(info->modename, pmagbafb_fix.id); - info->changevar = NULL; info->node = NODEV; info->fbops = &pmagbafb_ops; info->var = pmagbafb_defined; info->fix = pmagbafb_fix; info->screen_base = pmagbafb_fix.smem_start; - info->disp = &disp; - info->currcon = -1; - info->switch_con = gen_switch; - info->updatevar = gen_update_var; info->flags = FBINFO_FLAG_DEFAULT; fb_alloc_cmap(&fb_info.cmap, 256, 0); - gen_set_disp(-1, info); if (register_framebuffer(info) < 0) return 1; @@ -183,9 +173,4 @@ int __init pmagbafb_init(void) } } -int __init pmagbafb_setup(char *options) -{ - return 0; -} - MODULE_LICENSE("GPL"); diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index 9d95f157ce46..5c2108d8a7fb 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -39,8 +39,6 @@ #include <asm/dec/tc.h> #include "pmagb-b-fb.h" -#include <video/fbcon.h> - struct pmagb_b_ramdac_regs { unsigned char addr_low; unsigned char pad0[3]; @@ -55,27 +53,29 @@ struct pmagb_b_ramdac_regs { * Max 3 TURBOchannel slots -> max 3 PMAGB-B :) */ static struct fb_info pmagbb_fb_info[3]; -static struct display pmagbb_disp[3]; static struct fb_var_screeninfo pmagbbfb_defined = { - .xres = 1280, - .yres = 1024, - .xres_virtual = 1280, - .yres_virtual = 1024, - .bits_per_pixel =8, - .activate = FB_ACTIVATE_NOW, - .height = 274, - .width = 195, - .accel_flags = FB_ACCEL_NONE, - .vmode = FB_VMODE_NONINTERLACED, + .xres = 1280, + .yres = 1024, + .xres_virtual = 1280, + .yres_virtual = 1024, + .bits_per_pixel = 8, + .red.length = 8, + .green.length = 8, + .blue.length = 8, + .activate = FB_ACTIVATE_NOW, + .height = 274, + .width = 195, + .accel_flags = FB_ACCEL_NONE, + .vmode = FB_VMODE_NONINTERLACED, }; static struct fb_fix_screeninfo pmagbafb_fix = { - .id = "PMAGB-BA", - .smem_len = (1280 * 1024), - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_PSEUDOCOLOR, - .line_length = 1280, + .id = "PMAGB-BA", + .smem_len = (1280 * 1024), + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .line_length = 1280, } /* @@ -114,20 +114,17 @@ static int pmagbbfb_setcolreg(unsigned regno, unsigned red, unsigned green, static struct fb_ops pmagbbfb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = pmagbbfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; int __init pmagbbfb_init_one(int slot) { unsigned long base_addr = get_tc_base_addr(slot); struct fb_info *info = &pmagbb_fb_info[slot]; - struct display *disp = &pmagbb_disp[slot]; printk("PMAGB-BA framebuffer in slot %d\n", slot); /* @@ -144,21 +141,14 @@ int __init pmagbbfb_init_one(int slot) /* * Let there be consoles.. */ - strcpy(info->modename, pmagbbfb_fix.id); - info->changevar = NULL; info->node = NODEV; info->fbops = &pmagbbfb_ops; info->var = pmagbbfb_defined; info->fix = pmagbbfb_fix; info->screen_base = pmagbbfb_fix.smem_start; - info->disp = &disp; - info->currcon = -1; - info->switch_con = gen_switch; - info->updatevar = gen_update_var; info->flags = FBINFO_FLAG_DEFAULT; fb_alloc_cmap(&fb_info.cmap, 256, 0); - gen_set_disp(-1, info); if (register_framebuffer(info) < 0) return 1; @@ -186,9 +176,4 @@ int __init pmagbbfb_init(void) } } -int __init pmagbbfb_setup(char *options) -{ - return 0; -} - MODULE_LICENSE("GPL"); diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 1b0725a11cbc..0790fbf9db7d 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -1059,10 +1059,10 @@ int __init pvr2fb_init(void) modememused = get_line_length(var.xres_virtual, var.bits_per_pixel); modememused *= var.yres_virtual; printk("fb%d: %s frame buffer device, using %ldk/%ldk of video memory\n", - GET_FB_IDX(fb_info.node), fb_info.modename, modememused>>10, + minor(fb_info.node), fb_info.modename, modememused>>10, videomemorysize>>10); printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", - GET_FB_IDX(fb_info.node), var.xres, var.yres, var.bits_per_pixel, + minor(fb_info.node), var.xres, var.yres, var.bits_per_pixel, get_line_length(var.xres, var.bits_per_pixel), (char *)pvr2_get_param(cables, NULL, cable_type, 3), (char *)pvr2_get_param(outputs, NULL, video_output, 3)); diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 97b036f6cce0..7093cd15b7a6 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c @@ -28,13 +28,10 @@ #include <linux/module.h> #include <asm/pgtable.h> -#include <video/fbcon.h> - #define Q40_PHYS_SCREEN_ADDR 0xFE800000 static u32 pseudo_palette[17]; static struct fb_info fb_info; -static struct display display; static struct fb_fix_screeninfo q40fb_fix __initdata = { .id = "Q40", @@ -69,13 +66,11 @@ static int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green, static struct fb_ops q40fb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = q40fb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; static int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green, @@ -117,15 +112,8 @@ int q40fb_init(void) fb_info.screen_base = (char *) q40fb_fix.smem_start; /* The below feilds will go away !!!! */ - fb_info.currcon = -1; - strcpy(fb_info.modename, fb_info.fix.id); - fb_info.disp = &display; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_alloc_cmap(&fb_info.cmap, 16, 0); - gen_set_disp(-1, &fb_info); - master_outb(3, DISPLAY_CONTROL_REG); if (register_framebuffer(&fb_info) < 0) { @@ -134,7 +122,7 @@ int q40fb_init(void) } printk(KERN_INFO "fb%d: Q40 frame buffer alive and kicking !\n", - GET_FB_IDX(fb_info.node)); + minor(fb_info.node)); return 0; } diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index b55a6b503e7c..ea8466a9bd7a 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -2,7 +2,7 @@ * drivers/video/radeonfb.c * framebuffer driver for ATI Radeon chipset video boards * - * Copyright 2000 Ani Joshi <ajoshi@unixbox.com> + * Copyright 2000 Ani Joshi <ajoshi@kernel.crashing.org> * * * ChangeLog: @@ -15,13 +15,21 @@ * blanking, pan_display, and cmap fixes, 0.1.0 * 2001-10-10 Radeon 7500 and 8500 support, and experimental * flat panel support, 0.1.1 + * 2001-11-17 Radeon M6 (ppc) support, Daniel Berlin, 0.1.2 + * 2001-11-18 DFP fixes, Kevin Hendricks, 0.1.3 + * 2001-11-29 more cmap, backlight fixes, Benjamin Herrenschmidt + * 2002-01-18 DFP panel detection via BIOS, Michael Clark, 0.1.4 + * 2002-06-02 console switching, mode set fixes, accel fixes + * 2002-06-03 MTRR support, Peter Horton, 0.1.5 + * 2002-09-21 rv250, r300, m9 initial support, + * added mirror option, 0.1.6 * * Special thanks to ATI DevRel team for their hardware donations. * */ -#define RADEON_VERSION "0.1.1" +#define RADEON_VERSION "0.1.6" #include <linux/config.h> @@ -34,27 +42,45 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/fb.h> -#include <linux/console.h> -#include <linux/selection.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/pci.h> +#include <linux/vmalloc.h> #include <asm/io.h> +#include <asm/uaccess.h> #if defined(__powerpc__) #include <asm/prom.h> +#include <asm/pci-bridge.h> +#include "macmodes.h" + +#ifdef CONFIG_NVRAM +#include <linux/nvram.h> #endif -#include <video/fbcon.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-cfb24.h> -#include <video/fbcon-cfb32.h> +#ifdef CONFIG_PMAC_BACKLIGHT +#include <asm/backlight.h> +#endif -#include "radeon.h" +#ifdef CONFIG_BOOTX_TEXT +#include <asm/btext.h> +#endif +#ifdef CONFIG_ADB_PMU +#include <linux/adb.h> +#include <linux/pmu.h> +#endif -#define DEBUG 0 +#endif /* __powerpc__ */ + +#ifdef CONFIG_MTRR +#include <asm/mtrr.h> +#endif + +#include <video/radeon.h> +#include <linux/radeonfb.h> + +#define DEBUG 1 #if DEBUG #define RTRACE printk @@ -62,6 +88,8 @@ #define RTRACE if(0) printk #endif +// XXX +#undef CONFIG_PMAC_PBOOK enum radeon_chips { @@ -71,11 +99,76 @@ enum radeon_chips { RADEON_QG, RADEON_QY, RADEON_QZ, - RADEON_QL, - RADEON_QW, RADEON_LW, + RADEON_LX, RADEON_LY, - RADEON_LZ + RADEON_LZ, + RADEON_QL, + RADEON_QN, + RADEON_QO, + RADEON_Ql, + RADEON_BB, + RADEON_QW, + RADEON_QX, + RADEON_Id, + RADEON_Ie, + RADEON_If, + RADEON_Ig, + RADEON_Ld, + RADEON_Le, + RADEON_Lf, + RADEON_Lg, + RADEON_ND, + RADEON_NE, + RADEON_NF, + RADEON_NG +}; + +enum radeon_arch { + RADEON_R100, + RADEON_RV100, + RADEON_R200, + RADEON_RV200, + RADEON_RV250, + RADEON_R300, + RADEON_M6, + RADEON_M7, + RADEON_M9 +}; + +static struct radeon_chip_info { + const char *name; + unsigned char arch; +} radeon_chip_info[] __devinitdata = { + { "QD", RADEON_R100 }, + { "QE", RADEON_R100 }, + { "QF", RADEON_R100 }, + { "QG", RADEON_R100 }, + { "VE QY", RADEON_RV100 }, + { "VE QZ", RADEON_RV100 }, + { "M7 LW", RADEON_M7 }, + { "M7 LX", RADEON_M7 }, + { "M6 LY", RADEON_M6 }, + { "M6 LZ", RADEON_M6 }, + { "8500 QL", RADEON_R200 }, + { "8500 QN", RADEON_R200 }, + { "8500 QO", RADEON_R200 }, + { "8500 Ql", RADEON_R200 }, + { "8500 BB", RADEON_R200 }, + { "7500 QW", RADEON_RV200 }, + { "7500 QX", RADEON_RV200 }, + { "9000 Id", RADEON_RV250 }, + { "9000 Ie", RADEON_RV250 }, + { "9000 If", RADEON_RV250 }, + { "9000 Ig", RADEON_RV250 }, + { "M9 Ld", RADEON_M9 }, + { "M9 Le", RADEON_M9 }, + { "M9 Lf", RADEON_M9 }, + { "M9 Lg", RADEON_M9 }, + { "9700 ND", RADEON_R300 }, + { "9700 NE", RADEON_R300 }, + { "9700 NF", RADEON_R300 }, + { "9700 NG", RADEON_R300 } }; @@ -91,17 +184,35 @@ enum radeon_montype static struct pci_device_id radeonfb_pci_table[] __devinitdata = { - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QD}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QE}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QF}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QG}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QY}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QZ}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QL}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QW}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_LW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LW}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_LY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LY}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_LZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LZ}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QD}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QE}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QF}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QG}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QY}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QZ}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LW}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LX}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LY}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LZ}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QL}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QN, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QN}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QO}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ql, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ql}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_BB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_BB}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QW}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QX}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Id}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ie, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ie}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_If, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_If}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ig, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ig}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ld, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ld}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Le, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Le}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lf}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lg, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lg}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_ND, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_ND}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NE}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NF}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NG}, { 0, } }; MODULE_DEVICE_TABLE(pci, radeonfb_pci_table); @@ -128,7 +239,15 @@ reg_val common_regs[] = { { CAP0_TRIG_CNTL, 0 }, }; -#define COMMON_REGS_SIZE = (sizeof(common_regs)/sizeof(common_regs[0])) +reg_val common_regs_m6[] = { + { OVR_CLR, 0 }, + { OVR_WID_LEFT_RIGHT, 0 }, + { OVR_WID_TOP_BOTTOM, 0 }, + { OV0_SCALE_CNTL, 0 }, + { SUBPIC_CNTL, 0 }, + { GEN_INT_CNTL, 0 }, + { CAP0_TRIG_CNTL, 0 } +}; typedef struct { u8 clock_chip_type; @@ -192,7 +311,6 @@ struct radeon_regs { u32 flags; u32 pix_clock; int xres, yres; - int bpp; /* DDA regs */ u32 dda_config; @@ -201,7 +319,8 @@ struct radeon_regs { /* PLL regs */ u32 ppll_div_3; u32 ppll_ref_div; - + u32 vclk_ecp_cntl; + /* Flat panel regs */ u32 fp_crtc_h_total_disp; u32 fp_crtc_v_total_disp; @@ -214,6 +333,7 @@ struct radeon_regs { u32 lvds_gen_cntl; u32 lvds_pll_cntl; u32 tmds_crc; + u32 tmds_transmitter_cntl; #if defined(__BIG_ENDIAN) u32 surface_cntl; @@ -227,35 +347,47 @@ struct radeonfb_info { struct radeon_regs state; struct radeon_regs init_state; - char name[17]; + char name[32]; char ram_type[12]; - u32 mmio_base_phys; - u32 fb_base_phys; + unsigned long mmio_base_phys; + unsigned long fb_base_phys; - u32 mmio_base; - u32 fb_base; + unsigned long mmio_base; + unsigned long fb_base; struct pci_dev *pdev; - struct display disp; - struct display *currcon_display; + unsigned char *EDID; + unsigned char *bios_seg; + + struct display disp; /* Will disappear */ + u32 pseudo_palette[17]; struct { u8 red, green, blue, pad; } palette[256]; int chipset; + unsigned char arch; int video_ram; u8 rev; int pitch, bpp, depth; int xres, yres, pixclock; + int xres_virtual, yres_virtual; + u32 accel_flags; + + int use_default_var; + int got_dfpinfo; int hasCRTC2; int crtDisp_type; int dviDisp_type; int panel_xres, panel_yres; + int clock; int hOver_plus, hSync_width, hblank; int vOver_plus, vSync_width, vblank; + int hAct_high, vAct_high, interlaced; + int synct, misc; u32 dp_gui_master_cntl; @@ -264,22 +396,16 @@ struct radeonfb_info { struct ram_info ram; - u32 hack_crtc_ext_cntl; - u32 hack_crtc_v_sync_strt_wid; + int mtrr_hdl; -#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) - union { -#if defined(FBCON_HAS_CFB16) - u_int16_t cfb16[16]; -#endif -#if defined(FBCON_HAS_CFB24) - u_int32_t cfb24[16]; -#endif -#if defined(FBCON_HAS_CFB32) - u_int32_t cfb32[16]; -#endif - } con_cmap; -#endif +#ifdef CONFIG_PMAC_PBOOK + int pm_reg; + u32 save_regs[64]; + u32 mdll, mdll2; +#endif /* CONFIG_PMAC_PBOOK */ + int asleep; + + struct radeonfb_info *next; }; @@ -290,7 +416,6 @@ static struct fb_var_screeninfo radeonfb_default_var = { 0, FB_VMODE_NONINTERLACED }; - /* * IO macros */ @@ -300,8 +425,12 @@ static struct fb_var_screeninfo radeonfb_default_var = { #define INREG(addr) readl((rinfo->mmio_base)+addr) #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) -#define OUTPLL(addr,val) OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000001f) | 0x00000080); \ - OUTREG(CLOCK_CNTL_DATA, val) +#define OUTPLL(addr,val) \ + do { \ + OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \ + OUTREG(CLOCK_CNTL_DATA, val); \ + } while(0) + #define OUTPLLP(addr,val,mask) \ do { \ unsigned int _tmp = INPLL(addr); \ @@ -321,7 +450,7 @@ static struct fb_var_screeninfo radeonfb_default_var = { static __inline__ u32 _INPLL(struct radeonfb_info *rinfo, u32 addr) { - OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000001f); + OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f); return (INREG(CLOCK_CNTL_DATA)); } @@ -432,6 +561,14 @@ static __inline__ u32 radeon_get_dstbpp(u16 depth) } +static inline int var_to_depth(const struct fb_var_screeninfo *var) +{ + if (var->bits_per_pixel != 16) + return var->bits_per_pixel; + return (var->green.length == 6) ? 16 : 15; +} + + static void _radeon_engine_reset(struct radeonfb_info *rinfo) { u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; @@ -457,8 +594,7 @@ static void _radeon_engine_reset(struct radeonfb_info *rinfo) SOFT_RESET_RE | SOFT_RESET_PP | SOFT_RESET_E2 | - SOFT_RESET_RB | - SOFT_RESET_HDP); + SOFT_RESET_RB); INREG(RBBM_SOFT_RESET); OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32) ~(SOFT_RESET_CP | @@ -467,8 +603,7 @@ static void _radeon_engine_reset(struct radeonfb_info *rinfo) SOFT_RESET_RE | SOFT_RESET_PP | SOFT_RESET_E2 | - SOFT_RESET_RB | - SOFT_RESET_HDP)); + SOFT_RESET_RB)); INREG(RBBM_SOFT_RESET); OUTPLL(MCLK_CNTL, mclk_cntl); @@ -542,416 +677,57 @@ static __inline__ int _max(int val1, int val2) * globals */ -static char fontname[40] __initdata; static char *mode_option __initdata; -static char noaccel __initdata = 0; -static char panel_yres __initdata = 0; - -#ifdef FBCON_HAS_CFB8 -static struct display_switch fbcon_radeon8; -#endif - +static char noaccel = 1; +static char mirror = 0; +static int panel_yres __initdata = 0; +static char force_dfp __initdata = 0; +static struct radeonfb_info *board_list = NULL; +static char nomtrr __initdata = 0; /* * prototypes */ -static int radeonfb_get_fix (struct fb_fix_screeninfo *fix, int con, - struct fb_info *info); -static int radeonfb_get_var (struct fb_var_screeninfo *var, int con, - struct fb_info *info); -static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, - struct fb_info *info); -static int radeonfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info); -static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, struct fb_info *info); -static int radeonfb_pan_display (struct fb_var_screeninfo *var, int con, - struct fb_info *info); -static int radeonfb_blank (int blank, struct fb_info *info); -static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, int con, struct fb_info *info); -static int radeonfb_switch (int con, struct fb_info *info); -static int radeonfb_updatevar (int con, struct fb_info *info); -static int radeon_get_cmap_len (const struct fb_var_screeninfo *var); -static int radeon_getcolreg (unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info); -static void radeon_set_dispsw (struct radeonfb_info *rinfo, struct display *disp); static void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save); static void radeon_engine_init (struct radeonfb_info *rinfo); -static void radeon_load_video_mode (struct radeonfb_info *rinfo, - struct fb_var_screeninfo *mode); static void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode); static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo); static int __devinit radeon_init_disp (struct radeonfb_info *rinfo); -static int radeon_init_disp_var (struct radeonfb_info *rinfo); -static int radeonfb_pci_register (struct pci_dev *pdev, - const struct pci_device_id *ent); -static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev); +static int radeon_init_disp_var (struct radeonfb_info *rinfo, struct fb_var_screeninfo *var); static char *radeon_find_rom(struct radeonfb_info *rinfo); static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg); static void radeon_get_moninfo (struct radeonfb_info *rinfo); static int radeon_get_dfpinfo (struct radeonfb_info *rinfo); -static int radeon_read_OF (struct radeonfb_info *rinfo); +static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo); +static void radeon_get_EDID(struct radeonfb_info *rinfo); +static int radeon_dfp_parse_EDID(struct radeonfb_info *rinfo); +static void radeon_update_default_var(struct radeonfb_info *rinfo); -#if defined(__powerpc__) +#ifdef CONFIG_ALL_PPC + +static int radeon_read_OF (struct radeonfb_info *rinfo); +static int radeon_get_EDID_OF(struct radeonfb_info *rinfo); extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev); -#endif -static struct fb_ops radeon_fb_ops = { - .fb_get_fix = radeonfb_get_fix, - .fb_get_var = radeonfb_get_var, - .fb_set_var = radeonfb_set_var, - .fb_get_cmap = radeonfb_get_cmap, - .fb_set_cmap = gen_set_cmap, - .fb_setcolreg = radeonfb_setcolreg, - .fb_pan_display = radeonfb_pan_display, - .fb_blank = radeonfb_blank, - .fb_ioctl = radeonfb_ioctl, +#ifdef CONFIG_PMAC_PBOOK +int radeon_sleep_notify(struct pmu_sleep_notifier *self, int when); +static struct pmu_sleep_notifier radeon_sleep_notifier = { + radeon_sleep_notify, SLEEP_LEVEL_VIDEO, }; - - -static struct pci_driver radeonfb_driver = { - .name = "radeonfb", - .id_table = radeonfb_pci_table, - .probe = radeonfb_pci_register, - .remove = __devexit_p(radeonfb_pci_unregister), +#endif /* CONFIG_PMAC_PBOOK */ +#ifdef CONFIG_PMAC_BACKLIGHT +static int radeon_set_backlight_enable(int on, int level, void *data); +static int radeon_set_backlight_level(int level, void *data); +static struct backlight_controller radeon_backlight_controller = { + radeon_set_backlight_enable, + radeon_set_backlight_level }; +#endif /* CONFIG_PMAC_BACKLIGHT */ - -int __init radeonfb_init (void) -{ - return pci_module_init (&radeonfb_driver); -} - - -void __exit radeonfb_exit (void) -{ - pci_unregister_driver (&radeonfb_driver); -} - - -int __init radeonfb_setup (char *options) -{ - char *this_opt; - - if (!options || !*options) - return 0; - - while ((this_opt = strsep (&options, ",")) != NULL) { - if (!*this_opt) - continue; - if (!strncmp (this_opt, "font:", 5)) { - char *p; - int i; - - p = this_opt + 5; - for (i=0; i<sizeof (fontname) - 1; i++) - if (!*p || *p == ' ' || *p == ',') - break; - memcpy(fontname, this_opt + 5, i); - } else if (!strncmp(this_opt, "noaccel", 7)) { - noaccel = 1; - } else if (!strncmp(this_opt, "panel_yres:", 11)) { - panel_yres = simple_strtoul((this_opt+11), NULL, 0); - } else - mode_option = this_opt; - } - - return 0; -} - -#ifdef MODULE -module_init(radeonfb_init); -module_exit(radeonfb_exit); -#endif - - -MODULE_AUTHOR("Ani Joshi"); -MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset"); -MODULE_LICENSE("GPL"); - -static int radeonfb_pci_register (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct radeonfb_info *rinfo; - u32 tmp; - int i, j; - char *bios_seg = NULL; - - RTRACE("radeonfb_pci_register BEGIN\n"); - - rinfo = kmalloc (sizeof (struct radeonfb_info), GFP_KERNEL); - if (!rinfo) { - printk ("radeonfb: could not allocate memory\n"); - return -ENODEV; - } - - memset (rinfo, 0, sizeof (struct radeonfb_info)); - - rinfo->pdev = pdev; - - /* enable device */ - { - int err; - - if ((err = pci_enable_device(pdev))) { - printk("radeonfb: cannot enable device\n"); - kfree (rinfo); - return -ENODEV; - } - } - - /* set base addrs */ - rinfo->fb_base_phys = pci_resource_start (pdev, 0); - rinfo->mmio_base_phys = pci_resource_start (pdev, 2); - - /* request the mem regions */ - if (!request_mem_region (rinfo->fb_base_phys, - pci_resource_len(pdev, 0), "radeonfb")) { - printk ("radeonfb: cannot reserve FB region\n"); - kfree (rinfo); - return -ENODEV; - } - - if (!request_mem_region (rinfo->mmio_base_phys, - pci_resource_len(pdev, 2), "radeonfb")) { - printk ("radeonfb: cannot reserve MMIO region\n"); - release_mem_region (rinfo->fb_base_phys, - pci_resource_len(pdev, 0)); - kfree (rinfo); - return -ENODEV; - } - - /* map the regions */ - rinfo->mmio_base = (u32) ioremap (rinfo->mmio_base_phys, - RADEON_REGSIZE); - if (!rinfo->mmio_base) { - printk ("radeonfb: cannot map MMIO\n"); - release_mem_region (rinfo->mmio_base_phys, - pci_resource_len(pdev, 2)); - release_mem_region (rinfo->fb_base_phys, - pci_resource_len(pdev, 0)); - kfree (rinfo); - return -ENODEV; - } - - rinfo->chipset = pdev->device; - - /* chipset */ - switch (pdev->device) { - case PCI_DEVICE_ID_RADEON_QD: - strcpy(rinfo->name, "Radeon QD "); - break; - case PCI_DEVICE_ID_RADEON_QE: - strcpy(rinfo->name, "Radeon QE "); - break; - case PCI_DEVICE_ID_RADEON_QF: - strcpy(rinfo->name, "Radeon QF "); - break; - case PCI_DEVICE_ID_RADEON_QG: - strcpy(rinfo->name, "Radeon QG "); - break; - case PCI_DEVICE_ID_RADEON_QY: - strcpy(rinfo->name, "Radeon QY VE "); - rinfo->hasCRTC2 = 1; - break; - case PCI_DEVICE_ID_RADEON_QZ: - strcpy(rinfo->name, "Radeon QZ VE "); - rinfo->hasCRTC2 = 1; - break; - case PCI_DEVICE_ID_RADEON_QW: - strcpy(rinfo->name, "Radeon 7500 QW "); - rinfo->hasCRTC2 = 1; - break; - case PCI_DEVICE_ID_RADEON_QL: - strcpy(rinfo->name, "Radeon 8500 QL "); - rinfo->hasCRTC2 = 1; - break; - case PCI_DEVICE_ID_RADEON_LW: - strcpy(rinfo->name, "Radeon M7 LW "); - rinfo->hasCRTC2 = 1; - break; - case PCI_DEVICE_ID_RADEON_LY: - strcpy(rinfo->name, "Radeon M6 LY "); - rinfo->hasCRTC2 = 1; - break; - case PCI_DEVICE_ID_RADEON_LZ: - strcpy(rinfo->name, "Radeon M6 LZ "); - rinfo->hasCRTC2 = 1; - break; - default: - return -ENODEV; - } - - /* framebuffer size */ - tmp = INREG(CONFIG_MEMSIZE); - - /* mem size is bits [28:0], mask off the rest */ - rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK; - - /* ram type */ - tmp = INREG(MEM_SDRAM_MODE_REG); - switch ((MEM_CFG_TYPE & tmp) >> 30) { - case 0: - /* SDR SGRAM (2:1) */ - strcpy(rinfo->ram_type, "SDR SGRAM"); - rinfo->ram.ml = 4; - rinfo->ram.mb = 4; - rinfo->ram.trcd = 1; - rinfo->ram.trp = 2; - rinfo->ram.twr = 1; - rinfo->ram.cl = 2; - rinfo->ram.loop_latency = 16; - rinfo->ram.rloop = 16; - - break; - case 1: - /* DDR SGRAM */ - strcpy(rinfo->ram_type, "DDR SGRAM"); - rinfo->ram.ml = 4; - rinfo->ram.mb = 4; - rinfo->ram.trcd = 3; - rinfo->ram.trp = 3; - rinfo->ram.twr = 2; - rinfo->ram.cl = 3; - rinfo->ram.tr2w = 1; - rinfo->ram.loop_latency = 16; - rinfo->ram.rloop = 16; - - break; - default: - /* 64-bit SDR SGRAM */ - strcpy(rinfo->ram_type, "SDR SGRAM 64"); - rinfo->ram.ml = 4; - rinfo->ram.mb = 8; - rinfo->ram.trcd = 3; - rinfo->ram.trp = 3; - rinfo->ram.twr = 1; - rinfo->ram.cl = 3; - rinfo->ram.tr2w = 1; - rinfo->ram.loop_latency = 17; - rinfo->ram.rloop = 17; - - break; - } - - bios_seg = radeon_find_rom(rinfo); - radeon_get_pllinfo(rinfo, bios_seg); - - RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024)); - - radeon_get_moninfo(rinfo); - if ((rinfo->dviDisp_type == MT_DFP) || (rinfo->dviDisp_type == MT_LCD) || - (rinfo->crtDisp_type == MT_DFP)) { - if (!radeon_get_dfpinfo(rinfo)) { - iounmap ((void*)rinfo->mmio_base); - release_mem_region (rinfo->mmio_base_phys, - pci_resource_len(pdev, 2)); - release_mem_region (rinfo->fb_base_phys, - pci_resource_len(pdev, 0)); - kfree (rinfo); - return -ENODEV; - } - } - - rinfo->fb_base = (u32) ioremap (rinfo->fb_base_phys, - rinfo->video_ram); - if (!rinfo->fb_base) { - printk ("radeonfb: cannot map FB\n"); - iounmap ((void*)rinfo->mmio_base); - release_mem_region (rinfo->mmio_base_phys, - pci_resource_len(pdev, 2)); - release_mem_region (rinfo->fb_base_phys, - pci_resource_len(pdev, 0)); - kfree (rinfo); - return -ENODEV; - } - - /* XXX turn off accel for now, blts aren't working right */ - noaccel = 1; - - /* set all the vital stuff */ - radeon_set_fbinfo (rinfo); - - /* save current mode regs before we switch into the new one - * so we can restore this upon __exit - */ - radeon_save_state (rinfo, &rinfo->init_state); - - /* init palette */ - for (i=0; i<16; i++) { - j = color_table[i]; - rinfo->palette[i].red = default_red[j]; - rinfo->palette[i].green = default_grn[j]; - rinfo->palette[i].blue = default_blu[j]; - } - - pci_set_drvdata(pdev, rinfo); - - if (register_framebuffer ((struct fb_info *) rinfo) < 0) { - printk ("radeonfb: could not register framebuffer\n"); - iounmap ((void*)rinfo->fb_base); - iounmap ((void*)rinfo->mmio_base); - release_mem_region (rinfo->mmio_base_phys, - pci_resource_len(pdev, 2)); - release_mem_region (rinfo->fb_base_phys, - pci_resource_len(pdev, 0)); - kfree (rinfo); - return -ENODEV; - } - - if (!noaccel) { - /* initialize the engine */ - radeon_engine_init (rinfo); - } - - printk ("radeonfb: ATI %s %s %d MB\n", rinfo->name, rinfo->ram_type, - (rinfo->video_ram/(1024*1024))); - - if (rinfo->hasCRTC2) { - printk("radeonfb: DVI port %s monitor connected\n", - GET_MON_NAME(rinfo->dviDisp_type)); - printk("radeonfb: CRT port %s monitor connected\n", - GET_MON_NAME(rinfo->crtDisp_type)); - } else { - printk("radeonfb: CRT port %s monitor connected\n", - GET_MON_NAME(rinfo->crtDisp_type)); - } - - RTRACE("radeonfb_pci_register END\n"); - - return 0; -} - - - -static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev) -{ - struct radeonfb_info *rinfo = pci_get_drvdata(pdev); - - if (!rinfo) - return; - - /* restore original state */ - radeon_write_mode (rinfo, &rinfo->init_state); - - unregister_framebuffer ((struct fb_info *) rinfo); - - iounmap ((void*)rinfo->mmio_base); - iounmap ((void*)rinfo->fb_base); - - release_mem_region (rinfo->mmio_base_phys, - pci_resource_len(pdev, 2)); - release_mem_region (rinfo->fb_base_phys, - pci_resource_len(pdev, 0)); - - kfree (rinfo); -} - +#endif /* CONFIG_ALL_PPC */ static char *radeon_find_rom(struct radeonfb_info *rinfo) @@ -1053,7 +829,7 @@ static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg) printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from BIOS\n", rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk); } else { -#if defined(__powerpc__) +#ifdef CONFIG_ALL_PPC if (radeon_read_OF(rinfo)) { unsigned int tmp, Nx, M, ref_div, xclk; @@ -1078,24 +854,39 @@ static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg) #endif /* no BIOS or BIOS not found, use defaults */ switch (rinfo->chipset) { - case PCI_DEVICE_ID_RADEON_QW: + case PCI_DEVICE_ID_ATI_RADEON_QW: + case PCI_DEVICE_ID_ATI_RADEON_QX: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; rinfo->pll.xclk = 23000; rinfo->pll.ref_div = 12; rinfo->pll.ref_clk = 2700; break; - case PCI_DEVICE_ID_RADEON_QL: + case PCI_DEVICE_ID_ATI_RADEON_QL: + case PCI_DEVICE_ID_ATI_RADEON_QN: + case PCI_DEVICE_ID_ATI_RADEON_QO: + case PCI_DEVICE_ID_ATI_RADEON_Ql: + case PCI_DEVICE_ID_ATI_RADEON_BB: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; rinfo->pll.xclk = 27500; rinfo->pll.ref_div = 12; rinfo->pll.ref_clk = 2700; break; - case PCI_DEVICE_ID_RADEON_QD: - case PCI_DEVICE_ID_RADEON_QE: - case PCI_DEVICE_ID_RADEON_QF: - case PCI_DEVICE_ID_RADEON_QG: + case PCI_DEVICE_ID_ATI_RADEON_Id: + case PCI_DEVICE_ID_ATI_RADEON_Ie: + case PCI_DEVICE_ID_ATI_RADEON_If: + case PCI_DEVICE_ID_ATI_RADEON_Ig: + rinfo->pll.ppll_max = 35000; + rinfo->pll.ppll_min = 12000; + rinfo->pll.xclk = 25000; + rinfo->pll.ref_div = 12; + rinfo->pll.ref_clk = 2700; + break; + case PCI_DEVICE_ID_ATI_RADEON_QD: + case PCI_DEVICE_ID_ATI_RADEON_QE: + case PCI_DEVICE_ID_ATI_RADEON_QF: + case PCI_DEVICE_ID_ATI_RADEON_QG: default: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; @@ -1115,8 +906,14 @@ static void radeon_get_moninfo (struct radeonfb_info *rinfo) { unsigned int tmp; - tmp = INREG(RADEON_BIOS_4_SCRATCH); + if (force_dfp) { + rinfo->dviDisp_type = MT_DFP; + return; + } + tmp = INREG(RADEON_BIOS_4_SCRATCH); + printk(KERN_DEBUG "radeon_get_moninfo: bios 4 scratch = %x\n", tmp); + if (rinfo->hasCRTC2) { /* primary DVI port */ if (tmp & 0x08) @@ -1154,74 +951,254 @@ static void radeon_get_moninfo (struct radeonfb_info *rinfo) } -static int radeon_get_dfpinfo (struct radeonfb_info *rinfo) + +static void radeon_get_EDID(struct radeonfb_info *rinfo) { - unsigned int tmp; - unsigned short a, b; +#ifdef CONFIG_ALL_PPC + if (!radeon_get_EDID_OF(rinfo)) + RTRACE("radeonfb: could not retrieve EDID from OF\n"); +#else + /* XXX use other methods later */ +#endif +} - if (panel_yres) { - rinfo->panel_yres = panel_yres; - } else { - tmp = INREG(FP_VERT_STRETCH); - tmp &= 0x00fff000; - rinfo->panel_yres = (unsigned short)(tmp >> 0x0c) + 1; - } - switch (rinfo->panel_yres) { - case 480: - rinfo->panel_xres = 640; - break; - case 600: - rinfo->panel_xres = 800; - break; - case 786: - rinfo->panel_xres = 1024; - break; - case 1024: - rinfo->panel_xres = 1280; - break; - case 1050: - rinfo->panel_xres = 1400; - break; - case 1200: - rinfo->panel_xres = 1600; - break; - default: - printk("radeonfb: Failed to detect DFP panel size\n"); - return 0; +#ifdef CONFIG_ALL_PPC +static int radeon_get_EDID_OF(struct radeonfb_info *rinfo) +{ + struct device_node *dp; + unsigned char *pedid = NULL; + static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL }; + int i; + + dp = pci_device_to_OF_node(rinfo->pdev); + while (dp != NULL) { + for (i = 0; propnames[i] != NULL; ++i) { + pedid = (unsigned char *) + get_property(dp, propnames[i], NULL); + if (pedid != NULL) { + rinfo->EDID = pedid; + return 1; + } + } + dp = dp->child; + } + return 0; +} +#endif /* CONFIG_ALL_PPC */ + + +static int radeon_dfp_parse_EDID(struct radeonfb_info *rinfo) +{ + unsigned char *block = rinfo->EDID; + + if (!block) + return 0; + + /* jump to the detailed timing block section */ + block += 54; + + rinfo->clock = (block[0] + (block[1] << 8)); + rinfo->panel_xres = (block[2] + ((block[4] & 0xf0) << 4)); + rinfo->hblank = (block[3] + ((block[4] & 0x0f) << 8)); + rinfo->panel_yres = (block[5] + ((block[7] & 0xf0) << 4)); + rinfo->vblank = (block[6] + ((block[7] & 0x0f) << 8)); + rinfo->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2)); + rinfo->hSync_width = (block[9] + ((block[11] & 0x30) << 4)); + rinfo->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2)); + rinfo->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4)); + rinfo->interlaced = ((block[17] & 0x80) >> 7); + rinfo->synct = ((block[17] & 0x18) >> 3); + rinfo->misc = ((block[17] & 0x06) >> 1); + rinfo->hAct_high = rinfo->vAct_high = 0; + if (rinfo->synct == 3) { + if (rinfo->misc & 2) + rinfo->hAct_high = 1; + if (rinfo->misc & 1) + rinfo->vAct_high = 1; } - printk("radeonfb: detected DFP panel size: %dx%d\n", + printk("radeonfb: detected DFP panel size from EDID: %dx%d\n", rinfo->panel_xres, rinfo->panel_yres); - tmp = INREG(FP_CRTC_H_TOTAL_DISP); - a = (tmp & FP_CRTC_H_TOTAL_MASK) + 4; - b = (tmp & 0x01ff0000) >> FP_CRTC_H_DISP_SHIFT; - rinfo->hblank = (a - b + 1) * 8; - - tmp = INREG(FP_H_SYNC_STRT_WID); - rinfo->hOver_plus = (unsigned short) ((tmp & FP_H_SYNC_STRT_CHAR_MASK) >> - FP_H_SYNC_STRT_CHAR_SHIFT) - b - 1; - rinfo->hOver_plus *= 8; - rinfo->hSync_width = (unsigned short) ((tmp & FP_H_SYNC_WID_MASK) >> - FP_H_SYNC_WID_SHIFT); - rinfo->hSync_width *= 8; - tmp = INREG(FP_CRTC_V_TOTAL_DISP); - a = (tmp & FP_CRTC_V_TOTAL_MASK) + 1; - b = (tmp & FP_CRTC_V_DISP_MASK) >> FP_CRTC_V_DISP_SHIFT; - rinfo->vblank = a - b /* + 24 */ ; - - tmp = INREG(FP_V_SYNC_STRT_WID); - rinfo->vOver_plus = (unsigned short) (tmp & FP_V_SYNC_STRT_MASK) - - b + 1; - rinfo->vSync_width = (unsigned short) ((tmp & FP_V_SYNC_WID_MASK) >> - FP_V_SYNC_WID_SHIFT); + rinfo->got_dfpinfo = 1; return 1; } +static void radeon_update_default_var(struct radeonfb_info *rinfo) +{ + struct fb_var_screeninfo *var = &radeonfb_default_var; + + var->xres = rinfo->panel_xres; + var->yres = rinfo->panel_yres; + var->xres_virtual = rinfo->panel_xres; + var->yres_virtual = rinfo->panel_yres; + var->xoffset = var->yoffset = 0; + var->bits_per_pixel = 8; + var->pixclock = 100000000 / rinfo->clock; + var->left_margin = (rinfo->hblank - rinfo->hOver_plus - rinfo->hSync_width); + var->right_margin = rinfo->hOver_plus; + var->upper_margin = (rinfo->vblank - rinfo->vOver_plus - rinfo->vSync_width); + var->lower_margin = rinfo->vOver_plus; + var->hsync_len = rinfo->hSync_width; + var->vsync_len = rinfo->vSync_width; + var->sync = 0; + if (rinfo->synct == 3) { + if (rinfo->hAct_high) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (rinfo->vAct_high) + var->sync |= FB_SYNC_VERT_HIGH_ACT; + } + + var->vmode = 0; + if (rinfo->interlaced) + var->vmode |= FB_VMODE_INTERLACED; + + rinfo->use_default_var = 1; +} + + +static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo) +{ + char *fpbiosstart, *tmp, *tmp0; + char stmp[30]; + int i; + + if (!rinfo->bios_seg) + return 0; + + if (!(fpbiosstart = rinfo->bios_seg + readw(rinfo->bios_seg + 0x48))) { + printk("radeonfb: Failed to detect DFP panel info using BIOS\n"); + return 0; + } + + if (!(tmp = rinfo->bios_seg + readw(fpbiosstart + 0x40))) { + printk("radeonfb: Failed to detect DFP panel info using BIOS\n"); + return 0; + } + + for(i=0; i<24; i++) + stmp[i] = readb(tmp+i+1); + stmp[24] = 0; + printk("radeonfb: panel ID string: %s\n", stmp); + rinfo->panel_xres = readw(tmp + 25); + rinfo->panel_yres = readw(tmp + 27); + printk("radeonfb: detected DFP panel size from BIOS: %dx%d\n", + rinfo->panel_xres, rinfo->panel_yres); + + for(i=0; i<20; i++) { + tmp0 = rinfo->bios_seg + readw(tmp+64+i*2); + if (tmp0 == 0) + break; + if ((readw(tmp0) == rinfo->panel_xres) && + (readw(tmp0+2) == rinfo->panel_yres)) { + rinfo->hblank = (readw(tmp0+17) - readw(tmp0+19)) * 8; + rinfo->hOver_plus = ((readw(tmp0+21) - readw(tmp0+19) -1) * 8) & 0x7fff; + rinfo->hSync_width = readb(tmp0+23) * 8; + rinfo->vblank = readw(tmp0+24) - readw(tmp0+26); + rinfo->vOver_plus = (readw(tmp0+28) & 0x7ff) - readw(tmp0+26); + rinfo->vSync_width = (readw(tmp0+28) & 0xf800) >> 11; + rinfo->clock = readw(tmp0+9); + + rinfo->got_dfpinfo = 1; + return 1; + } + } + + return 0; +} + + + +static int radeon_get_dfpinfo (struct radeonfb_info *rinfo) +{ + unsigned int tmp; + unsigned short a, b; + + if (radeon_get_dfpinfo_BIOS(rinfo)) + radeon_update_default_var(rinfo); + + if (radeon_dfp_parse_EDID(rinfo)) + radeon_update_default_var(rinfo); + + if (!rinfo->got_dfpinfo) { + /* + * it seems all else has failed now and we + * resort to probing registers for our DFP info + */ + if (panel_yres) { + rinfo->panel_yres = panel_yres; + } else { + tmp = INREG(FP_VERT_STRETCH); + tmp &= 0x00fff000; + rinfo->panel_yres = (unsigned short)(tmp >> 0x0c) + 1; + } + + switch (rinfo->panel_yres) { + case 480: + rinfo->panel_xres = 640; + break; + case 600: + rinfo->panel_xres = 800; + break; + case 768: #if defined(__powerpc__) + if (rinfo->dviDisp_type == MT_LCD) + rinfo->panel_xres = 1152; + else +#endif + rinfo->panel_xres = 1024; + break; + case 1024: + rinfo->panel_xres = 1280; + break; + case 1050: + rinfo->panel_xres = 1400; + break; + case 1200: + rinfo->panel_xres = 1600; + break; + default: + printk("radeonfb: Failed to detect DFP panel size\n"); + return 0; + } + + printk("radeonfb: detected DFP panel size from registers: %dx%d\n", + rinfo->panel_xres, rinfo->panel_yres); + + tmp = INREG(FP_CRTC_H_TOTAL_DISP); + a = (tmp & FP_CRTC_H_TOTAL_MASK) + 4; + b = (tmp & 0x01ff0000) >> FP_CRTC_H_DISP_SHIFT; + rinfo->hblank = (a - b + 1) * 8; + + tmp = INREG(FP_H_SYNC_STRT_WID); + rinfo->hOver_plus = (unsigned short) ((tmp & FP_H_SYNC_STRT_CHAR_MASK) >> + FP_H_SYNC_STRT_CHAR_SHIFT) - b - 1; + rinfo->hOver_plus *= 8; + rinfo->hSync_width = (unsigned short) ((tmp & FP_H_SYNC_WID_MASK) >> + FP_H_SYNC_WID_SHIFT); + rinfo->hSync_width *= 8; + tmp = INREG(FP_CRTC_V_TOTAL_DISP); + a = (tmp & FP_CRTC_V_TOTAL_MASK) + 1; + b = (tmp & FP_CRTC_V_DISP_MASK) >> FP_CRTC_V_DISP_SHIFT; + rinfo->vblank = a - b /* + 24 */ ; + + tmp = INREG(FP_V_SYNC_STRT_WID); + rinfo->vOver_plus = (unsigned short) (tmp & FP_V_SYNC_STRT_MASK) + - b + 1; + rinfo->vSync_width = (unsigned short) ((tmp & FP_V_SYNC_WID_MASK) >> + FP_V_SYNC_WID_SHIFT); + + return 1; + } + + return 1; +} + + +#ifdef CONFIG_ALL_PPC static int radeon_read_OF (struct radeonfb_info *rinfo) { struct device_node *dp; @@ -1251,10 +1228,10 @@ static void radeon_engine_init (struct radeonfb_info *rinfo) radeon_engine_reset (); radeon_fifo_wait (1); - OUTREG(DSTCACHE_MODE, 0); + OUTREG(RB2D_DSTCACHE_MODE, 0); /* XXX */ - rinfo->pitch = ((rinfo->xres * (rinfo->depth / 8) + 0x3f)) >> 6; + rinfo->pitch = ((rinfo->xres_virtual * (rinfo->bpp / 8) + 0x3f)) >> 6; radeon_fifo_wait (1); temp = INREG(DEFAULT_PITCH_OFFSET); @@ -1296,141 +1273,54 @@ static void radeon_engine_init (struct radeonfb_info *rinfo) } - -static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) -{ - struct fb_info *info; - - info = &rinfo->info; - - strcpy (info->modename, rinfo->name); - info->node = NODEV; - info->flags = FBINFO_FLAG_DEFAULT; - info->fbops = &radeon_fb_ops; - info->screen_base = (char*)rinfo->fb_base; - info->display_fg = NULL; - info->currcon = -1; - strncpy (info->fontname, fontname, sizeof (info->fontname)); - info->fontname[sizeof (info->fontname) - 1] = 0; - info->changevar = NULL; - info->switch_con = radeonfb_switch; - info->updatevar = radeonfb_updatevar; - - if (radeon_init_disp (rinfo) < 0) - return -1; - - return 0; -} - - - static int __devinit radeon_init_disp (struct radeonfb_info *rinfo) { - struct fb_info *info; - struct display *disp; + struct fb_info *info = &rinfo->info; + struct fb_var_screeninfo var; - info = &rinfo->info; - disp = &rinfo->disp; - - disp->var = radeonfb_default_var; - info->disp = disp; - - radeon_set_dispsw (rinfo, disp); + var = radeonfb_default_var; + if ((radeon_init_disp_var(rinfo, &var)) < 0) + return -1; - if (noaccel) - disp->scrollmode = SCROLL_YREDRAW; - else - disp->scrollmode = 0; + rinfo->depth = var_to_depth(&var); + rinfo->bpp = var.bits_per_pixel; - rinfo->currcon_display = disp; + info->var = var; + fb_alloc_cmap(&info->cmap, 256, 0); - if ((radeon_init_disp_var (rinfo)) < 0) - return -1; - + var.activate = FB_ACTIVATE_NOW; + gen_set_var(&var, -1, info); return 0; } - -static int radeon_init_disp_var (struct radeonfb_info *rinfo) +static int radeon_init_disp_var (struct radeonfb_info *rinfo, + struct fb_var_screeninfo *var) { #ifndef MODULE if (mode_option) - fb_find_mode (&rinfo->disp.var, &rinfo->info, mode_option, + fb_find_mode (var, &rinfo->info, mode_option, NULL, 0, NULL, 8); else #endif - fb_find_mode (&rinfo->disp.var, &rinfo->info, "640x480-8@60", + if (rinfo->use_default_var) + /* We will use the modified default far */ + *var = radeonfb_default_var; + else + + fb_find_mode (var, &rinfo->info, "640x480-8@60", NULL, 0, NULL, 0); if (noaccel) - rinfo->disp.var.accel_flags &= ~FB_ACCELF_TEXT; + var->accel_flags &= ~FB_ACCELF_TEXT; else - rinfo->disp.var.accel_flags |= FB_ACCELF_TEXT; + var->accel_flags |= FB_ACCELF_TEXT; return 0; } - -static void radeon_set_dispsw (struct radeonfb_info *rinfo, struct display *disp) - -{ - int accel; - - accel = disp->var.accel_flags & FB_ACCELF_TEXT; - - disp->dispsw_data = NULL; - - disp->type = FB_TYPE_PACKED_PIXELS; - disp->type_aux = 0; - disp->ypanstep = 1; - disp->ywrapstep = 0; - disp->can_soft_blank = 1; - disp->inverse = 0; - - rinfo->depth = disp->var.bits_per_pixel; - switch (disp->var.bits_per_pixel) { -#ifdef FBCON_HAS_CFB8 - case 8: - disp->dispsw = &fbcon_cfb8; - disp->visual = FB_VISUAL_PSEUDOCOLOR; - disp->line_length = disp->var.xres_virtual; - break; -#endif -#ifdef FBCON_HAS_CFB16 - case 16: - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = &rinfo->con_cmap.cfb16; - disp->visual = FB_VISUAL_DIRECTCOLOR; - disp->line_length = disp->var.xres_virtual * 2; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case 24: - disp->dispsw = &fbcon_cfb24; - disp->dispsw_data = &rinfo->con_cmap.cfb24; - disp->visual = FB_VISUAL_DIRECTCOLOR; - disp->line_length = disp->var.xres_virtual * 4; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case 32: - disp->dispsw = &fbcon_cfb32; - disp->dispsw_data = &rinfo->con_cmap.cfb32; - disp->visual = FB_VISUAL_DIRECTCOLOR; - disp->line_length = disp->var.xres_virtual * 4; - break; -#endif - default: - printk ("radeonfb: setting fbcon_dummy renderer\n"); - disp->dispsw = &fbcon_dummy; - } - - return; -} - -static int radeonfb_do_maximize(struct radeonfb_info *rinfo, +static int radeon_do_maximize(struct radeonfb_info *rinfo, struct fb_var_screeninfo *var, struct fb_var_screeninfo *v, int nom, int den) @@ -1446,7 +1336,7 @@ static int radeonfb_do_maximize(struct radeonfb_info *rinfo, {-1, -1} }; int i; - + /* use highest possible virtual resolution */ if (v->xres_virtual == -1 && v->yres_virtual == -1) { printk("radeonfb: using max available virtual resolution\n"); @@ -1490,105 +1380,55 @@ static int radeonfb_do_maximize(struct radeonfb_info *rinfo, return 0; } - -/* - * fb ops - */ - -static int radeonfb_get_fix (struct fb_fix_screeninfo *fix, int con, - struct fb_info *info) +static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info) { - struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - struct display *disp; - - disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; - - memset (fix, 0, sizeof (struct fb_fix_screeninfo)); - strcpy (fix->id, rinfo->name); - - fix->smem_start = rinfo->fb_base_phys; - fix->smem_len = rinfo->video_ram; - - fix->type = disp->type; - fix->type_aux = disp->type_aux; - fix->visual = disp->visual; - - fix->xpanstep = 1; - fix->ypanstep = 1; - fix->ywrapstep = 0; - - fix->line_length = disp->line_length; - - fix->mmio_start = rinfo->mmio_base_phys; - fix->mmio_len = RADEON_REGSIZE; - if (noaccel) - fix->accel = FB_ACCEL_NONE; - else - fix->accel = 40; /* XXX */ - - return 0; -} - - - -static int radeonfb_get_var (struct fb_var_screeninfo *var, int con, - struct fb_info *info) -{ - struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - - *var = (con < 0) ? rinfo->disp.var : fb_display[con].var; - - return 0; -} - - - -static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, - struct fb_info *info) -{ - struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - struct display *disp; + struct radeonfb_info *rinfo = (struct radeonfb_info *) info->par; struct fb_var_screeninfo v; - int nom, den, accel; - unsigned chgvar = 0; - - disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; - - accel = var->accel_flags & FB_ACCELF_TEXT; - - if (con >= 0) { - chgvar = ((disp->var.xres != var->xres) || - (disp->var.yres != var->yres) || - (disp->var.xres_virtual != var->xres_virtual) || - (disp->var.yres_virtual != var->yres_virtual) || - (disp->var.bits_per_pixel != var->bits_per_pixel) || - memcmp (&disp->var.red, &var->red, sizeof (var->red)) || - memcmp (&disp->var.green, &var->green, sizeof (var->green)) || - memcmp (&disp->var.blue, &var->blue, sizeof (var->blue))); - } + int nom, den; memcpy (&v, var, sizeof (v)); switch (v.bits_per_pixel) { -#ifdef FBCON_HAS_CFB8 + case 0 ... 8: + v.bits_per_pixel = 8; + break; + case 9 ... 16: + v.bits_per_pixel = 16; + break; + case 17 ... 24: +#if 0 /* Doesn't seem to work */ + v.bits_per_pixel = 24; + break; +#endif + return -EINVAL; + case 25 ... 32: + v.bits_per_pixel = 32; + break; + default: + return -EINVAL; + } + + switch (var_to_depth(&v)) { case 8: nom = den = 1; - disp->line_length = v.xres_virtual; - disp->visual = FB_VISUAL_PSEUDOCOLOR; v.red.offset = v.green.offset = v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 8; v.transp.offset = v.transp.length = 0; break; -#endif - -#ifdef FBCON_HAS_CFB16 + case 15: + nom = 2; + den = 1; + v.red.offset = 10; + v.green.offset = 5; + v.red.offset = 0; + v.red.length = v.green.length = v.blue.length = 5; + v.transp.offset = v.transp.length = 0; + break; case 16: nom = 2; den = 1; - disp->line_length = v.xres_virtual * 2; - disp->visual = FB_VISUAL_DIRECTCOLOR; v.red.offset = 11; v.green.offset = 5; v.blue.offset = 0; @@ -1596,28 +1436,19 @@ static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, v.green.length = 6; v.blue.length = 5; v.transp.offset = v.transp.length = 0; - break; -#endif - -#ifdef FBCON_HAS_CFB24 + break; case 24: nom = 4; den = 1; - disp->line_length = v.xres_virtual * 3; - disp->visual = FB_VISUAL_DIRECTCOLOR; v.red.offset = 16; v.green.offset = 8; v.blue.offset = 0; v.red.length = v.blue.length = v.green.length = 8; v.transp.offset = v.transp.length = 0; break; -#endif -#ifdef FBCON_HAS_CFB32 case 32: nom = 4; den = 1; - disp->line_length = v.xres_virtual * 4; - disp->visual = FB_VISUAL_DIRECTCOLOR; v.red.offset = 16; v.green.offset = 8; v.blue.offset = 0; @@ -1625,14 +1456,13 @@ static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, v.transp.offset = 24; v.transp.length = 8; break; -#endif default: printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n", var->xres, var->yres, var->bits_per_pixel); return -EINVAL; } - if (radeonfb_do_maximize(rinfo, var, &v, nom, den) < 0) + if (radeon_do_maximize(rinfo, var, &v, nom, den) < 0) return -EINVAL; if (v.xoffset < 0) @@ -1649,179 +1479,144 @@ static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, v.red.msb_right = v.green.msb_right = v.blue.msb_right = v.transp.offset = v.transp.length = v.transp.msb_right = 0; - - switch (v.activate & FB_ACTIVATE_MASK) { - case FB_ACTIVATE_TEST: - return 0; - case FB_ACTIVATE_NXTOPEN: - case FB_ACTIVATE_NOW: - break; - default: - return -EINVAL; - } - - memcpy (&disp->var, &v, sizeof (v)); - - if (chgvar) { - radeon_set_dispsw(rinfo, disp); - if (noaccel) - disp->scrollmode = SCROLL_YREDRAW; - else - disp->scrollmode = 0; - - if (info && info->changevar) - info->changevar(con); - } - - radeon_load_video_mode (rinfo, &v); - - do_install_cmap(con, info); - + if (noaccel) + v.accel_flags = 0; + + memcpy(var, &v, sizeof(v)); + return 0; } - -static int radeonfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) +static int radeonfb_pan_display (struct fb_var_screeninfo *var, + struct fb_info *info) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - struct display *disp; + + if ((var->xoffset + var->xres > var->xres_virtual) + || (var->yoffset + var->yres > var->yres_virtual)) + return -EINVAL; - disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; - - if (con == info->currcon) { - int rc = fb_get_cmap (cmap, kspc, radeon_getcolreg, info); - return rc; - } else if (disp->cmap.len) - fb_copy_cmap (&disp->cmap, cmap, kspc ? 0 : 2); - else - fb_copy_cmap (fb_default_cmap (radeon_get_cmap_len (&disp->var)), - cmap, kspc ? 0 : 2); - + if (rinfo->asleep) + return 0; + + OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) + * var->bits_per_pixel / 8) & ~7); return 0; } - -static int radeonfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) +static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, int con, struct fb_info *info) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - struct display *disp; - unsigned int cmap_len; - - disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; - - cmap_len = radeon_get_cmap_len (&disp->var); - if (disp->cmap.len != cmap_len) { - int err = fb_alloc_cmap (&disp->cmap, cmap_len, 0); - if (err) - return err; - } - - if (con == info->currcon) { - int rc = fb_set_cmap (cmap, kspc, info); - return rc; - } else - fb_copy_cmap (cmap, &disp->cmap, kspc ? 0 : 1); - - return 0; -} + unsigned int tmp; + u32 value = 0; + int rc; + + switch (cmd) { + /* + * TODO: set mirror accordingly for non-Mobility chipsets with 2 CRTC's + */ + case FBIO_RADEON_SET_MIRROR: + switch (rinfo->arch) { + case RADEON_R100: + case RADEON_RV100: + case RADEON_R200: + case RADEON_RV200: + case RADEON_RV250: + case RADEON_R300: + return -EINVAL; + default: + /* RADEON M6, RADEON_M7, RADEON_M9 */ + break; + } + rc = get_user(value, (__u32*)arg); + if (rc) + return rc; -static int radeonfb_pan_display (struct fb_var_screeninfo *var, int con, - struct fb_info *info) -{ - struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - u32 offset, xoffset, yoffset; - - xoffset = (var->xoffset + 7) & ~7; - yoffset = var->yoffset; - - if ((xoffset + var->xres > var->xres_virtual) || (yoffset+var->yres > - var->yres_virtual)) - return -EINVAL; - - offset = ((yoffset * var->xres + xoffset) * var->bits_per_pixel) >> 6; - - OUTREG(CRTC_OFFSET, offset); - - return 0; -} + if (value & 0x01) { + tmp = INREG(LVDS_GEN_CNTL); + tmp |= (LVDS_ON | LVDS_BLON); + } else { + tmp = INREG(LVDS_GEN_CNTL); -static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, int con, struct fb_info *info) -{ - return -EINVAL; -} + tmp &= ~(LVDS_ON | LVDS_BLON); + } + OUTREG(LVDS_GEN_CNTL, tmp); -static int radeonfb_switch (int con, struct fb_info *info) -{ - struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - struct display *disp; - struct fb_cmap *cmap; - int switchcon = 0; - - disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; - - if (info->currcon >= 0) { - cmap = &(rinfo->currcon_display->cmap); - if (cmap->len) - fb_get_cmap (cmap, 1, radeon_getcolreg, info); - } - - if ((disp->var.xres != rinfo->xres) || - (disp->var.yres != rinfo->yres) || - (disp->var.pixclock != rinfo->pixclock) || - (disp->var.bits_per_pixel != rinfo->depth)) - switchcon = 1; - - if (switchcon) { - info->currcon = con; - rinfo->currcon_display = disp; - disp->var.activate = FB_ACTIVATE_NOW; - - radeonfb_set_var (&disp->var, con, info); - radeon_set_dispsw (rinfo, disp); - do_install_cmap(con, info); - } + if (value & 0x02) { + tmp = INREG(CRTC_EXT_CNTL); + tmp |= CRTC_CRT_ON; - /* XXX absurd hack for X to restore console */ - { - OUTREGP(CRTC_EXT_CNTL, rinfo->hack_crtc_ext_cntl, - CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS); - OUTREG(CRTC_V_SYNC_STRT_WID, rinfo->hack_crtc_v_sync_strt_wid); - } + mirror = 1; + } else { + tmp = INREG(CRTC_EXT_CNTL); + tmp &= ~CRTC_CRT_ON; - return 0; -} + mirror = 0; + } + OUTREG(CRTC_EXT_CNTL, tmp); + break; + case FBIO_RADEON_GET_MIRROR: + switch (rinfo->arch) { + case RADEON_R100: + case RADEON_RV100: + case RADEON_R200: + case RADEON_RV200: + case RADEON_RV250: + case RADEON_R300: + return -EINVAL; + default: + /* RADEON M6, RADEON_M7, RADEON_M9 */ + break; + } -static int radeonfb_updatevar (int con, struct fb_info *info) -{ - int rc; - - rc = (con < 0) ? -EINVAL : radeonfb_pan_display (&fb_display[con].var, - con, info); - - return rc; + tmp = INREG(LVDS_GEN_CNTL); + if ((LVDS_ON | LVDS_BLON) & tmp) + value |= 0x01; + + tmp = INREG(CRTC_EXT_CNTL); + if (CRTC_CRT_ON & tmp) + value |= 0x02; + + return put_user(value, (__u32*)arg); + default: + return -EINVAL; + } + + return -EINVAL; } + static int radeonfb_blank (int blank, struct fb_info *info) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; u32 val = INREG(CRTC_EXT_CNTL); + u32 val2 = INREG(LVDS_GEN_CNTL); + + if (rinfo->asleep) + return 0; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (rinfo->dviDisp_type == MT_LCD && _machine == _MACH_Pmac) { + set_backlight_enable(!blank); + return 0; + } +#endif /* reset it */ val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS); - + val2 &= ~(LVDS_DISPLAY_DIS); + switch (blank) { case VESA_NO_BLANKING: break; @@ -1834,56 +1629,31 @@ static int radeonfb_blank (int blank, struct fb_info *info) case VESA_POWERDOWN: val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | CRTC_HSYNC_DIS); + val2 |= (LVDS_DISPLAY_DIS); break; } - - OUTREG(CRTC_EXT_CNTL, val); - return 0; -} -static int radeon_get_cmap_len (const struct fb_var_screeninfo *var) -{ - int rc = 16; /* reasonable default */ - - switch (var->bits_per_pixel) { - case 8: - rc = 256; - break; - default: - rc = 32; - break; - } - - return rc; -} - - - -static int radeon_getcolreg (unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info) -{ - struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - - if (regno > 255) - return 1; - - *red = (rinfo->palette[regno].red<<8) | rinfo->palette[regno].red; - *green = (rinfo->palette[regno].green<<8) | rinfo->palette[regno].green; - *blue = (rinfo->palette[regno].blue<<8) | rinfo->palette[regno].blue; - *transp = 0; + switch (rinfo->dviDisp_type) { + case MT_LCD: + OUTREG(LVDS_GEN_CNTL, val2); + break; + case MT_CRT: + default: + OUTREG(CRTC_EXT_CNTL, val); + break; + } return 0; -} - +} static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, struct fb_info *info) + unsigned blue, unsigned transp, struct fb_info *info) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; - u32 pindex; - + u32 pindex, vclk_cntl; + unsigned int i; + if (regno > 255) return 1; @@ -1894,62 +1664,58 @@ static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, rinfo->palette[regno].green = green; rinfo->palette[regno].blue = blue; - /* init gamma for hicolor */ - if ((rinfo->depth > 8) && (regno == 0)) { - int i; - - for (i=0; i<255; i++) { - OUTREG(PALETTE_INDEX, i); - OUTREG(PALETTE_DATA, (i << 16) | (i << 8) | i); - } - } - /* default */ pindex = regno; - - /* XXX actually bpp, fixme */ - if (rinfo->depth == 16) - pindex = regno * 8; - - if (rinfo->depth == 16) { - OUTREG(PALETTE_INDEX, pindex/2); - OUTREG(PALETTE_DATA, (rinfo->palette[regno/2].red << 16) | - (green << 8) | (rinfo->palette[regno/2].blue)); - green = rinfo->palette[regno/2].green; - } - - if ((rinfo->depth == 8) || (regno < 32)) { - OUTREG(PALETTE_INDEX, pindex); - OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue); - } + if (!rinfo->asleep) { + vclk_cntl = INPLL(VCLK_ECP_CNTL); + OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb); + + if (rinfo->bpp == 16) { + pindex = regno * 8; + + if (rinfo->depth == 16 && regno > 63) + return 1; + if (rinfo->depth == 15 && regno > 31) + return 1; + + /* For 565, the green component is mixed one order below */ + if (rinfo->depth == 16) { + OUTREG(PALETTE_INDEX, pindex>>1); + OUTREG(PALETTE_DATA, (rinfo->palette[regno>>1].red << 16) | + (green << 8) | (rinfo->palette[regno>>1].blue)); + green = rinfo->palette[regno<<1].green; + } + } + + if (rinfo->depth != 16 || regno < 32) { + OUTREG(PALETTE_INDEX, pindex); + OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue); + } -#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) - if (regno < 32) { + OUTPLL(VCLK_ECP_CNTL, vclk_cntl); + } + if (regno < 16) { switch (rinfo->depth) { -#ifdef FBCON_HAS_CFB16 - case 16: - rinfo->con_cmap.cfb16[regno] = (regno << 11) | (regno << 5) | - regno; - break; -#endif -#ifdef FBCON_HAS_CFB24 - case 24: - rinfo->con_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | regno; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case 32: { - u32 i; - - i = (regno << 8) | regno; - rinfo->con_cmap.cfb32[regno] = (i << 16) | i; - break; - } -#endif + case 15: + ((u16 *) (info->pseudo_palette))[regno] = + (regno << 10) | (regno << 5) | regno; + break; + case 16: + ((u16 *) (info->pseudo_palette))[regno] = + (regno << 11) | (regno << 6) | regno; + break; + case 24: + ((u32 *) (info->pseudo_palette))[regno] = + (regno << 16) | (regno << 8) | regno; + break; + case 32: + i = (regno << 8) | regno; + ((u32 *) (info->pseudo_palette))[regno] = + (i << 16) | i; + break; } } -#endif return 0; } @@ -1982,13 +1748,16 @@ static void radeon_save_state (struct radeonfb_info *rinfo, save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL); save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL); save->tmds_crc = INREG(TMDS_CRC); + save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL); + save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL); } -static void radeon_load_video_mode (struct radeonfb_info *rinfo, - struct fb_var_screeninfo *mode) +static int radeonfb_set_par (struct fb_info *info) { + struct radeonfb_info *rinfo = (struct radeonfb_info *)info->par; + struct fb_var_screeninfo *mode = &info->var; struct radeon_regs newmode; int hTotal, vTotal, hSyncStart, hSyncEnd, hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync; @@ -2002,9 +1771,12 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, int min_bits, format = 0; int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid; int primary_mon = PRIMARY_MONITOR(rinfo); + int depth = var_to_depth(mode); rinfo->xres = mode->xres; rinfo->yres = mode->yres; + rinfo->xres_virtual = mode->xres_virtual; + rinfo->yres_virtual = mode->yres_virtual; rinfo->pixclock = mode->pixclock; hSyncStart = mode->xres + mode->right_margin; @@ -2021,13 +1793,13 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, if (rinfo->panel_yres < mode->yres) rinfo->yres = mode->yres = rinfo->panel_yres; - hTotal = mode->xres + rinfo->hblank + mode->left_margin; - hSyncStart = mode->xres + rinfo->hOver_plus + mode->right_margin; - hSyncEnd = hSyncStart + rinfo->hOver_plus + mode->hsync_len; + hTotal = mode->xres + rinfo->hblank; + hSyncStart = mode->xres + rinfo->hOver_plus; + hSyncEnd = hSyncStart + rinfo->hSync_width; - vTotal = mode->yres + rinfo->vblank + mode->upper_margin; - vSyncStart = mode->yres + rinfo->vOver_plus + mode->lower_margin; - vSyncEnd = vSyncStart + rinfo->vSync_width + mode->vsync_len; + vTotal = mode->yres + rinfo->vblank; + vSyncStart = mode->yres + rinfo->vOver_plus; + vSyncEnd = vSyncStart + rinfo->vSync_width; } sync = mode->sync; @@ -2045,7 +1817,7 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, hsync_wid = 1; else if (hsync_wid > 0x3f) /* max */ hsync_wid = 0x3f; - vsync_wid = mode->vsync_len; + if (vsync_wid == 0) vsync_wid = 1; else if (vsync_wid > 0x1f) /* max */ @@ -2056,24 +1828,8 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; - switch (mode->bits_per_pixel) { - case 8: - format = DST_8BPP; - bytpp = 1; - break; - case 16: - format = DST_16BPP; - bytpp = 2; - break; - case 24: - format = DST_24BPP; - bytpp = 3; - break; - case 32: - format = DST_32BPP; - bytpp = 4; - break; - } + format = radeon_get_dstbpp(depth); + bytpp = mode->bits_per_pixel >> 3; if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) hsync_fudge = hsync_fudge_fp[format-1]; @@ -2087,6 +1843,9 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN; + if (mirror) + newmode.crtc_ext_cntl |= CRTC_CRT_ON; + newmode.crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN | CRTC_INTERLACE_EN); } else { @@ -2097,7 +1856,7 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, newmode.dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN | DAC_8BIT_EN; - newmode.crtc_h_total_disp = ((((hTotal / 8) - 1) & 0xffff) | + newmode.crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) | (((mode->xres / 8) - 1) << 16)); newmode.crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) | @@ -2109,7 +1868,7 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) | (vsync_wid << 16) | (v_sync_pol << 23)); - newmode.crtc_pitch = (mode->xres >> 3); + newmode.crtc_pitch = (mode->xres_virtual >> 3); newmode.crtc_pitch |= (newmode.crtc_pitch << 16); #if defined(__BIG_ENDIAN) @@ -2125,8 +1884,8 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, } #endif - rinfo->pitch = ((mode->xres * ((mode->bits_per_pixel + 1) / 8) + 0x3f) - & ~(0x3f)) / 64; + rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f) + & ~(0x3f)) / 64; RTRACE("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n", newmode.crtc_h_total_disp, newmode.crtc_h_sync_strt_wid); @@ -2137,9 +1896,7 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, newmode.yres = mode->yres; rinfo->bpp = mode->bits_per_pixel; - - rinfo->hack_crtc_ext_cntl = newmode.crtc_ext_cntl; - rinfo->hack_crtc_v_sync_strt_wid = newmode.crtc_v_sync_strt_wid; + rinfo->depth = depth; if (freq > rinfo->pll.ppll_max) freq = rinfo->pll.ppll_max; @@ -2176,6 +1933,8 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, newmode.ppll_ref_div = rinfo->pll.ref_div; newmode.ppll_div_3 = rinfo->fb_div | (post_div->bitvalue << 16); } + newmode.vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl; + RTRACE("post div = 0x%x\n", rinfo->post_div); RTRACE("fb_div = 0x%x\n", rinfo->fb_div); @@ -2204,7 +1963,7 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, if ((ron + rinfo->ram.rloop) >= roff) { printk("radeonfb: error ron out of range\n"); - return; + return -EINVAL; } newmode.dda_config = (xclk_per_trans_precise | @@ -2213,48 +1972,43 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, newmode.dda_on_off = (ron << 16) | roff; if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { - int hRatio, vRatio; - - if ((rinfo->panel_xres == 0) || (rinfo->panel_yres == 0)) { - hRatio = vRatio = 1; - } else { - if (mode->xres > rinfo->panel_xres) - mode->xres = rinfo->panel_xres; - if (mode->yres > rinfo->panel_yres) - mode->yres = rinfo->panel_yres; - - hRatio = mode->xres / rinfo->panel_xres; - vRatio = mode->yres / rinfo->panel_yres; - } - - if (hRatio == 1) { - newmode.fp_horz_stretch = - rinfo->init_state.fp_horz_stretch; - newmode.fp_horz_stretch &= ~(HORZ_STRETCH_BLEND | - HORZ_STRETCH_ENABLE); - } else { - newmode.fp_horz_stretch = - ((((unsigned long)(hRatio * HORZ_STRETCH_RATIO_MAX + - (int)0.5)) & HORZ_STRETCH_RATIO_MASK)) | - (rinfo->init_state.fp_horz_stretch & - (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH | - HORZ_AUTO_RATIO_INC)); + unsigned int hRatio, vRatio; + + /* We force the pixel clock to be always enabled. Allowing it + * to be power managed during blanking would save power, but has + * nasty interactions with the 2D engine & sleep code that haven't + * been solved yet. --BenH + */ + newmode.vclk_ecp_cntl &= ~PIXCLK_DAC_ALWAYS_ONb; + + if (mode->xres > rinfo->panel_xres) + mode->xres = rinfo->panel_xres; + if (mode->yres > rinfo->panel_yres) + mode->yres = rinfo->panel_yres; + + newmode.fp_horz_stretch = (((rinfo->panel_xres / 8) - 1) + << HORZ_PANEL_SHIFT); + newmode.fp_vert_stretch = ((rinfo->panel_yres - 1) + << VERT_PANEL_SHIFT); + + if (mode->xres != rinfo->panel_xres) { + hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX, + rinfo->panel_xres); + newmode.fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) | + (newmode.fp_horz_stretch & + (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH | + HORZ_AUTO_RATIO_INC))); newmode.fp_horz_stretch |= (HORZ_STRETCH_BLEND | HORZ_STRETCH_ENABLE); } newmode.fp_horz_stretch &= ~HORZ_AUTO_RATIO; - if (vRatio == 1) { - newmode.fp_vert_stretch = - rinfo->init_state.fp_vert_stretch; - newmode.fp_vert_stretch &= ~(VERT_STRETCH_BLEND | - VERT_STRETCH_ENABLE); - } else { - newmode.fp_vert_stretch = - ((((unsigned long)(vRatio * VERT_STRETCH_RATIO_MAX + - (int)0.5)) & VERT_STRETCH_RATIO_MASK)) | - (rinfo->init_state.fp_vert_stretch & - (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED)); + if (mode->yres != rinfo->panel_yres) { + vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX, + rinfo->panel_yres); + newmode.fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) | + (newmode.fp_vert_stretch & + (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED))); newmode.fp_vert_stretch |= (VERT_STRETCH_BLEND | VERT_STRETCH_ENABLE); } @@ -2269,14 +2023,14 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, FP_USE_SHADOW_EN | FP_CRTC_USE_SHADOW_VEND | FP_CRT_SYNC_ALT)); + newmode.fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR | FP_CRTC_DONT_SHADOW_HEND); newmode.lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl; newmode.lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl; newmode.tmds_crc = rinfo->init_state.tmds_crc; - - newmode.crtc_ext_cntl &= ~CRTC_CRT_ON; + newmode.tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl; if (primary_mon == MT_LCD) { newmode.lvds_gen_cntl |= (LVDS_ON | LVDS_BLON); @@ -2284,22 +2038,41 @@ static void radeon_load_video_mode (struct radeonfb_info *rinfo, } else { /* DFP */ newmode.fp_gen_cntl |= (FP_FPON | FP_TMDS_EN); + newmode.tmds_transmitter_cntl = (TMDS_RAN_PAT_RST | + ICHCSEL | TMDS_PLL_EN) & + ~(TMDS_PLLRST); + newmode.crtc_ext_cntl &= ~CRTC_CRT_ON; } - newmode.fp_crtc_h_total_disp = - rinfo->init_state.fp_crtc_h_total_disp; - newmode.fp_crtc_v_total_disp = - rinfo->init_state.fp_crtc_v_total_disp; - newmode.fp_h_sync_strt_wid = - rinfo->init_state.fp_h_sync_strt_wid; - newmode.fp_v_sync_strt_wid = - rinfo->init_state.fp_v_sync_strt_wid; + newmode.fp_crtc_h_total_disp = (((rinfo->hblank / 8) & 0x3ff) | + (((mode->xres / 8) - 1) << 16)); + newmode.fp_crtc_v_total_disp = (rinfo->vblank & 0xffff) | + ((mode->yres - 1) << 16); + newmode.fp_h_sync_strt_wid = ((rinfo->hOver_plus & 0x1fff) | + (hsync_wid << 16) | (h_sync_pol << 23)); + newmode.fp_v_sync_strt_wid = ((rinfo->vOver_plus & 0xfff) | + (vsync_wid << 16) | (v_sync_pol << 23)); } /* do it! */ - radeon_write_mode (rinfo, &newmode); + if (!rinfo->asleep) { + radeon_write_mode (rinfo, &newmode); + /* (re)initialize the engine */ + if (!noaccel) + radeon_engine_init (rinfo); + + } + /* Update fix */ + info->fix.line_length = rinfo->pitch*64; + info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; + +#ifdef CONFIG_BOOTX_TEXT + /* Update debug text engine */ + btext_update_display(rinfo->fb_base_phys, mode->xres, mode->yres, + rinfo->depth, rinfo->pitch*64); +#endif - return; + return 0; } @@ -2309,11 +2082,16 @@ static void radeon_write_mode (struct radeonfb_info *rinfo, int i; int primary_mon = PRIMARY_MONITOR(rinfo); - /* blank screen */ - OUTREG8(CRTC_EXT_CNTL + 1, 4); + radeonfb_blank(VESA_POWERDOWN, (struct fb_info *)rinfo); - for (i=0; i<9; i++) - OUTREG(common_regs[i].reg, common_regs[i].val); + + if (rinfo->arch == RADEON_M6) { + for (i=0; i<8; i++) + OUTREG(common_regs_m6[i].reg, common_regs_m6[i].val); + } else { + for (i=0; i<9; i++) + OUTREG(common_regs[i].reg, common_regs[i].val); + } OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl); OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl, @@ -2326,16 +2104,6 @@ static void radeon_write_mode (struct radeonfb_info *rinfo, OUTREG(CRTC_OFFSET, 0); OUTREG(CRTC_OFFSET_CNTL, 0); OUTREG(CRTC_PITCH, mode->crtc_pitch); -#if 1 - printk("CRTC_H_TOTAL_DISP = 0x%x, H_SYNC = 0x%x\n", - mode->crtc_h_total_disp, mode->crtc_h_sync_strt_wid); - printk("CRTC_V_TOTAL_DISP = 0x%x, V_SYNC = 0x%x\n", - mode->crtc_v_total_disp, mode->crtc_v_sync_strt_wid); - printk("PPLL_DIV_3 = 0x%x, PPLL_REF_DIV = 0x%x\n", - mode->ppll_div_3, mode->ppll_ref_div); - printk("DDA_CONFIG = 0x%x, DDA_ON_OFF = 0x%x\n", - mode->dda_config, mode->dda_on_off); -#endif #if defined(__BIG_ENDIAN) OUTREG(SURFACE_CNTL, mode->surface_cntl); @@ -2367,131 +2135,1017 @@ static void radeon_write_mode (struct radeonfb_info *rinfo, OUTPLLP(PPLL_CNTL, 0, ~PPLL_RESET); - OUTREG(DDA_CONFIG, mode->dda_config); - OUTREG(DDA_ON_OFF, mode->dda_on_off); +// OUTREG(DDA_CONFIG, mode->dda_config); +// OUTREG(DDA_ON_OFF, mode->dda_on_off); if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp); OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp); OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid); OUTREG(FP_V_SYNC_STRT_WID, mode->fp_v_sync_strt_wid); - OUTREG(TMDS_CRC, mode->tmds_crc); OUTREG(FP_HORZ_STRETCH, mode->fp_horz_stretch); OUTREG(FP_VERT_STRETCH, mode->fp_vert_stretch); OUTREG(FP_GEN_CNTL, mode->fp_gen_cntl); + OUTREG(TMDS_CRC, mode->tmds_crc); + OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl); if (primary_mon == MT_LCD) { unsigned int tmp = INREG(LVDS_GEN_CNTL); + mode->lvds_gen_cntl &= ~LVDS_STATE_MASK; + mode->lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_STATE_MASK); + if ((tmp & (LVDS_ON | LVDS_BLON)) == - (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON))) - OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl); - } else { - /* DVI */ - if (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON)) { - udelay(1000); + (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON))) { OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl); } else { - OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl | - LVDS_BLON); - udelay(1000); - OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl); + if (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON)) { + udelay(1000); + OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl); + } else { + OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl | + LVDS_BLON); + udelay(1000); + OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl); + } } } } - /* unblank screen */ - OUTREG8(CRTC_EXT_CNTL + 1, 0); + radeonfb_blank(VESA_NO_BLANKING, (struct fb_info *)rinfo); + OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); + return; } +static struct fb_ops radeonfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = radeonfb_check_var, + .fb_set_par = radeonfb_set_par, + .fb_setcolreg = radeonfb_setcolreg, + .fb_pan_display = radeonfb_pan_display, + .fb_blank = radeonfb_blank, + .fb_ioctl = radeonfb_ioctl, +#if 0 + .fb_fillrect = radeonfb_fillrect, + .fb_copyarea = radeonfb_copyarea, + .fb_imageblit = radeonfb_imageblit, + .fb_rasterimg = radeonfb_rasterimg, +#else + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +#endif +}; + + +static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) +{ + struct fb_info *info; + + 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; + info->fbops = &radeonfb_ops; + info->display_fg = NULL; + info->screen_base = (char *)rinfo->fb_base; + + /* Fill fix common fields */ + strncpy(info->fix.id, rinfo->name, sizeof(info->fix.id)); + info->fix.id[sizeof(info->fix.id) - 1] = '\0'; + info->fix.smem_start = rinfo->fb_base_phys; + info->fix.smem_len = rinfo->video_ram; + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + info->fix.xpanstep = 8; + info->fix.ypanstep = 1; + info->fix.ywrapstep = 0; + info->fix.type_aux = 0; + info->fix.mmio_start = rinfo->mmio_base_phys; + info->fix.mmio_len = RADEON_REGSIZE; + if (noaccel) + info->fix.accel = FB_ACCEL_NONE; + else + info->fix.accel = FB_ACCEL_ATI_RADEON; + + if (radeon_init_disp (rinfo) < 0) + return -1; + + return 0; +} + +#ifdef CONFIG_PMAC_BACKLIGHT + +/* TODO: Dbl check these tables, we don't go up to full ON backlight + * in these, possibly because we noticed MacOS doesn't, but I'd prefer + * having some more official numbers from ATI + */ +static int backlight_conv_m6[] = { + 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, + 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 +}; +static int backlight_conv_m7[] = { + 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81, + 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9 +}; + +#define BACKLIGHT_LVDS_OFF +#undef BACKLIGHT_DAC_OFF + +/* We turn off the LCD completely instead of just dimming the backlight. + * This provides some greater power saving and the display is useless + * without backlight anyway. + */ + +static int radeon_set_backlight_enable(int on, int level, void *data) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *)data; + unsigned int lvds_gen_cntl = INREG(LVDS_GEN_CNTL); + int* conv_table; + + if (rinfo->arch == RADEON_M7) + conv_table = backlight_conv_m7; + else + conv_table = backlight_conv_m6; + + lvds_gen_cntl |= (LVDS_BL_MOD_EN | LVDS_BLON); + if (on && (level > BACKLIGHT_OFF)) { + lvds_gen_cntl |= LVDS_DIGON; + if (!lvds_gen_cntl & LVDS_ON) { + lvds_gen_cntl &= ~LVDS_BLON; + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + (void)INREG(LVDS_GEN_CNTL); + mdelay(10); + lvds_gen_cntl |= LVDS_BLON; + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + } + lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; + lvds_gen_cntl |= (conv_table[level] << + LVDS_BL_MOD_LEVEL_SHIFT); + lvds_gen_cntl |= (LVDS_ON | LVDS_EN); + lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; + } else { + lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; + lvds_gen_cntl |= (conv_table[0] << + LVDS_BL_MOD_LEVEL_SHIFT); + lvds_gen_cntl |= LVDS_DISPLAY_DIS; + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + udelay(10); + lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGON); + } + + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; + rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); + + return 0; +} + +static int radeon_set_backlight_level(int level, void *data) +{ + return radeon_set_backlight_enable(1, level, data); +} +#endif /* CONFIG_PMAC_BACKLIGHT */ + + +#ifdef CONFIG_PMAC_PBOOK + +static u32 dbg_clk; /* - * text console acceleration + * Radeon M6 Power Management code. This code currently only supports + * the mobile chips, it's based from some informations provided by ATI + * along with hours of tracing of MacOS drivers */ + +static void radeon_pm_save_regs(struct radeonfb_info *rinfo) +{ + rinfo->save_regs[0] = INPLL(PLL_PWRMGT_CNTL); + rinfo->save_regs[1] = INPLL(CLK_PWRMGT_CNTL); + rinfo->save_regs[2] = INPLL(MCLK_CNTL); + rinfo->save_regs[3] = INPLL(SCLK_CNTL); + rinfo->save_regs[4] = INPLL(CLK_PIN_CNTL); + rinfo->save_regs[5] = INPLL(VCLK_ECP_CNTL); + rinfo->save_regs[6] = INPLL(PIXCLKS_CNTL); + rinfo->save_regs[7] = INPLL(MCLK_MISC); + rinfo->save_regs[8] = INPLL(P2PLL_CNTL); + + rinfo->save_regs[9] = INREG(DISP_MISC_CNTL); + rinfo->save_regs[10] = INREG(DISP_PWR_MAN); + rinfo->save_regs[11] = INREG(LVDS_GEN_CNTL); + rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL); + rinfo->save_regs[13] = INREG(TV_DAC_CNTL); + rinfo->save_regs[14] = INREG(BUS_CNTL1); + rinfo->save_regs[15] = INREG(CRTC_OFFSET_CNTL); + rinfo->save_regs[16] = INREG(AGP_CNTL); + rinfo->save_regs[17] = (INREG(CRTC_GEN_CNTL) & 0xfdffffff) | 0x04000000; + rinfo->save_regs[18] = (INREG(CRTC2_GEN_CNTL) & 0xfdffffff) | 0x04000000; + rinfo->save_regs[19] = INREG(GPIOPAD_A); + rinfo->save_regs[20] = INREG(GPIOPAD_EN); + rinfo->save_regs[21] = INREG(GPIOPAD_MASK); + rinfo->save_regs[22] = INREG(ZV_LCDPAD_A); + rinfo->save_regs[23] = INREG(ZV_LCDPAD_EN); + rinfo->save_regs[24] = INREG(ZV_LCDPAD_MASK); + rinfo->save_regs[25] = INREG(GPIO_VGA_DDC); + rinfo->save_regs[26] = INREG(GPIO_DVI_DDC); + rinfo->save_regs[27] = INREG(GPIO_MONID); + rinfo->save_regs[28] = INREG(GPIO_CRT2_DDC); + + rinfo->save_regs[29] = INREG(SURFACE_CNTL); + rinfo->save_regs[30] = INREG(MC_FB_LOCATION); + rinfo->save_regs[31] = INREG(DISPLAY_BASE_ADDR); + rinfo->save_regs[32] = INREG(MC_AGP_LOCATION); + rinfo->save_regs[33] = INREG(CRTC2_DISPLAY_BASE_ADDR); +} +static void radeon_pm_restore_regs(struct radeonfb_info *rinfo) +{ + OUTPLL(P2PLL_CNTL, rinfo->save_regs[8] & 0xFFFFFFFE); /* First */ + + OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]); + OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]); + OUTPLL(MCLK_CNTL, rinfo->save_regs[2]); + OUTPLL(SCLK_CNTL, rinfo->save_regs[3]); + OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]); + OUTPLL(VCLK_ECP_CNTL, rinfo->save_regs[5]); + OUTPLL(PIXCLKS_CNTL, rinfo->save_regs[6]); + OUTPLL(MCLK_MISC, rinfo->save_regs[7]); + + OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]); + OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]); + OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11]); + OUTREG(LVDS_PLL_CNTL,rinfo->save_regs[12]); + OUTREG(TV_DAC_CNTL, rinfo->save_regs[13]); + OUTREG(BUS_CNTL1, rinfo->save_regs[14]); + OUTREG(CRTC_OFFSET_CNTL, rinfo->save_regs[15]); + OUTREG(AGP_CNTL, rinfo->save_regs[16]); + OUTREG(CRTC_GEN_CNTL, rinfo->save_regs[17]); + OUTREG(CRTC2_GEN_CNTL, rinfo->save_regs[18]); + + // wait VBL before that one ? + OUTPLL(P2PLL_CNTL, rinfo->save_regs[8]); + + OUTREG(GPIOPAD_A, rinfo->save_regs[19]); + OUTREG(GPIOPAD_EN, rinfo->save_regs[20]); + OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]); + OUTREG(ZV_LCDPAD_A, rinfo->save_regs[22]); + OUTREG(ZV_LCDPAD_EN, rinfo->save_regs[23]); + OUTREG(ZV_LCDPAD_MASK, rinfo->save_regs[24]); + OUTREG(GPIO_VGA_DDC, rinfo->save_regs[25]); + OUTREG(GPIO_DVI_DDC, rinfo->save_regs[26]); + OUTREG(GPIO_MONID, rinfo->save_regs[27]); + OUTREG(GPIO_CRT2_DDC, rinfo->save_regs[28]); +} -static void fbcon_radeon_bmove(struct display *p, int srcy, int srcx, - int dsty, int dstx, int height, int width) +static void radeon_pm_disable_iopad(struct radeonfb_info *rinfo) +{ + OUTREG(GPIOPAD_MASK, 0x0001ffff); + OUTREG(GPIOPAD_EN, 0x00000400); + OUTREG(GPIOPAD_A, 0x00000000); + OUTREG(ZV_LCDPAD_MASK, 0x00000000); + OUTREG(ZV_LCDPAD_EN, 0x00000000); + OUTREG(ZV_LCDPAD_A, 0x00000000); + OUTREG(GPIO_VGA_DDC, 0x00030000); + OUTREG(GPIO_DVI_DDC, 0x00000000); + OUTREG(GPIO_MONID, 0x00030000); + OUTREG(GPIO_CRT2_DDC, 0x00000000); +} + +static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo) { - struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info); - u32 dp_cntl = DST_LAST_PEL; - - srcx *= fontwidth(p); - srcy *= fontheight(p); - dstx *= fontwidth(p); - dsty *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); - - if (srcy < dsty) { - srcy += height - 1; - dsty += height - 1; - } else - dp_cntl |= DST_Y_TOP_TO_BOTTOM; - - if (srcx < dstx) { - srcx += width - 1; - dstx += width - 1; - } else - dp_cntl |= DST_X_LEFT_TO_RIGHT; - - radeon_fifo_wait(6); - OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | - GMC_BRUSH_NONE | - GMC_SRC_DATATYPE_COLOR | - ROP3_S | - DP_SRC_SOURCE_MEMORY)); - OUTREG(DP_WRITE_MSK, 0xffffffff); - OUTREG(DP_CNTL, dp_cntl); - OUTREG(SRC_Y_X, (srcy << 16) | srcx); - OUTREG(DST_Y_X, (dsty << 16) | dstx); - OUTREG(DST_HEIGHT_WIDTH, (height << 16) | width); +// +// u32 reg; +// +// OUTPLL(P2PLL_REF_DIV, 0x0c); +// +// .../... figure out what macos does here } +static void radeon_pm_low_current(struct radeonfb_info *rinfo) +{ + u32 reg; + reg = INREG(BUS_CNTL1); + reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK; + reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT); + OUTREG(BUS_CNTL1, reg); + + reg = INPLL(PLL_PWRMGT_CNTL); + reg |= PLL_PWRMGT_CNTL_SPLL_TURNOFF | PLL_PWRMGT_CNTL_PPLL_TURNOFF | + PLL_PWRMGT_CNTL_P2PLL_TURNOFF | PLL_PWRMGT_CNTL_TVPLL_TURNOFF; + reg &= ~PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK; + reg &= ~PLL_PWRMGT_CNTL_MOBILE_SU; + OUTPLL(PLL_PWRMGT_CNTL, reg); + +// reg = INPLL(TV_PLL_CNTL1); +// reg |= TV_PLL_CNTL1__TVPLL_RESET | TV_PLL_CNTL1__TVPLL_SLEEP; +// OUTPLL(TV_PLL_CNTL1, reg); + + reg = INREG(TV_DAC_CNTL); + reg &= ~(TV_DAC_CNTL_BGADJ_MASK |TV_DAC_CNTL_DACADJ_MASK); + reg |=TV_DAC_CNTL_BGSLEEP | TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD | + TV_DAC_CNTL_BDACPD | + (8<<TV_DAC_CNTL_BGADJ__SHIFT) | (8<<TV_DAC_CNTL_DACADJ__SHIFT); + OUTREG(TV_DAC_CNTL, reg); + + reg = INREG(TMDS_TRANSMITTER_CNTL); + reg &= ~(TMDS_PLL_EN |TMDS_PLLRST); + OUTREG(TMDS_TRANSMITTER_CNTL, reg); + +// lvds_pll_cntl = regr32(g, LVDS_PLL_CNTL); +// lvds_pll_cntl &= ~LVDS_PLL_CNTL__LVDS_PLL_EN; +// lvds_pll_cntl |= LVDS_PLL_CNTL__LVDS_PLL_RESET; +// regw32(g, LVDS_PLL_CNTL, lvds_pll_cntl); + + reg = INREG(DAC_CNTL); + reg &= ~DAC_CMP_EN; + OUTREG(DAC_CNTL, reg); + + reg = INREG(DAC_CNTL2); + reg &= ~DAC2_CMP_EN; + OUTREG(DAC_CNTL2, reg); + + reg = INREG(TV_DAC_CNTL); + reg &= ~TV_DAC_CNTL_DETECT; + OUTREG(TV_DAC_CNTL, reg); +} -static void fbcon_radeon_clear(struct vc_data *conp, struct display *p, - int srcy, int srcx, int height, int width) +static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo) { - struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info); - u32 clr; + /* This code is disabled. It does what is in the pm_init + * function of the MacOS driver code ATI sent me. However, + * it doesn't fix my sleep problem, and is causing other issues + * on wakeup (bascially the machine dying when switching consoles + * I haven't had time to investigate this yet + */ +#if 0 + u32 disp_misc_cntl; + u32 disp_pwr_man; + u32 temp; - clr = attr_bgcol_ec(p, conp); - clr |= (clr << 8); - clr |= (clr << 16); + // set SPLL, MPLL, PPLL, P2PLL, TVPLL, SCLK, MCLK, PCLK, P2CLK, + // TCLK and TEST_MODE to 0 + temp = INPLL(CLK_PWRMGT_CNTL); + OUTPLL(CLK_PWRMGT_CNTL , temp & ~0xc00002ff); - srcx *= fontwidth(p); - srcy *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); + // Turn on Power Management + temp = INPLL(CLK_PWRMGT_CNTL); + OUTPLL(CLK_PWRMGT_CNTL , temp | 0x00000400); - radeon_fifo_wait(6); - OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | - GMC_BRUSH_SOLID_COLOR | - GMC_SRC_DATATYPE_COLOR | - ROP3_P)); - OUTREG(DP_BRUSH_FRGD_CLR, clr); - OUTREG(DP_WRITE_MSK, 0xffffffff); - OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); - OUTREG(DST_Y_X, (srcy << 16) | srcx); - OUTREG(DST_WIDTH_HEIGHT, (width << 16) | height); + // Turn off display clock if using mobile chips + temp = INPLL(CLK_PWRMGT_CNTL); + OUTREG(CLK_PWRMGT_CNTL , temp | 0x00100000); + + // Force PIXCLK_ALWAYS_ON and PIXCLK_DAC_ALWAYS_ON + temp = INPLL(VCLK_ECP_CNTL); + OUTPLL(VCLK_ECP_CNTL, temp & ~0x000000c0); + + // Force ECP_FORCE_ON to 1 + temp = INPLL(VCLK_ECP_CNTL); + OUTPLL(VCLK_ECP_CNTL, temp | 0x00040000); + + // Force PIXCLK_BLEND_ALWAYS_ON and PIXCLK_GV_ALWAYS_ON + temp = INPLL(PIXCLKS_CNTL); + OUTPLL(PIXCLKS_CNTL, temp & ~0x00001800); + + // Forcing SCLK_CNTL to ON + OUTPLL(SCLK_CNTL, (INPLL(SCLK_CNTL)& 0x00000007) | 0xffff8000 ); + + // Set PM control over XTALIN pad + temp = INPLL(CLK_PIN_CNTL); + OUTPLL(CLK_PIN_CNTL, temp | 0x00080000); + + // Force MCLK and YCLK and MC as dynamic + temp = INPLL(MCLK_CNTL); + OUTPLL(MCLK_CNTL, temp & 0xffeaffff); + + // PLL_TURNOFF + temp = INPLL(PLL_PWRMGT_CNTL); + OUTPLL(PLL_PWRMGT_CNTL, temp | 0x0000001f); + + // set MOBILE_SU to 1 if M6 or DDR64 is detected + temp = INPLL(PLL_PWRMGT_CNTL); + OUTPLL(PLL_PWRMGT_CNTL, temp | 0x00010000); + + // select PM access mode (PM_MODE_SEL) (use ACPI mode) +// temp = INPLL(PLL_PWRMGT_CNTL); +// OUTPLL(PLL_PWRMGT_CNTL, temp | 0x00002000); + temp = INPLL(PLL_PWRMGT_CNTL); + OUTPLL(PLL_PWRMGT_CNTL, temp & ~0x00002000); + + // set DISP_MISC_CNTL register + disp_misc_cntl = INREG(DISP_MISC_CNTL); + disp_misc_cntl &= ~( DISP_MISC_CNTL_SOFT_RESET_GRPH_PP | + DISP_MISC_CNTL_SOFT_RESET_SUBPIC_PP | + DISP_MISC_CNTL_SOFT_RESET_OV0_PP | + DISP_MISC_CNTL_SOFT_RESET_GRPH_SCLK | + DISP_MISC_CNTL_SOFT_RESET_SUBPIC_SCLK | + DISP_MISC_CNTL_SOFT_RESET_OV0_SCLK | + DISP_MISC_CNTL_SOFT_RESET_GRPH2_PP | + DISP_MISC_CNTL_SOFT_RESET_GRPH2_SCLK | + DISP_MISC_CNTL_SOFT_RESET_LVDS | + DISP_MISC_CNTL_SOFT_RESET_TMDS | + DISP_MISC_CNTL_SOFT_RESET_DIG_TMDS | + DISP_MISC_CNTL_SOFT_RESET_TV); + OUTREG(DISP_MISC_CNTL, disp_misc_cntl); + + // set DISP_PWR_MAN register + disp_pwr_man = INREG(DISP_PWR_MAN); + // clau - 9.29.2000 - changes made to bit23:18 to set to 1 as requested by George + disp_pwr_man |= (DISP_PWR_MAN_DIG_TMDS_ENABLE_RST | + DISP_PWR_MAN_TV_ENABLE_RST | + // DISP_PWR_MAN_AUTO_PWRUP_EN | + DISP_PWR_MAN_DISP_D3_GRPH_RST | + DISP_PWR_MAN_DISP_D3_SUBPIC_RST | + DISP_PWR_MAN_DISP_D3_OV0_RST | + DISP_PWR_MAN_DISP_D1D2_GRPH_RST | + DISP_PWR_MAN_DISP_D1D2_SUBPIC_RST | + DISP_PWR_MAN_DISP_D1D2_OV0_RST); + disp_pwr_man &= ~(DISP_PWR_MAN_DISP_PWR_MAN_D3_CRTC_EN | + DISP_PWR_MAN_DISP2_PWR_MAN_D3_CRTC2_EN| + DISP_PWR_MAN_DISP_D3_RST | + DISP_PWR_MAN_DISP_D3_REG_RST); + OUTREG(DISP_PWR_MAN, disp_pwr_man); + + // clau - 10.24.2000 + // - add in setting for BUS_CNTL1 b27:26 = 0x01 and b31 = 0x1 + // - add in setting for AGP_CNTL b7:0 = 0x20 + // - add in setting for DVI_DDC_DATA_OUT_EN b17:16 = 0x0 + + // the following settings (two lines) are applied at a later part of this function, only on mobile platform + // requres -mobile flag + OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & 0xf3ffffff) | 0x04000000); + OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | 0x80000000); + OUTREG(AGP_CNTL, (INREG(AGP_CNTL) & 0xffffff00) | 0x20); + OUTREG(GPIO_DVI_DDC, INREG(GPIO_DVI_DDC) & 0xfffcffff); + + // yulee - 12.12.2000 + // A12 only + // EN_MCLK_TRISTATE_IN_SUSPEND@MCLK_MISC = 1 + // ACCESS_REGS_IN_SUSPEND@CLK_PIN_CNTL = 0 + // only on mobile platform + OUTPLL(MCLK_MISC, INPLL(MCLK_MISC) | 0x00040000 ); + + // yulee -12.12.2000 + // AGPCLK_VALID@BUS_CNTL1 = 1 + // MOBILE_PLATFORM_SEL@BUS_CNTL1 = 01 + // CRTC_STEREO_SYNC_OUT_EN@CRTC_OFFSET_CNTL = 0 + // CG_CLK_TO_OUTPIN@CLK_PIN_CNTL = 0 + // only on mobile platform + OUTPLL(CLK_PIN_CNTL, INPLL(CLK_PIN_CNTL ) & 0xFFFFF7FF ); + OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1 ) & 0xF3FFFFFF) | 0x84000000 ); + OUTREG(CRTC_OFFSET_CNTL, INREG(CRTC_OFFSET_CNTL ) & 0xFFEFFFFF ); + + mdelay(100); +#endif + + /* Disable CRTCs */ + OUTREG(CRTC_GEN_CNTL, (INREG(CRTC_GEN_CNTL) & ~CRTC_EN) | CRTC_DISP_REQ_EN_B); + OUTREG(CRTC2_GEN_CNTL, (INREG(CRTC2_GEN_CNTL) & ~CRTC2_EN) | CRTC2_DISP_REQ_EN_B); + (void)INREG(CRTC2_GEN_CNTL); + mdelay(17); +} + +static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) +{ + u16 pwr_cmd; + + if (!rinfo->pm_reg) + return; + + /* Set the chip into appropriate suspend mode (we use D2, + * D3 would require a compete re-initialization of the chip, + * including PCI config registers, clocks, AGP conf, ...) + */ + if (suspend) { + /* According to ATI, we should program V2CLK here, I have + * to verify what's up exactly + */ + /* Save some registers */ + radeon_pm_save_regs(rinfo); + + /* Check that on M7 too, might work might not. M7 may also + * need explicit enabling of PM + */ + if (rinfo->arch == RADEON_M6) { + /* Program V2CLK */ + radeon_pm_program_v2clk(rinfo); + + /* Disable IO PADs */ + radeon_pm_disable_iopad(rinfo); + + /* Set low current */ + radeon_pm_low_current(rinfo); + + /* Prepare chip for power management */ + radeon_pm_setup_for_suspend(rinfo); + + /* Reset the MDLL */ + OUTPLL(MDLL_CKO, INPLL(MDLL_CKO) | MCKOA_RESET); + (void)INPLL(MDLL_RDCKA); + OUTPLL(MDLL_CKO, INPLL(MDLL_CKO) & ~MCKOA_RESET); + (void)INPLL(MDLL_RDCKA); + } + + /* Switch PCI power managment to D2. */ + for (;;) { + pci_read_config_word( + rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, + &pwr_cmd); + if (pwr_cmd & 2) + break; + pci_write_config_word( + rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, + (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2); + mdelay(500); + } + } else { + /* Switch back PCI powermanagment to D0 */ + mdelay(200); + pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0); + mdelay(500); + + dbg_clk = INPLL(1); + + /* Do we need that on M7 ? */ + if (rinfo->arch == RADEON_M6) { + /* Restore the MDLL */ + OUTPLL(MDLL_CKO, INPLL(MDLL_CKO) & ~MCKOA_RESET); + (void)INPLL(MDLL_CKO); + } + + /* Restore some registers */ + radeon_pm_restore_regs(rinfo); + } +} + +/* + * Save the contents of the framebuffer when we go to sleep, + * and restore it when we wake up again. + */ + +int radeon_sleep_notify(struct pmu_sleep_notifier *self, int when) +{ + struct radeonfb_info *rinfo; + + for (rinfo = board_list; rinfo != NULL; rinfo = rinfo->next) { + struct fb_fix_screeninfo fix; + int nb; + struct display *disp; + + disp = (rinfo->currcon < 0) ? rinfo->info.disp : &fb_display[rinfo->currcon]; + + switch (rinfo->arch) { + case RADEON_M6: + case RADEON_M7: + case RADEON_M9: + break; + default: + return PBOOK_SLEEP_REFUSE; + } + + radeonfb_get_fix(&fix, fg_console, (struct fb_info *)rinfo); + nb = fb_display[fg_console].var.yres * fix.line_length; + + switch (when) { + case PBOOK_SLEEP_NOW: + acquire_console_sem(); + disp->dispsw = &fbcon_dummy; + + if (!noaccel) { + /* Make sure engine is reset */ + radeon_engine_reset(); + radeon_engine_idle(); + } + + /* Blank display and LCD */ + radeonfb_blank(VESA_POWERDOWN+1, + (struct fb_info *)rinfo); + + /* Sleep */ + rinfo->asleep = 1; + radeon_set_suspend(rinfo, 1); + release_console_sem(); + + break; + case PBOOK_WAKE: + acquire_console_sem(); + /* Wakeup */ + radeon_set_suspend(rinfo, 0); + + if (!noaccel) + radeon_engine_init(rinfo); + rinfo->asleep = 0; + radeon_set_dispsw(rinfo, disp); + radeon_load_video_mode(rinfo, &disp->var); + do_install_cmap(rinfo->currcon < 0 ? 0 : rinfo->currcon, + (struct fb_info *)rinfo); + + radeonfb_blank(0, (struct fb_info *)rinfo); + release_console_sem(); + printk("CLK_PIN_CNTL on wakeup was: %08x\n", dbg_clk); + break; + } + } + + return PBOOK_SLEEP_OK; } +#endif /* CONFIG_PMAC_PBOOK */ +static int radeonfb_pci_register (struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct radeonfb_info *rinfo; + struct radeon_chip_info *rci = &radeon_chip_info[ent->driver_data]; + u32 tmp; + + RTRACE("radeonfb_pci_register BEGIN\n"); + /* Enable device in PCI config */ + if (pci_enable_device(pdev) != 0) { + printk(KERN_ERR "radeonfb: Cannot enable PCI device\n"); + return -ENODEV; + } -#ifdef FBCON_HAS_CFB8 -static struct display_switch fbcon_radeon8 = { - .setup = fbcon_cfb8_setup, - .bmove = fbcon_radeon_bmove, - .clear = fbcon_radeon_clear, - .putc = fbcon_cfb8_putc, - .putcs = fbcon_cfb8_putcs, - .revc = fbcon_cfb8_revc, - .clear_margins = fbcon_cfb8_clear_margins, - .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + rinfo = kmalloc (sizeof (struct radeonfb_info), GFP_KERNEL); + if (!rinfo) { + printk ("radeonfb: could not allocate memory\n"); + return -ENODEV; + } + + memset (rinfo, 0, sizeof (struct radeonfb_info)); + //info = &rinfo->info; + rinfo->pdev = pdev; + strcpy(rinfo->name, rci->name); + rinfo->arch = rci->arch; + + /* Set base addrs */ + rinfo->fb_base_phys = pci_resource_start (pdev, 0); + rinfo->mmio_base_phys = pci_resource_start (pdev, 2); + + /* request the mem regions */ + if (!request_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0), "radeonfb")) { + printk ("radeonfb: cannot reserve FB region\n"); + kfree (rinfo); + return -ENODEV; + } + + if (!request_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2), "radeonfb")) { + printk ("radeonfb: cannot reserve MMIO region\n"); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + kfree (rinfo); + return -ENODEV; + } + + /* map the regions */ + rinfo->mmio_base = (u32) ioremap (rinfo->mmio_base_phys, + RADEON_REGSIZE); + if (!rinfo->mmio_base) { + printk ("radeonfb: cannot map MMIO\n"); + release_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2)); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + kfree (rinfo); + return -ENODEV; + } + + rinfo->chipset = pdev->device; + + switch (rinfo->arch) { + case RADEON_R100: + rinfo->hasCRTC2 = 0; + break; + default: + /* all the rest have it */ + rinfo->hasCRTC2 = 1; + break; + } +#if 0 + if (rinfo->arch == RADEON_M7) { + /* + * Noticed some errors in accel with M7, will have to work these out... + */ + noaccel = 1; + } +#endif + if (mirror) + printk("radeonfb: mirroring display to CRT\n"); + + /* framebuffer size */ + tmp = INREG(CONFIG_MEMSIZE); + + /* mem size is bits [28:0], mask off the rest */ + rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK; + + /* ram type */ + tmp = INREG(MEM_SDRAM_MODE_REG); + switch ((MEM_CFG_TYPE & tmp) >> 30) { + case 0: + /* SDR SGRAM (2:1) */ + strcpy(rinfo->ram_type, "SDR SGRAM"); + rinfo->ram.ml = 4; + rinfo->ram.mb = 4; + rinfo->ram.trcd = 1; + rinfo->ram.trp = 2; + rinfo->ram.twr = 1; + rinfo->ram.cl = 2; + rinfo->ram.loop_latency = 16; + rinfo->ram.rloop = 16; + + break; + case 1: + /* DDR SGRAM */ + strcpy(rinfo->ram_type, "DDR SGRAM"); + rinfo->ram.ml = 4; + rinfo->ram.mb = 4; + rinfo->ram.trcd = 3; + rinfo->ram.trp = 3; + rinfo->ram.twr = 2; + rinfo->ram.cl = 3; + rinfo->ram.tr2w = 1; + rinfo->ram.loop_latency = 16; + rinfo->ram.rloop = 16; + + break; + default: + /* 64-bit SDR SGRAM */ + strcpy(rinfo->ram_type, "SDR SGRAM 64"); + rinfo->ram.ml = 4; + rinfo->ram.mb = 8; + rinfo->ram.trcd = 3; + rinfo->ram.trp = 3; + rinfo->ram.twr = 1; + rinfo->ram.cl = 3; + rinfo->ram.tr2w = 1; + rinfo->ram.loop_latency = 17; + rinfo->ram.rloop = 17; + + break; + } + + rinfo->bios_seg = radeon_find_rom(rinfo); + radeon_get_pllinfo(rinfo, rinfo->bios_seg); + + /* + * Hack to get around some busted production M6's + * reporting no ram + */ + if (rinfo->video_ram == 0) { + switch (pdev->device) { + case PCI_DEVICE_ID_ATI_RADEON_LY: + case PCI_DEVICE_ID_ATI_RADEON_LZ: + rinfo->video_ram = 8192; + break; + default: + break; + } + } + + + RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024)); + +#if !defined(__powerpc__) + radeon_get_moninfo(rinfo); +#else + switch (pdev->device) { + case PCI_DEVICE_ID_ATI_RADEON_LW: + case PCI_DEVICE_ID_ATI_RADEON_LX: + case PCI_DEVICE_ID_ATI_RADEON_LY: + case PCI_DEVICE_ID_ATI_RADEON_LZ: + rinfo->dviDisp_type = MT_LCD; + break; + default: + radeon_get_moninfo(rinfo); + break; + } +#endif + + radeon_get_EDID(rinfo); + + if ((rinfo->dviDisp_type == MT_DFP) || (rinfo->dviDisp_type == MT_LCD) || + (rinfo->crtDisp_type == MT_DFP)) { + if (!radeon_get_dfpinfo(rinfo)) { + iounmap ((void*)rinfo->mmio_base); + release_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2)); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + kfree (rinfo); + return -ENODEV; + } + } + + rinfo->fb_base = (u32) ioremap (rinfo->fb_base_phys, + rinfo->video_ram); + if (!rinfo->fb_base) { + printk ("radeonfb: cannot map FB\n"); + iounmap ((void*)rinfo->mmio_base); + release_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2)); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + kfree (rinfo); + return -ENODEV; + } + + /* I SHOULD FIX THAT CRAP ! I should probably mimmic XFree DRI + * driver setup here. + * + * On PPC, OF based cards setup the internal memory + * mapping in strange ways. We change it so that the + * framebuffer is mapped at 0 and given half of the card's + * address space (2Gb). AGP is mapped high (0xe0000000) and + * can use up to 512Mb. Once DRI is fully implemented, we + * will have to setup the PCI remapper to remap the agp_special_page + * memory page somewhere between those regions so that the card + * use a normal PCI bus master cycle to access the ring read ptr. + * --BenH. + */ +#ifdef CONFIG_ALL_PPC + if (rinfo->hasCRTC2) + OUTREG(CRTC2_GEN_CNTL, + (INREG(CRTC2_GEN_CNTL) & ~CRTC2_EN) | CRTC2_DISP_REQ_EN_B); + OUTREG(CRTC_EXT_CNTL, INREG(CRTC_EXT_CNTL) | CRTC_DISPLAY_DIS); + OUTREG(MC_FB_LOCATION, 0x7fff0000); + OUTREG(MC_AGP_LOCATION, 0xffffe000); + OUTREG(DISPLAY_BASE_ADDR, 0x00000000); + if (rinfo->hasCRTC2) + OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0x00000000); + OUTREG(SRC_OFFSET, 0x00000000); + OUTREG(DST_OFFSET, 0x00000000); + mdelay(10); + OUTREG(CRTC_EXT_CNTL, INREG(CRTC_EXT_CNTL) & ~CRTC_DISPLAY_DIS); +#endif /* CONFIG_ALL_PPC */ + + /* save current mode regs before we switch into the new one + * so we can restore this upon __exit + */ + radeon_save_state (rinfo, &rinfo->init_state); + + if (!noaccel) { + /* initialize the engine */ + radeon_engine_init (rinfo); + } + + /* set all the vital stuff */ + radeon_set_fbinfo (rinfo); + + pci_set_drvdata(pdev, rinfo); + rinfo->next = board_list; + board_list = rinfo; + + if (register_framebuffer ((struct fb_info *) rinfo) < 0) { + printk ("radeonfb: could not register framebuffer\n"); + iounmap ((void*)rinfo->fb_base); + iounmap ((void*)rinfo->mmio_base); + release_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2)); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + kfree (rinfo); + return -ENODEV; + } + +#ifdef CONFIG_MTRR + rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys, + rinfo->video_ram, + MTRR_TYPE_WRCOMB, 1); +#endif + +#ifdef CONFIG_PMAC_BACKLIGHT + if (rinfo->dviDisp_type == MT_LCD) + register_backlight_controller(&radeon_backlight_controller, + rinfo, "ati"); +#endif + +#ifdef CONFIG_PMAC_PBOOK + if (rinfo->dviDisp_type == MT_LCD) { + rinfo->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); + pmu_register_sleep_notifier(&radeon_sleep_notifier); + } +#endif + + printk ("radeonfb: ATI Radeon %s %s %d MB\n", rinfo->name, rinfo->ram_type, + (rinfo->video_ram/(1024*1024))); + + if (rinfo->hasCRTC2) { + printk("radeonfb: DVI port %s monitor connected\n", + GET_MON_NAME(rinfo->dviDisp_type)); + printk("radeonfb: CRT port %s monitor connected\n", + GET_MON_NAME(rinfo->crtDisp_type)); + } else { + printk("radeonfb: CRT port %s monitor connected\n", + GET_MON_NAME(rinfo->crtDisp_type)); + } + + RTRACE("radeonfb_pci_register END\n"); + + return 0; +} + + + +static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev) +{ + struct radeonfb_info *rinfo = pci_get_drvdata(pdev); + + if (!rinfo) + return; + + /* restore original state + * + * Doesn't quite work yet, possibly because of the PPC hacking + * I do on startup, disable for now. --BenH + */ + radeon_write_mode (rinfo, &rinfo->init_state); + +#ifdef CONFIG_MTRR + if (rinfo->mtrr_hdl >= 0) + mtrr_del(rinfo->mtrr_hdl, 0, 0); +#endif + + unregister_framebuffer ((struct fb_info *) rinfo); + + iounmap ((void*)rinfo->mmio_base); + iounmap ((void*)rinfo->fb_base); + + release_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2)); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + + kfree (rinfo); +} + + +static struct pci_driver radeonfb_driver = { + name: "radeonfb", + id_table: radeonfb_pci_table, + probe: radeonfb_pci_register, + remove: __devexit_p(radeonfb_pci_unregister), }; + + +int __init radeonfb_init (void) +{ + return pci_module_init (&radeonfb_driver); +} + + +void __exit radeonfb_exit (void) +{ + pci_unregister_driver (&radeonfb_driver); +} + + +int __init radeonfb_setup (char *options) +{ + char *this_opt; + + if (!options || !*options) + return 0; + + while ((this_opt = strsep (&options, ",")) != NULL) { + if (!*this_opt) + continue; + if (!strncmp(this_opt, "noaccel", 7)) { + noaccel = 1; + } else if (!strncmp(this_opt, "mirror", 6)) { + mirror = 1; + } else if (!strncmp(this_opt, "dfp", 3)) { + force_dfp = 1; + } else if (!strncmp(this_opt, "panel_yres:", 11)) { + panel_yres = simple_strtoul((this_opt+11), NULL, 0); + } else if (!strncmp(this_opt, "nomtrr", 6)) { + nomtrr = 1; + } else + mode_option = this_opt; + } + + return 0; +} + +#ifdef MODULE +module_init(radeonfb_init); +module_exit(radeonfb_exit); #endif + + +MODULE_AUTHOR("Ani Joshi"); +MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c index 52ac100708bd..fb5e1020908c 100644 --- a/drivers/video/retz3fb.c +++ b/drivers/video/retz3fb.c @@ -1430,7 +1430,7 @@ int __init retz3fb_init(void) return -EINVAL; printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of " - "video memory\n", GET_FB_IDX(fb_info->node), + "video memory\n", minor(fb_info->node), fb_info->modename, zinfo->fbsize>>10); /* FIXME: This driver cannot be unloaded yet */ diff --git a/drivers/video/riva/Makefile b/drivers/video/riva/Makefile index 664fefd88eb4..d7656aacb5cc 100644 --- a/drivers/video/riva/Makefile +++ b/drivers/video/riva/Makefile @@ -4,6 +4,6 @@ obj-$(CONFIG_FB_RIVA) += rivafb.o -rivafb-objs := fbdev.o riva_hw.o accel.o +rivafb-objs := fbdev.o riva_hw.o include $(TOPDIR)/Rules.make diff --git a/drivers/video/riva/accel.c b/drivers/video/riva/accel.c deleted file mode 100644 index bea186a5f46e..000000000000 --- a/drivers/video/riva/accel.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * linux/drivers/video/accel.c - nVidia RIVA 128/TNT/TNT2 fb driver - * - * Copyright 2000 Jindrich Makovicka, Ani Joshi - * - * 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 "rivafb.h" - -/* acceleration routines */ - -inline void wait_for_idle(struct rivafb_info *rinfo) -{ - while (rinfo->riva.Busy(&rinfo->riva)); -} - -/* set copy ROP, no mask */ -static void riva_setup_ROP(struct rivafb_info *rinfo) -{ - RIVA_FIFO_FREE(rinfo->riva, Patt, 5); - rinfo->riva.Patt->Shape = 0; - rinfo->riva.Patt->Color0 = 0xffffffff; - rinfo->riva.Patt->Color1 = 0xffffffff; - rinfo->riva.Patt->Monochrome[0] = 0xffffffff; - rinfo->riva.Patt->Monochrome[1] = 0xffffffff; - - RIVA_FIFO_FREE(rinfo->riva, Rop, 1); - rinfo->riva.Rop->Rop3 = 0xCC; -} - -void riva_setup_accel(struct rivafb_info *rinfo) -{ - RIVA_FIFO_FREE(rinfo->riva, Clip, 2); - rinfo->riva.Clip->TopLeft = 0x0; - rinfo->riva.Clip->WidthHeight = 0x80008000; - riva_setup_ROP(rinfo); - wait_for_idle(rinfo); -} - -static void riva_rectfill(struct rivafb_info *rinfo, int sy, - int sx, int height, int width, u_int color) -{ - RIVA_FIFO_FREE(rinfo->riva, Bitmap, 1); - rinfo->riva.Bitmap->Color1A = color; - - RIVA_FIFO_FREE(rinfo->riva, Bitmap, 2); - rinfo->riva.Bitmap->UnclippedRectangle[0].TopLeft = (sx << 16) | sy; - rinfo->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (width << 16) | height; -} - -static void fbcon_riva_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info); - - sx *= fontwidth(p); - sy *= fontheight(p); - dx *= fontwidth(p); - dy *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); - - RIVA_FIFO_FREE(rinfo->riva, Blt, 3); - rinfo->riva.Blt->TopLeftSrc = (sy << 16) | sx; - rinfo->riva.Blt->TopLeftDst = (dy << 16) | dx; - rinfo->riva.Blt->WidthHeight = (height << 16) | width; -} - -static void riva_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only, u32 bgx) -{ - struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info); - - unsigned int right_start = conp->vc_cols*fontwidth(p); - unsigned int bottom_start = conp->vc_rows*fontheight(p); - unsigned int right_width, bottom_width; - - if (!bottom_only && (right_width = p->var.xres - right_start)) - riva_rectfill(rinfo, 0, right_start, p->var.yres_virtual, - right_width, bgx); - if ((bottom_width = p->var.yres - bottom_start)) - riva_rectfill(rinfo, p->var.yoffset + bottom_start, 0, - bottom_width, right_start, bgx); -} - -static u8 byte_rev[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -}; - -static inline void fbcon_reverse_order(u32 *l) -{ - u8 *a = (u8 *)l; - *a++ = byte_rev[*a]; -/* *a++ = byte_rev[*a]; - *a++ = byte_rev[*a];*/ - *a = byte_rev[*a]; -} - -static void fbcon_riva_writechr(struct vc_data *conp, struct display *p, - int c, int fgx, int bgx, int yy, int xx) -{ - u8 *cdat; - struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info); - int w, h; - volatile u32 *d; - u32 cdat2; - int i, j, cnt; - - w = fontwidth(p); - h = fontheight(p); - - if (w <= 8) - cdat = p->fontdata + (c & p->charmask) * h; - else - cdat = p->fontdata + ((c & p->charmask) * h << 1); - - RIVA_FIFO_FREE(rinfo->riva, Bitmap, 7); - rinfo->riva.Bitmap->ClipE.TopLeft = (yy << 16) | (xx & 0xFFFF); - rinfo->riva.Bitmap->ClipE.BottomRight = ((yy+h) << 16) | ((xx+w) & 0xffff); - rinfo->riva.Bitmap->Color0E = bgx; - rinfo->riva.Bitmap->Color1E = fgx; - rinfo->riva.Bitmap->WidthHeightInE = (h << 16) | 32; - rinfo->riva.Bitmap->WidthHeightOutE = (h << 16) | 32; - rinfo->riva.Bitmap->PointE = (yy << 16) | (xx & 0xFFFF); - - d = &rinfo->riva.Bitmap->MonochromeData01E; - for (i = h; i > 0; i-=16) { - if (i >= 16) - cnt = 16; - else - cnt = i; - RIVA_FIFO_FREE(rinfo->riva, Bitmap, cnt); - for (j = 0; j < cnt; j++) { - if (w <= 8) - cdat2 = *cdat++; - else - cdat2 = *((u16*)cdat)++; - fbcon_reverse_order(&cdat2); - d[j] = cdat2; - } - } -} - -#ifdef FBCON_HAS_CFB8 -void fbcon_riva8_setup(struct display *p) -{ - p->next_line = p->line_length ? p->line_length : p->var.xres_virtual; - p->next_plane = 0; -} - -static void fbcon_riva8_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) -{ - u32 bgx; - - struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info); - - bgx = attr_bgcol_ec(p, conp); - - sx *= fontwidth(p); - sy *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); - - riva_rectfill(rinfo, sy, sx, height, width, bgx); -} - -static void fbcon_riva8_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx) -{ - u32 fgx,bgx; - - fgx = attr_fgcol(p,c); - bgx = attr_bgcol(p,c); - - xx *= fontwidth(p); - yy *= fontheight(p); - - fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx); -} - -static void fbcon_riva8_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, - int xx) -{ - u16 c; - u32 fgx,bgx; - - xx *= fontwidth(p); - yy *= fontheight(p); - - c = scr_readw(s); - fgx = attr_fgcol(p, c); - bgx = attr_bgcol(p, c); - while (count--) { - c = scr_readw(s++); - fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx); - xx += fontwidth(p); - } -} - -static void fbcon_riva8_revc(struct display *p, int xx, int yy) -{ - struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info); - - xx *= fontwidth(p); - yy *= fontheight(p); - - RIVA_FIFO_FREE(rinfo->riva, Rop, 1); - rinfo->riva.Rop->Rop3 = 0x66; // XOR - riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0x0f); - RIVA_FIFO_FREE(rinfo->riva, Rop, 1); - rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY -} - -static void fbcon_riva8_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - riva_clear_margins(conp, p, bottom_only, attr_bgcol_ec(p, conp)); -} - -struct display_switch fbcon_riva8 = { - .setup = fbcon_riva8_setup, - .bmove = fbcon_riva_bmove, - .clear = fbcon_riva8_clear, - .putc = fbcon_riva8_putc, - .putcs = fbcon_riva8_putcs, - .revc = fbcon_riva8_revc, - .clear_margins =fbcon_riva8_clear_margins, - .fontwidthmask =FONTWIDTHRANGE(4, 16) -}; -#endif - -#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) -static void fbcon_riva1632_revc(struct display *p, int xx, int yy) -{ - struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info); - - xx *= fontwidth(p); - yy *= fontheight(p); - - RIVA_FIFO_FREE(rinfo->riva, Rop, 1); - rinfo->riva.Rop->Rop3 = 0x66; // XOR - riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0xffffffff); - RIVA_FIFO_FREE(rinfo->riva, Rop, 1); - rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY -} -#endif - -#ifdef FBCON_HAS_CFB16 -void fbcon_riva16_setup(struct display *p) -{ - p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1; - p->next_plane = 0; -} - -static void fbcon_riva16_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) -{ - u32 bgx; - - struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info); - - bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - sx *= fontwidth(p); - sy *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); - - riva_rectfill(rinfo, sy, sx, height, width, bgx); -} - -static inline void convert_bgcolor_16(u32 *col) -{ - *col = ((*col & 0x00007C00) << 9) - | ((*col & 0x000003E0) << 6) - | ((*col & 0x0000001F) << 3) - | 0xFF000000; -} - -static void fbcon_riva16_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx) -{ - u32 fgx,bgx; - - fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)]; - bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)]; - if (p->var.green.length == 6) - convert_bgcolor_16(&bgx); - xx *= fontwidth(p); - yy *= fontheight(p); - - fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx); -} - -static void fbcon_riva16_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, - int xx) -{ - u16 c; - u32 fgx,bgx; - - xx *= fontwidth(p); - yy *= fontheight(p); - - c = scr_readw(s); - fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)]; - if (p->var.green.length == 6) - convert_bgcolor_16(&bgx); - while (count--) { - c = scr_readw(s++); - fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx); - xx += fontwidth(p); - } -} - -static void fbcon_riva16_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - riva_clear_margins(conp, p, bottom_only, ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]); -} - -struct display_switch fbcon_riva16 = { - .setup = fbcon_riva16_setup, - .bmove = fbcon_riva_bmove, - .clear = fbcon_riva16_clear, - .putc = fbcon_riva16_putc, - .putcs = fbcon_riva16_putcs, - .revc = fbcon_riva1632_revc, - .clear_margins =fbcon_riva16_clear_margins, - .fontwidthmask =FONTWIDTHRANGE(4, 16) -}; -#endif - -#ifdef FBCON_HAS_CFB32 -void fbcon_riva32_setup(struct display *p) -{ - p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2; - p->next_plane = 0; -} - -static void fbcon_riva32_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) -{ - u32 bgx; - - struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info); - - bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - sx *= fontwidth(p); - sy *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); - - riva_rectfill(rinfo, sy, sx, height, width, bgx); -} - -static void fbcon_riva32_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx) -{ - u32 fgx,bgx; - - fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)]; - bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)]; - xx *= fontwidth(p); - yy *= fontheight(p); - fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx); -} - -static void fbcon_riva32_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, - int xx) -{ - u16 c; - u32 fgx,bgx; - - xx *= fontwidth(p); - yy *= fontheight(p); - - c = scr_readw(s); - fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)]; - bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)]; - while (count--) { - c = scr_readw(s++); - fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx); - xx += fontwidth(p); - } -} - -static void fbcon_riva32_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only) -{ - riva_clear_margins(conp, p, bottom_only, ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]); -} - -struct display_switch fbcon_riva32 = { - .setup = fbcon_riva32_setup, - .bmove = fbcon_riva_bmove, - .clear = fbcon_riva32_clear, - .putc = fbcon_riva32_putc, - .putcs = fbcon_riva32_putcs, - .revc = fbcon_riva1632_revc, - .clear_margins =fbcon_riva32_clear_margins, - .fontwidthmask =FONTWIDTHRANGE(4, 16) -}; -#endif diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index fa083a87938c..7321f818eacc 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -25,7 +25,6 @@ * Known bugs and issues: * restoring text mode fails * doublescan modes are broken - * option 'noaccel' has no effect */ #include <linux/config.h> @@ -34,17 +33,16 @@ #include <linux/errno.h> #include <linux/string.h> #include <linux/mm.h> -#include <linux/selection.h> #include <linux/tty.h> #include <linux/slab.h> #include <linux/delay.h> -#include <linux/fb.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/console.h> #ifdef CONFIG_MTRR #include <asm/mtrr.h> #endif + #include "rivafb.h" #include "nvreg.h" @@ -55,7 +53,7 @@ /* version number of this driver */ -#define RIVAFB_VERSION "0.9.2a" +#define RIVAFB_VERSION "0.9.3" @@ -109,10 +107,7 @@ static int rivafb_blank(int blank, struct fb_info *info); -extern void riva_setup_accel(struct rivafb_info *rinfo); -extern inline void wait_for_idle(struct rivafb_info *rinfo); - - +extern inline void wait_for_idle(struct riva_par *par); /* ------------------------------------------------------------------------- * * @@ -136,6 +131,11 @@ enum riva_chips { CH_GEFORCE2_GTS, CH_GEFORCE2_ULTRA, CH_QUADRO2_PRO, + CH_GEFORCE2_GO, + CH_GEFORCE3, + CH_GEFORCE3_1, + CH_GEFORCE3_2, + CH_QUADRO_DDC }; /* directly indexed by riva_chips enum, above */ @@ -158,6 +158,11 @@ static struct riva_chip_info { { "GeForce2-GTS", NV_ARCH_10}, { "GeForce2-ULTRA", NV_ARCH_10}, { "Quadro2-PRO", NV_ARCH_10}, + { "GeForce2-Go", NV_ARCH_10}, + { "GeForce3", NV_ARCH_20}, + { "GeForce3 Ti 200", NV_ARCH_20}, + { "GeForce3 Ti 500", NV_ARCH_20}, + { "Quadro DDC", NV_ARCH_20} }; static struct pci_device_id rivafb_pci_tbl[] __devinitdata = { @@ -195,6 +200,16 @@ static struct pci_device_id rivafb_pci_tbl[] __devinitdata = { 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 }, { 0, } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl); @@ -207,24 +222,9 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl); * * ------------------------------------------------------------------------- */ -#ifdef FBCON_HAS_CFB8 extern struct display_switch fbcon_riva8; -#endif -#ifdef FBCON_HAS_CFB16 extern struct display_switch fbcon_riva16; -#endif -#ifdef FBCON_HAS_CFB32 extern struct display_switch fbcon_riva32; -#endif - -#if 0 -/* describes the state of a Riva board */ -struct rivafb_par { - struct riva_regs state; /* state of hw board */ - __u32 visual; /* FB_VISUAL_xxx */ - unsigned depth; /* bpp of current mode */ -}; -#endif struct riva_cursor { int enable; @@ -239,59 +239,56 @@ struct riva_cursor { struct timer_list *timer; }; - - /* ------------------------------------------------------------------------- * * * global variables * * ------------------------------------------------------------------------- */ -struct rivafb_info *riva_boards = NULL; - /* command line data, set in rivafb_setup() */ -static char fontname[40] __initdata = { 0 }; -static char noaccel __initdata = 0; -static char nomove = 0; -static char nohwcursor __initdata = 0; -static char noblink = 0; +static u32 pseudo_palette[17]; #ifdef CONFIG_MTRR static char nomtrr __initdata = 0; #endif #ifndef MODULE static char *mode_option __initdata = NULL; -#else -static char *font = NULL; #endif +static struct fb_fix_screeninfo rivafb_fix = { + id: "nVidia", + type: FB_TYPE_PACKED_PIXELS, + xpanstep: 1, + ypanstep: 1, +}; + static struct fb_var_screeninfo rivafb_default_var = { - .xres = 640, - .yres = 480, - .xres_virtual = 640, - .yres_virtual = 480, - .xoffset = 0, - .yoffset = 0, - .bits_per_pixel =8, - .grayscale = 0, - .red = {0, 6, 0}, - .green = {0, 6, 0}, - .blue = {0, 6, 0}, - .transp = {0, 0, 0}, - .nonstd = 0, - .activate = 0, - .height = -1, - .width = -1, - .accel_flags = 0, - .pixclock = 39721, - .left_margin = 40, - .right_margin = 24, - .upper_margin = 32, - .lower_margin = 11, - .hsync_len = 96, - .vsync_len = 2, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED + xres: 640, + yres: 480, + xres_virtual: 640, + yres_virtual: 480, + xoffset: 0, + yoffset: 0, + bits_per_pixel: 8, + grayscale: 0, + red: {0, 6, 0}, + green: {0, 6, 0}, + blue: {0, 6, 0}, + transp: {0, 0, 0}, + nonstd: 0, + activate: 0, + height: -1, + width: -1, + accel_flags: FB_ACCELF_TEXT, + pixclock: 39721, + left_margin: 40, + right_margin: 24, + upper_margin: 32, + lower_margin: 11, + hsync_len: 96, + vsync_len: 2, + sync: 0, + vmode: FB_VMODE_NONINTERLACED }; /* from GGI */ @@ -323,70 +320,70 @@ static const struct riva_regs reg_template = { * * ------------------------------------------------------------------------- */ -static inline void CRTCout(struct rivafb_info *rinfo, unsigned char index, +static inline void CRTCout(struct riva_par *par, unsigned char index, unsigned char val) { - VGA_WR08(rinfo->riva.PCIO, 0x3d4, index); - VGA_WR08(rinfo->riva.PCIO, 0x3d5, val); + VGA_WR08(par->riva.PCIO, 0x3d4, index); + VGA_WR08(par->riva.PCIO, 0x3d5, val); } -static inline unsigned char CRTCin(struct rivafb_info *rinfo, +static inline unsigned char CRTCin(struct riva_par *par, unsigned char index) { - VGA_WR08(rinfo->riva.PCIO, 0x3d4, index); - return (VGA_RD08(rinfo->riva.PCIO, 0x3d5)); + VGA_WR08(par->riva.PCIO, 0x3d4, index); + return (VGA_RD08(par->riva.PCIO, 0x3d5)); } -static inline void GRAout(struct rivafb_info *rinfo, unsigned char index, +static inline void GRAout(struct riva_par *par, unsigned char index, unsigned char val) { - VGA_WR08(rinfo->riva.PVIO, 0x3ce, index); - VGA_WR08(rinfo->riva.PVIO, 0x3cf, val); + VGA_WR08(par->riva.PVIO, 0x3ce, index); + VGA_WR08(par->riva.PVIO, 0x3cf, val); } -static inline unsigned char GRAin(struct rivafb_info *rinfo, +static inline unsigned char GRAin(struct riva_par *par, unsigned char index) { - VGA_WR08(rinfo->riva.PVIO, 0x3ce, index); - return (VGA_RD08(rinfo->riva.PVIO, 0x3cf)); + VGA_WR08(par->riva.PVIO, 0x3ce, index); + return (VGA_RD08(par->riva.PVIO, 0x3cf)); } -static inline void SEQout(struct rivafb_info *rinfo, unsigned char index, +static inline void SEQout(struct riva_par *par, unsigned char index, unsigned char val) { - VGA_WR08(rinfo->riva.PVIO, 0x3c4, index); - VGA_WR08(rinfo->riva.PVIO, 0x3c5, val); + VGA_WR08(par->riva.PVIO, 0x3c4, index); + VGA_WR08(par->riva.PVIO, 0x3c5, val); } -static inline unsigned char SEQin(struct rivafb_info *rinfo, +static inline unsigned char SEQin(struct riva_par *par, unsigned char index) { - VGA_WR08(rinfo->riva.PVIO, 0x3c4, index); - return (VGA_RD08(rinfo->riva.PVIO, 0x3c5)); + VGA_WR08(par->riva.PVIO, 0x3c4, index); + return (VGA_RD08(par->riva.PVIO, 0x3c5)); } -static inline void ATTRout(struct rivafb_info *rinfo, unsigned char index, +static inline void ATTRout(struct riva_par *par, unsigned char index, unsigned char val) { - VGA_WR08(rinfo->riva.PCIO, 0x3c0, index); - VGA_WR08(rinfo->riva.PCIO, 0x3c0, val); + VGA_WR08(par->riva.PCIO, 0x3c0, index); + VGA_WR08(par->riva.PCIO, 0x3c0, val); } -static inline unsigned char ATTRin(struct rivafb_info *rinfo, +static inline unsigned char ATTRin(struct riva_par *par, unsigned char index) { - VGA_WR08(rinfo->riva.PCIO, 0x3c0, index); - return (VGA_RD08(rinfo->riva.PCIO, 0x3c1)); + VGA_WR08(par->riva.PCIO, 0x3c0, index); + return (VGA_RD08(par->riva.PCIO, 0x3c1)); } -static inline void MISCout(struct rivafb_info *rinfo, unsigned char val) +static inline void MISCout(struct riva_par *par, unsigned char val) { - VGA_WR08(rinfo->riva.PVIO, 0x3c2, val); + VGA_WR08(par->riva.PVIO, 0x3c2, val); } -static inline unsigned char MISCin(struct rivafb_info *rinfo) +static inline unsigned char MISCin(struct riva_par *par) { - return (VGA_RD08(rinfo->riva.PVIO, 0x3cc)); + return (VGA_RD08(par->riva.PVIO, 0x3cc)); } @@ -398,240 +395,63 @@ static inline unsigned char MISCin(struct rivafb_info *rinfo) * ------------------------------------------------------------------------- */ /** - * riva_cursor_timer_handler - blink timer - * @dev_addr: pointer to rivafb_info object containing info for current riva board - * - * DESCRIPTION: - * Cursor blink timer. - */ -static void riva_cursor_timer_handler(unsigned long dev_addr) -{ - struct rivafb_info *rinfo = (struct rivafb_info *)dev_addr; - - if (!rinfo->cursor) return; - - if (!rinfo->cursor->enable) goto out; - - if (rinfo->cursor->last_move_delay < 1000) - rinfo->cursor->last_move_delay++; - - if (rinfo->cursor->vbl_cnt && --rinfo->cursor->vbl_cnt == 0) { - rinfo->cursor->on ^= 1; - if (rinfo->cursor->on) - *(rinfo->riva.CURSORPOS) = (rinfo->cursor->pos.x & 0xFFFF) - | (rinfo->cursor->pos.y << 16); - rinfo->riva.ShowHideCursor(&rinfo->riva, rinfo->cursor->on); - if (!noblink) - rinfo->cursor->vbl_cnt = rinfo->cursor->blink_rate; - } -out: - rinfo->cursor->timer->expires = jiffies + (HZ / 100); - add_timer(rinfo->cursor->timer); -} - -/** - * rivafb_init_cursor - allocates cursor structure and starts blink timer - * @rinfo: pointer to rivafb_info object containing info for current riva board - * - * DESCRIPTION: - * Allocates cursor structure and starts blink timer. - * - * RETURNS: - * Pointer to allocated cursor structure. - * - * CALLED FROM: - * rivafb_init_one() - */ -static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo) -{ - struct riva_cursor *cursor; - - cursor = kmalloc(sizeof(struct riva_cursor), GFP_KERNEL); - if (!cursor) return 0; - memset(cursor, 0, sizeof(*cursor)); - - cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL); - if (!cursor->timer) { - kfree(cursor); - return 0; - } - memset(cursor->timer, 0, sizeof(*cursor->timer)); - - cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE; - - init_timer(cursor->timer); - cursor->timer->expires = jiffies + (HZ / 100); - cursor->timer->data = (unsigned long)rinfo; - cursor->timer->function = riva_cursor_timer_handler; - add_timer(cursor->timer); - - return cursor; -} - -/** - * rivafb_exit_cursor - stops blink timer and releases cursor structure - * @rinfo: pointer to rivafb_info object containing info for current riva board - * - * DESCRIPTION: - * Stops blink timer and releases cursor structure. - * - * CALLED FROM: - * rivafb_init_one() - * rivafb_remove_one() - */ -static void rivafb_exit_cursor(struct rivafb_info *rinfo) -{ - struct riva_cursor *cursor = rinfo->cursor; - - if (cursor) { - if (cursor->timer) { - del_timer_sync(cursor->timer); - kfree(cursor->timer); - } - kfree(cursor); - rinfo->cursor = 0; - } -} - -/** - * rivafb_download_cursor - writes cursor shape into card registers - * @rinfo: pointer to rivafb_info object containing info for current riva board - * - * DESCRIPTION: - * Writes cursor shape into card registers. - * - * CALLED FROM: - * riva_load_video_mode() - */ -static void rivafb_download_cursor(struct rivafb_info *rinfo) -{ - int i, save; - int *image; - - if (!rinfo->cursor) return; - - image = (int *)rinfo->cursor->image; - save = rinfo->riva.ShowHideCursor(&rinfo->riva, 0); - for (i = 0; i < (MAX_CURS*MAX_CURS*2)/sizeof(int); i++) - writel(image[i], rinfo->riva.CURSOR + i); - - rinfo->riva.ShowHideCursor(&rinfo->riva, save); -} - -/** - * rivafb_create_cursor - sets rectangular cursor - * @rinfo: pointer to rivafb_info object containing info for current riva board - * @width: cursor width in pixels - * @height: cursor height in pixels - * - * DESCRIPTION: - * Sets rectangular cursor. + * rivafb_load_cursor_image - load cursor image to hardware + * @data: address to monochrome bitmap (1 = foreground color, 0 = background) + * @mask: address to mask (1 = write image pixel, 0 = do not write pixel) + * @par: pointer to private data + * @w: width of cursor image in pixels + * @h: height of cursor image in scanlines + * @bg: background color (ARGB1555) - alpha bit determines opacity + * @fg: foreground color (ARGB1555) + * + * DESCRIPTiON: + * Loads cursor image based on a monochrome source and mask bitmap. The + * mask bit determines if the image pixel is to be written to the framebuffer + * or not. The imaage bits determines the color of the pixel, 0 for + * background, 1 for foreground. Only the affected region (as determined + * by @w and @h parameters) will be updated. * * CALLED FROM: - * rivafb_set_font() - * rivafb_set_var() - */ -static void rivafb_create_cursor(struct rivafb_info *rinfo, int width, int height) -{ - struct riva_cursor *c = rinfo->cursor; - int i, j, idx; - - if (c) { - if (width <= 0 || height <= 0) { - width = 8; - height = 16; - } - if (width > MAX_CURS) width = MAX_CURS; - if (height > MAX_CURS) height = MAX_CURS; - - c->size.x = width; - c->size.y = height; - - idx = 0; - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++,idx++) - c->image[idx] = CURSOR_COLOR; - for (j = width; j < MAX_CURS; j++,idx++) - c->image[idx] = TRANSPARENT_COLOR; - } - for (i = height; i < MAX_CURS; i++) - for (j = 0; j < MAX_CURS; j++,idx++) - c->image[idx] = TRANSPARENT_COLOR; - } -} - -/** - * rivafb_set_font - change font size - * @p: pointer to display object - * @width: font width in pixels - * @height: font height in pixels - * - * DESCRIPTION: - * Callback function called if font settings changed. - * - * RETURNS: - * 1 (Always succeeds.) - */ -static int rivafb_set_font(struct display *p, int width, int height) -{ - struct rivafb_info *fb = (struct rivafb_info *)(p->fb_info); - - rivafb_create_cursor(fb, width, height); - return 1; -} - -/** - * rivafb_cursor - cursor handler - * @p: pointer to display object - * @mode: cursor mode (see CM_*) - * @x: cursor x coordinate in characters - * @y: cursor y coordinate in characters - * - * DESCRIPTION: - * Cursor handler. + * rivafb_cursor() */ -static void rivafb_cursor(struct display *p, int mode, int x, int y) +static void rivafb_load_cursor_image(u8 *data, u8 *mask, struct riva_par *par, + int w, int h, u16 bg, u16 fg) { - struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info); - struct riva_cursor *c = rinfo->cursor; - - if (!c) return; - - x = x * fontwidth(p) - p->var.xoffset; - y = y * fontheight(p) - p->var.yoffset; - - if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable) - return; - - c->enable = 0; - if (c->on) rinfo->riva.ShowHideCursor(&rinfo->riva, 0); - - c->pos.x = x; - c->pos.y = y; - - switch (mode) { - case CM_ERASE: - c->on = 0; - break; - case CM_DRAW: - case CM_MOVE: - if (c->last_move_delay <= 1) { /* rapid cursor movement */ - c->vbl_cnt = CURSOR_SHOW_DELAY; - } else { - *(rinfo->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16); - rinfo->riva.ShowHideCursor(&rinfo->riva, 1); - if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY; - c->on = 1; + int i, j, k = 0; + u32 b, m, tmp; + + + for (i = 0; i < h; i++) { + b = *((u32 *)data)++; + m = *((u32 *)mask)++; + for (j = 0; j < w/2; j++) { + tmp = 0; +#if defined (__BIG_ENDIAN__) + if (m & (1 << 31)) + tmp = (b & (1 << 31)) ? fg << 16 : bg << 16; + b <<= 1; + m <<= 1; + + if (m & (1 << 31)) + tmp |= (b & (1 << 31)) ? fg : bg; + b <<= 1; + m <<= 1; +#else + if (m & 1) + tmp = (b & 1) ? fg : bg; + b >>= 1; + m >>= 1; + if (m & 1) + tmp |= (b & 1) ? fg << 16 : bg << 16; + b >>= 1; + m >>= 1; +#endif + writel(tmp, par->riva.CURSOR + k++); } - c->last_move_delay = 0; - c->enable = 1; - break; + k += (MAX_CURS - w)/2; } } - - /* ------------------------------------------------------------------------- * * * general utility functions @@ -639,80 +459,6 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y) * ------------------------------------------------------------------------- */ /** - * riva_set_dispsw - sets dispsw - * @rinfo: pointer to internal driver struct for a given Riva card - * @disp: pointer to display object - * - * DESCRIPTION: - * Sets up console low level operations depending on the current? color depth - * of the display. - * - * CALLED FROM: - * rivafb_set_var() - * rivafb_switch() - * riva_init_disp() - */ -static void riva_set_dispsw(struct rivafb_info *rinfo, struct display *disp) -{ - int accel = disp->var.accel_flags & FB_ACCELF_TEXT; - - DPRINTK("ENTER\n"); - - assert(rinfo != NULL); - - disp->dispsw_data = NULL; - - disp->type = FB_TYPE_PACKED_PIXELS; - disp->type_aux = 0; - disp->ypanstep = 1; - disp->ywrapstep = 0; - disp->can_soft_blank = 1; - disp->inverse = 0; - - switch (disp->var.bits_per_pixel) { -#ifdef FBCON_HAS_CFB8 - case 8: - rinfo->dispsw = accel ? fbcon_riva8 : fbcon_cfb8; - disp->dispsw = &rinfo->dispsw; - disp->line_length = disp->var.xres_virtual; - disp->visual = FB_VISUAL_PSEUDOCOLOR; - break; -#endif -#ifdef FBCON_HAS_CFB16 - case 16: - rinfo->dispsw = accel ? fbcon_riva16 : fbcon_cfb16; - disp->dispsw_data = &rinfo->con_cmap.cfb16; - disp->dispsw = &rinfo->dispsw; - disp->line_length = disp->var.xres_virtual * 2; - disp->visual = FB_VISUAL_DIRECTCOLOR; - break; -#endif -#ifdef FBCON_HAS_CFB32 - case 32: - rinfo->dispsw = accel ? fbcon_riva32 : fbcon_cfb32; - disp->dispsw_data = rinfo->con_cmap.cfb32; - disp->dispsw = &rinfo->dispsw; - disp->line_length = disp->var.xres_virtual * 4; - disp->visual = FB_VISUAL_DIRECTCOLOR; - break; -#endif - default: - DPRINTK("Setting fbcon_dummy renderer\n"); - rinfo->dispsw = fbcon_dummy; - disp->dispsw = &rinfo->dispsw; - } - - /* FIXME: verify that the above code sets dsp->* fields correctly */ - - if (rinfo->cursor) { - rinfo->dispsw.cursor = rivafb_cursor; - rinfo->dispsw.set_font = rivafb_set_font; - } - - DPRINTK("EXIT\n"); -} - -/** * riva_wclut - set CLUT entry * @chip: pointer to RIVA_HW_INST object * @regnum: register number @@ -738,7 +484,7 @@ static void riva_wclut(RIVA_HW_INST *chip, /** * riva_save_state - saves current chip state - * @rinfo: pointer to rivafb_info object containing info for current riva board + * @par: pointer to riva_par object containing info for current riva board * @regs: pointer to riva_regs object * * DESCRIPTION: @@ -748,36 +494,36 @@ static void riva_wclut(RIVA_HW_INST *chip, * rivafb_init_one() */ /* from GGI */ -static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs) +static void riva_save_state(struct riva_par *par, struct riva_regs *regs) { int i; - rinfo->riva.LockUnlock(&rinfo->riva, 0); + par->riva.LockUnlock(&par->riva, 0); - rinfo->riva.UnloadStateExt(&rinfo->riva, ®s->ext); + par->riva.UnloadStateExt(&par->riva, ®s->ext); - regs->misc_output = MISCin(rinfo); + regs->misc_output = MISCin(par); for (i = 0; i < NUM_CRT_REGS; i++) { - regs->crtc[i] = CRTCin(rinfo, i); + regs->crtc[i] = CRTCin(par, i); } for (i = 0; i < NUM_ATC_REGS; i++) { - regs->attr[i] = ATTRin(rinfo, i); + regs->attr[i] = ATTRin(par, i); } for (i = 0; i < NUM_GRC_REGS; i++) { - regs->gra[i] = GRAin(rinfo, i); + regs->gra[i] = GRAin(par, i); } for (i = 0; i < NUM_SEQ_REGS; i++) { - regs->seq[i] = SEQin(rinfo, i); + regs->seq[i] = SEQin(par, i); } } /** * riva_load_state - loads current chip state - * @rinfo: pointer to rivafb_info object containing info for current riva board + * @par: pointer to riva_par object containing info for current riva board * @regs: pointer to riva_regs object * * DESCRIPTION: @@ -789,18 +535,18 @@ static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs) * rivafb_remove_one() */ /* from GGI */ -static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs) +static void riva_load_state(struct riva_par *par, struct riva_regs *regs) { - int i; RIVA_HW_STATE *state = ®s->ext; + int i; - CRTCout(rinfo, 0x11, 0x00); + CRTCout(par, 0x11, 0x00); - rinfo->riva.LockUnlock(&rinfo->riva, 0); + par->riva.LockUnlock(&par->riva, 0); - rinfo->riva.LoadStateExt(&rinfo->riva, state); + par->riva.LoadStateExt(&par->riva, state); - MISCout(rinfo, regs->misc_output); + MISCout(par, regs->misc_output); for (i = 0; i < NUM_CRT_REGS; i++) { switch (i) { @@ -808,26 +554,26 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs) case 0x20 ... 0x40: break; default: - CRTCout(rinfo, i, regs->crtc[i]); + CRTCout(par, i, regs->crtc[i]); } } for (i = 0; i < NUM_ATC_REGS; i++) { - ATTRout(rinfo, i, regs->attr[i]); + ATTRout(par, i, regs->attr[i]); } for (i = 0; i < NUM_GRC_REGS; i++) { - GRAout(rinfo, i, regs->gra[i]); + GRAout(par, i, regs->gra[i]); } for (i = 0; i < NUM_SEQ_REGS; i++) { - SEQout(rinfo, i, regs->seq[i]); + SEQout(par, i, regs->seq[i]); } } /** * riva_load_video_mode - calculate timings - * @rinfo: pointer to rivafb_info object containing info for current riva board + * @info: pointer to fb_info object containing info for current riva board * @video_mode: video mode to set * * DESCRIPTION: @@ -836,36 +582,36 @@ static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs) * CALLED FROM: * rivafb_set_var() */ -static void riva_load_video_mode(struct rivafb_info *rinfo, - struct fb_var_screeninfo *video_mode) +static void riva_load_video_mode(struct fb_info *info) { - struct riva_regs newmode; int bpp, width, hDisplaySize, hDisplay, hStart, hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock; + struct riva_par *par = (struct riva_par *) info->par; + struct riva_regs newmode; /* time to calculate */ - rivafb_blank(1, (struct fb_info *)rinfo); + rivafb_blank(1, info); - bpp = video_mode->bits_per_pixel; - if (bpp == 16 && video_mode->green.length == 5) + bpp = info->var.bits_per_pixel; + if (bpp == 16 && info->var.green.length == 5) bpp = 15; - width = video_mode->xres_virtual; - hDisplaySize = video_mode->xres; + width = info->var.xres_virtual; + hDisplaySize = info->var.xres; hDisplay = (hDisplaySize / 8) - 1; - hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2; - hEnd = (hDisplaySize + video_mode->right_margin + - video_mode->hsync_len) / 8 - 1; - hTotal = (hDisplaySize + video_mode->right_margin + - video_mode->hsync_len + video_mode->left_margin) / 8 - 1; - height = video_mode->yres_virtual; - vDisplay = video_mode->yres - 1; - vStart = video_mode->yres + video_mode->lower_margin - 1; - vEnd = video_mode->yres + video_mode->lower_margin + - video_mode->vsync_len - 1; - vTotal = video_mode->yres + video_mode->lower_margin + - video_mode->vsync_len + video_mode->upper_margin + 2; - dotClock = 1000000000 / video_mode->pixclock; + hStart = (hDisplaySize + info->var.right_margin) / 8 + 2; + 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; + height = info->var.yres_virtual; + vDisplay = info->var.yres - 1; + vStart = info->var.yres + info->var.lower_margin - 1; + vEnd = info->var.yres + info->var.lower_margin + + info->var.vsync_len - 1; + vTotal = info->var.yres + info->var.lower_margin + + info->var.vsync_len + info->var.upper_margin + 2; + dotClock = 1000000000 / info->var.pixclock; memcpy(&newmode, ®_template, sizeof(struct riva_regs)); @@ -899,83 +645,19 @@ static void riva_load_video_mode(struct rivafb_info *rinfo, newmode.ext.width = width; newmode.ext.height = height; - rinfo->riva.CalcStateExt(&rinfo->riva, &newmode.ext, bpp, width, + par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width, hDisplaySize, hDisplay, hStart, hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock); - rinfo->current_state = newmode; - riva_load_state(rinfo, &rinfo->current_state); - - rinfo->riva.LockUnlock(&rinfo->riva, 0); /* important for HW cursor */ - rivafb_download_cursor(rinfo); -} - -/** - * riva_board_list_add - maintains board list - * @board_list: root node of list of boards - * @new_node: new node to be added - * - * DESCRIPTION: - * Adds @new_node to the list referenced by @board_list. - * - * RETURNS: - * New root node - * - * CALLED FROM: - * rivafb_init_one() - */ -static struct rivafb_info *riva_board_list_add(struct rivafb_info *board_list, - struct rivafb_info *new_node) -{ - struct rivafb_info *i_p = board_list; - - new_node->next = NULL; - - if (board_list == NULL) - return new_node; - - while (i_p->next != NULL) - i_p = i_p->next; - i_p->next = new_node; - - return board_list; -} - -/** - * riva_board_list_del - maintains board list - * @board_list: root node of list of boards - * @del_node: node to be removed - * - * DESCRIPTION: - * Removes @del_node from the list referenced by @board_list. - * - * RETURNS: - * New root node - * - * CALLED FROM: - * rivafb_remove_one() - */ -static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list, - struct rivafb_info *del_node) -{ - struct rivafb_info *i_p = board_list; - - if (board_list == del_node) - return del_node->next; - - while (i_p->next != del_node) - i_p = i_p->next; - i_p->next = del_node->next; - - return board_list; + par->current_state = newmode; + riva_load_state(par, &par->current_state); } /** * rivafb_do_maximize - - * @rinfo: pointer to rivafb_info object containing info for current riva board + * @info: pointer to fb_info object containing info for current riva board * @var: - * @v: * @nom: * @den: * @@ -989,9 +671,8 @@ static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list, * CALLED FROM: * rivafb_set_var() */ -static int rivafb_do_maximize(struct rivafb_info *rinfo, +static int rivafb_do_maximize(struct fb_info *info, struct fb_var_screeninfo *var, - struct fb_var_screeninfo *v, int nom, int den) { static struct { @@ -1007,12 +688,12 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo, int i; /* use highest possible virtual resolution */ - if (v->xres_virtual == -1 && v->yres_virtual == -1) { + if (var->xres_virtual == -1 && var->yres_virtual == -1) { printk(KERN_WARNING PFX "using maximum available virtual resolution\n"); for (i = 0; modes[i].xres != -1; i++) { if (modes[i].xres * nom / den * modes[i].yres < - rinfo->ram_amount / 2) + info->fix.smem_len / 2) break; } if (modes[i].xres == -1) { @@ -1021,26 +702,26 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo, DPRINTK("EXIT - EINVAL error\n"); return -EINVAL; } - v->xres_virtual = modes[i].xres; - v->yres_virtual = modes[i].yres; + var->xres_virtual = modes[i].xres; + var->yres_virtual = modes[i].yres; printk(KERN_INFO PFX "virtual resolution set to maximum of %dx%d\n", - v->xres_virtual, v->yres_virtual); - } else if (v->xres_virtual == -1) { - v->xres_virtual = (rinfo->ram_amount * den / - (nom * v->yres_virtual * 2)) & ~15; + var->xres_virtual, var->yres_virtual); + } else if (var->xres_virtual == -1) { + var->xres_virtual = (info->fix.smem_len * den / + (nom * var->yres_virtual * 2)) & ~15; printk(KERN_WARNING PFX - "setting virtual X resolution to %d\n", v->xres_virtual); - } else if (v->yres_virtual == -1) { - v->xres_virtual = (v->xres_virtual + 15) & ~15; - v->yres_virtual = rinfo->ram_amount * den / - (nom * v->xres_virtual * 2); + "setting virtual X resolution to %d\n", var->xres_virtual); + } else if (var->yres_virtual == -1) { + var->xres_virtual = (var->xres_virtual + 15) & ~15; + var->yres_virtual = info->fix.smem_len * den / + (nom * var->xres_virtual * 2); printk(KERN_WARNING PFX - "setting virtual Y resolution to %d\n", v->yres_virtual); + "setting virtual Y resolution to %d\n", var->yres_virtual); } else { - v->xres_virtual = (v->xres_virtual + 15) & ~15; - if (v->xres_virtual * nom / den * v->yres_virtual > rinfo->ram_amount) { + var->xres_virtual = (var->xres_virtual + 15) & ~15; + if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) { printk(KERN_ERR PFX "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", var->xres, var->yres, var->bits_per_pixel); @@ -1049,397 +730,535 @@ static int rivafb_do_maximize(struct rivafb_info *rinfo, } } - if (v->xres_virtual * nom / den >= 8192) { + if (var->xres_virtual * nom / den >= 8192) { printk(KERN_WARNING PFX "virtual X resolution (%d) is too high, lowering to %d\n", - v->xres_virtual, 8192 * den / nom - 16); - v->xres_virtual = 8192 * den / nom - 16; + var->xres_virtual, 8192 * den / nom - 16); + var->xres_virtual = 8192 * den / nom - 16; } - if (v->xres_virtual < v->xres) { + if (var->xres_virtual < var->xres) { printk(KERN_ERR PFX - "virtual X resolution (%d) is smaller than real\n", v->xres_virtual); + "virtual X resolution (%d) is smaller than real\n", var->xres_virtual); return -EINVAL; } - if (v->yres_virtual < v->yres) { + if (var->yres_virtual < var->yres) { printk(KERN_ERR PFX - "virtual Y resolution (%d) is smaller than real\n", v->yres_virtual); + "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual); return -EINVAL; } - return 0; } +/* acceleration routines */ +inline void wait_for_idle(struct riva_par *par) +{ + while (par->riva.Busy(&par->riva)); +} +/* set copy ROP, no mask */ +static void riva_setup_ROP(struct riva_par *par) +{ + RIVA_FIFO_FREE(par->riva, Patt, 5); + par->riva.Patt->Shape = 0; + par->riva.Patt->Color0 = 0xffffffff; + par->riva.Patt->Color1 = 0xffffffff; + par->riva.Patt->Monochrome[0] = 0xffffffff; + par->riva.Patt->Monochrome[1] = 0xffffffff; + + RIVA_FIFO_FREE(par->riva, Rop, 1); + par->riva.Rop->Rop3 = 0xCC; +} -/* ------------------------------------------------------------------------- * - * - * internal fb_ops helper functions - * - * ------------------------------------------------------------------------- */ +void riva_setup_accel(struct riva_par *par) +{ + RIVA_FIFO_FREE(par->riva, Clip, 2); + par->riva.Clip->TopLeft = 0x0; + par->riva.Clip->WidthHeight = 0x80008000; + riva_setup_ROP(par); +} /** - * riva_get_cmap_len - query current color map length - * @var: standard kernel fb changeable data - * + * rivafb_fillrect - hardware accelerated color fill function + * @info: pointer to fb_info structure + * @rect: pointer to fb_fillrect structure + * * DESCRIPTION: - * Get current color map length. - * - * RETURNS: - * Length of color map + * This function fills up a region of framebuffer memory with a solid + * color with a choice of two different ROP's, copy or invert. * * CALLED FROM: - * riva_getcolreg() - * rivafb_setcolreg() - * rivafb_get_cmap() - * rivafb_set_cmap() + * framebuffer hook */ -static int riva_get_cmap_len(const struct fb_var_screeninfo *var) +static void rivafb_fillrect(struct fb_info *info, struct fb_fillrect *rect) { - int rc = 16; /* reasonable default */ + struct riva_par *par = (struct riva_par *) info->par; + u_int color, rop = 0; - assert(var != NULL); + if (info->var.bits_per_pixel == 8) + color = rect->color; + else + color = par->riva_palette[rect->color]; - switch (var->bits_per_pixel) { -#ifdef FBCON_HAS_CFB8 - case 8: - rc = 256; /* pseudocolor... 256 entries HW palette */ + switch (rect->rop) { + case ROP_XOR: + rop = 0x66; break; -#endif -#ifdef FBCON_HAS_CFB16 - case 15: - rc = 15; /* fix for 15 bpp depths on Riva 128 based cards */ - break; - case 16: - rc = 16; /* directcolor... 16 entries SW palette */ - break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */ -#endif -#ifdef FBCON_HAS_CFB32 - case 32: - rc = 16; /* directcolor... 16 entries SW palette */ - break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */ -#endif + case ROP_COPY: default: - /* should not occur */ + rop = 0xCC; break; } - return rc; + RIVA_FIFO_FREE(par->riva, Rop, 1); + par->riva.Rop->Rop3 = rop; + + RIVA_FIFO_FREE(par->riva, Bitmap, 1); + par->riva.Bitmap->Color1A = color; + + RIVA_FIFO_FREE(par->riva, Bitmap, 2); + par->riva.Bitmap->UnclippedRectangle[0].TopLeft = + (rect->dx << 16) | rect->dy; + par->riva.Bitmap->UnclippedRectangle[0].WidthHeight = + (rect->width << 16) | rect->height; } /** - * riva_getcolreg - * @regno: register index - * @red: red component - * @green: green component - * @blue: blue component - * @transp: transparency - * @info: pointer to rivafb_info object containing info for current riva board + * rivafb_copyarea - hardware accelerated blit function + * @info: pointer to fb_info structure + * @region: pointer to fb_copyarea structure * * DESCRIPTION: - * Read a single color register and split it into colors/transparent. - * The return values must have a 16 bit magnitude. - * - * RETURNS: - * Return != 0 for invalid regno. + * This copies an area of pixels from one location to another * * CALLED FROM: - * rivafb_get_cmap() - * rivafb_switch() - * fbcmap.c:fb_get_cmap() - * fbgen.c:fbgen_get_cmap() - * fbgen.c:fbgen_switch() + * framebuffer hook */ -static int riva_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info) +static void rivafb_copyarea(struct fb_info *info, struct fb_copyarea *region) { - struct rivafb_info *rivainfo = (struct rivafb_info *)info; - - if (regno >= riva_get_cmap_len(&rivainfo->currcon_display->var)) - return 1; - - *red = rivainfo->palette[regno].red; - *green = rivainfo->palette[regno].green; - *blue = rivainfo->palette[regno].blue; - *transp = 0; + struct riva_par *par = (struct riva_par *) info->par; - return 0; + RIVA_FIFO_FREE(par->riva, Blt, 3); + par->riva.Blt->TopLeftSrc = (region->sy << 16) | region->sx; + par->riva.Blt->TopLeftDst = (region->dy << 16) | region->dx; + par->riva.Blt->WidthHeight = (region->height << 16) | region->width; + wait_for_idle(par); } +static u8 byte_rev[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + /** - * rivafb_setcolreg - * @regno: register index - * @red: red component - * @green: green component - * @blue: blue component - * @transp: transparency - * @info: pointer to rivafb_info object containing info for current riva board + * rivafb_imageblit: hardware accelerated color expand function + * @info: pointer to fb_info structure + * @image: pointer to fb_image structure * * DESCRIPTION: - * Set a single color register. The values supplied have a 16 bit - * magnitude. + * If the source is a monochrome bitmap, the function fills up a a region + * of framebuffer memory with pixels whose color is determined by the bit + * setting of the bitmap, 1 - foreground, 0 - background. * - * RETURNS: - * Return != 0 for invalid regno. + * If the source is not a monochrome bitmap, color expansion is not done. + * In this case, it is channeled to a software function. * * CALLED FROM: - * rivafb_set_cmap() - * fbcmap.c:fb_set_cmap() - * fbgen.c:fbgen_get_cmap() - * fbgen.c:do_install_cmap() - * fbgen.c:fbgen_set_var() - * fbgen.c:fbgen_switch() - * fbgen.c:fbgen_blank() - * fbgen.c:fbgen_blank() + * framebuffer hook */ -static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) +static void rivafb_imageblit(struct fb_info *info, struct fb_image *image) { - struct rivafb_info *rivainfo = (struct rivafb_info *)info; - RIVA_HW_INST *chip = &rivainfo->riva; - struct display *p; - - DPRINTK("ENTER\n"); - - assert(rivainfo != NULL); - assert(rivainfo->currcon_display != NULL); - - p = rivainfo->currcon_display; + struct riva_par *par = (struct riva_par *) info->par; + u8 *cdat = image->data, *dat; + int w, h, dx, dy; + volatile u32 *d; + u32 fgx = 0, bgx = 0, size, width, mod; + int i, j; + + if (image->depth != 1) { + wait_for_idle(par); + cfb_imageblit(info, image); + return; + } - if (regno >= riva_get_cmap_len(&p->var)) - return -EINVAL; + w = image->width; + h = image->height; + dx = image->dx; + dy = image->dy; - rivainfo->palette[regno].red = red; - rivainfo->palette[regno].green = green; - rivainfo->palette[regno].blue = blue; + width = (w + 7)/8; - if (p->var.grayscale) { - /* gray = 0.30*R + 0.59*G + 0.11*B */ - red = green = blue = - (red * 77 + green * 151 + blue * 28) >> 8; + size = width * h; + dat = cdat; + for (i = 0; i < size; i++) { + *dat = byte_rev[*dat]; + dat++; } - switch (p->var.bits_per_pixel) { -#ifdef FBCON_HAS_CFB8 + switch (info->var.bits_per_pixel) { case 8: - /* "transparent" stuff is completely ignored. */ - riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8); + fgx = image->fg_color | ~((1 << 8) - 1); + bgx = image->bg_color | ~((1 << 8) - 1); + break; -#endif /* FBCON_HAS_CFB8 */ -#ifdef FBCON_HAS_CFB16 case 16: - assert(regno < 16); - if (p->var.green.length == 5) { - /* 0rrrrrgg gggbbbbb */ - rivainfo->con_cmap.cfb16[regno] = - ((red & 0xf800) >> 1) | - ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); - } else { - /* rrrrrggg gggbbbbb */ - rivainfo->con_cmap.cfb16[regno] = - ((red & 0xf800) >> 0) | - ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11); + /* set alpha bit */ + if (info->var.green.length == 5) { + fgx = 1 << 15; + bgx = fgx; } - break; -#endif /* FBCON_HAS_CFB16 */ -#ifdef FBCON_HAS_CFB32 + /* Fall through... */ case 32: - assert(regno < 16); - rivainfo->con_cmap.cfb32[regno] = - ((red & 0xff00) << 8) | - ((green & 0xff00)) | ((blue & 0xff00) >> 8); - break; -#endif /* FBCON_HAS_CFB32 */ - default: - /* do nothing */ + fgx |= par->riva_palette[image->fg_color]; + bgx |= par->riva_palette[image->bg_color]; break; } - return 0; -} - + RIVA_FIFO_FREE(par->riva, Bitmap, 7); + par->riva.Bitmap->ClipE.TopLeft = (dy << 16) | (dx & 0xFFFF); + par->riva.Bitmap->ClipE.BottomRight = (((dy + h) << 16) | + ((dx + w) & 0xffff)); + par->riva.Bitmap->Color0E = bgx; + par->riva.Bitmap->Color1E = fgx; + par->riva.Bitmap->WidthHeightInE = (h << 16) | ((w + 31) & ~31); + par->riva.Bitmap->WidthHeightOutE = (h << 16) | ((w + 31) & ~31); + par->riva.Bitmap->PointE = (dy << 16) | (dx & 0xFFFF); + + d = &par->riva.Bitmap->MonochromeData01E; + + mod = width % 4; + + if (width >= 4) { + while (h--) { + size = width / 4; + while (size >= 16) { + RIVA_FIFO_FREE(par->riva, Bitmap, 16); + for (i = 0; i < 16; i++) + d[i] = *((u32 *)cdat)++; + size -= 16; + } + + if (size) { + RIVA_FIFO_FREE(par->riva, Bitmap, size); + for (i = 0; i < size; i++) + d[i] = *((u32 *) cdat)++; + } + + if (mod) { + u32 tmp; + RIVA_FIFO_FREE(par->riva, Bitmap, 1); + for (i = 0; i < mod; i++) + ((u8 *)&tmp)[i] = *cdat++; + d[i] = tmp; + } + } + } + else { + u32 k, tmp; + for (i = h; i > 0; i-=16) { + if (i >= 16) + size = 16; + else + size = i; + RIVA_FIFO_FREE(par->riva, Bitmap, size); + for (j = 0; j < size; j++) { + for (k = 0; k < width; k++) + ((u8 *)&tmp)[k] = *cdat++; + d[j] = tmp; + } + } + } +} -/* ------------------------------------------------------------------------- * +/** + * rivafb_cursor - hardware cursor function + * @info: pointer to info structure + * @cursor: pointer to fbcursor structure * - * framebuffer operations + * DESCRIPTION: + * A cursor function that supports displaying a cursor image via hardware. + * Within the kernel, copy and invert rops are supported. If exported + * to user space, only the copy rop will be supported. * - * ------------------------------------------------------------------------- */ - -static int rivafb_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *info) + * CALLED FROM + * framebuffer hook + */ +static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor) { - struct rivafb_info *rivainfo = (struct rivafb_info *)info; - struct display *p; - - DPRINTK("ENTER\n"); - - assert(fix != NULL); - assert(info != NULL); - assert(rivainfo->drvr_name && rivainfo->drvr_name[0]); - assert(rivainfo->fb_base_phys > 0); - assert(rivainfo->ram_amount > 0); - - p = (con < 0) ? rivainfo->info.disp : &fb_display[con]; - - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - sprintf(fix->id, "nVidia %s", rivainfo->drvr_name); + static u8 data[MAX_CURS*MAX_CURS/8], mask[MAX_CURS*MAX_CURS/8]; + struct riva_par *par = (struct riva_par *) info->par; + int i, j, d_idx = 0, s_idx = 0; + u16 flags = cursor->set, fg, bg; + + /* + * Can't do invert if one of the operands (dest) is missing, + * ie, only opaque cursor supported. This should be + * standard for GUI apps. + */ + if (cursor->dest == NULL && cursor->rop == ROP_XOR) + return 1; - fix->smem_start = rivainfo->fb_base_phys; - fix->smem_len = rivainfo->ram_amount; + if (par->cursor_reset) { + flags = FB_CUR_SETALL; + par->cursor_reset = 0; + } - fix->type = p->type; - fix->type_aux = p->type_aux; - fix->visual = p->visual; + par->riva.ShowHideCursor(&par->riva, 0); - fix->xpanstep = 1; - fix->ypanstep = 1; - fix->ywrapstep = 0; /* FIXME: no ywrap for now */ + if (flags & FB_CUR_SETPOS) { + u32 xx, yy, temp; + + yy = cursor->image.dy - info->var.yoffset; + xx = cursor->image.dx - info->var.xoffset; + temp = xx & 0xFFFF; + temp |= yy << 16; - fix->line_length = p->line_length; + *(par->riva.CURSORPOS) = temp; + } - fix->mmio_start = rivainfo->ctrl_base_phys; - fix->mmio_len = rivainfo->base0_region_size; - fix->smem_start = rivainfo->fb_base_phys; - fix->smem_len = rivainfo->base1_region_size; + if (flags & FB_CUR_SETSIZE) { + memset(data, 0, MAX_CURS * MAX_CURS/8); + memset(mask, 0, MAX_CURS * MAX_CURS/8); + memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2); + } - switch (rivainfo->riva.Architecture) { - case NV_ARCH_03: - fix->accel = FB_ACCEL_NV3; - break; - case NV_ARCH_04: /* riva_hw.c now doesn't distinguish between TNT & TNT2 */ - fix->accel = FB_ACCEL_NV4; - break; - case NV_ARCH_10: /* FIXME: ID for GeForce */ - fix->accel = FB_ACCEL_NV4; - break; + if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETDEST)) { + int bg_idx = cursor->image.bg_color; + int fg_idx = cursor->image.fg_color; + + switch (cursor->rop) { + case ROP_XOR: + for (i = 0; i < cursor->image.height; i++) { + for (j = 0; j < (cursor->image.width + 7)/8; + j++) { + d_idx = i * MAX_CURS/8 + j; + data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx] ^ + ((u8 *)cursor->dest)[s_idx]]; + mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]]; + s_idx++; + } + } + break; + case ROP_COPY: + default: + for (i = 0; i < cursor->image.height; i++) { + for (j = 0; j < (cursor->image.width + 7)/8; j++) { + d_idx = i * MAX_CURS/8 + j; + data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx]]; + mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]]; + s_idx++; + } + } + break; + } + + bg = ((par->cmap[bg_idx].red & 0xf8) << 7) | + ((par->cmap[bg_idx].green & 0xf8) << 2) | + ((par->cmap[bg_idx].blue & 0xf8) >> 3) | 1 << 15; + + fg = ((par->cmap[fg_idx].red & 0xf8) << 7) | + ((par->cmap[fg_idx].green & 0xf8) << 2) | + ((par->cmap[fg_idx].blue & 0xf8) >> 3) | 1 << 15; + par->riva.LockUnlock(&par->riva, 0); + rivafb_load_cursor_image(data, mask, par, cursor->image.width, + cursor->image.height, bg, fg); } - - DPRINTK("EXIT, returning 0\n"); + + if (cursor->enable) + par->riva.ShowHideCursor(&par->riva, 1); return 0; } -static int rivafb_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) +static int rivafb_sync(struct fb_info *info) { - struct rivafb_info *rivainfo = (struct rivafb_info *)info; + struct riva_par *par = (struct riva_par *) info->par; - DPRINTK("ENTER\n"); + wait_for_idle(par); + + return 0; +} + +/* ------------------------------------------------------------------------- * + * + * internal fb_ops helper functions + * + * ------------------------------------------------------------------------- */ + +/** + * riva_get_cmap_len - query current color map length + * @var: standard kernel fb changeable data + * + * DESCRIPTION: + * Get current color map length. + * + * RETURNS: + * Length of color map + * + * CALLED FROM: + * riva_getcolreg() + * rivafb_setcolreg() + * rivafb_get_cmap() + * rivafb_set_cmap() + */ +static int riva_get_cmap_len(const struct fb_var_screeninfo *var) +{ + int rc = 16; /* reasonable default */ - assert(info != NULL); assert(var != NULL); - *var = (con < 0) ? rivainfo->disp.var : fb_display[con].var; + switch (var->green.length) { + case 5: + rc = 32; /* fix for 15 bpp depths on Riva 128 based cards */ + break; + case 6: + rc = 64; /* directcolor... 16 entries SW palette */ + break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */ + default: + rc = 256; /* pseudocolor... 256 entries HW palette */ + break; + } - DPRINTK("EXIT, returning 0\n"); + return rc; +} +/* ------------------------------------------------------------------------- * + * + * framebuffer operations + * + * ------------------------------------------------------------------------- */ +static int rivafb_open(struct fb_info *info, int user) +{ + struct riva_par *par = (struct riva_par *) info->par; + int cnt = atomic_read(&par->ref_count); + + if (!cnt) { + memset(&par->state, 0, sizeof(struct fb_vgastate)); + par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; + /* save the DAC for Riva128 */ + if (par->riva.Architecture == NV_ARCH_03) + par->state.flags |= VGA_SAVE_CMAP; + fb_save_vga(&par->state); + + RivaGetConfig(&par->riva); + riva_save_state(par, &par->initial_state); + } + + atomic_inc(&par->ref_count); return 0; } -static int rivafb_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) +static int rivafb_release(struct fb_info *info, int user) { - struct rivafb_info *rivainfo = (struct rivafb_info *)info; - struct display *dsp; - struct fb_var_screeninfo v; - int nom, den; /* translating from pixels->bytes */ - int accel; - unsigned chgvar = 0; - - DPRINTK("ENTER\n"); + struct riva_par *par = (struct riva_par *) info->par; + int cnt = atomic_read(&par->ref_count); - assert(info != NULL); - assert(var != NULL); + if (!cnt) + return -EINVAL; + if (cnt == 1) { + par->riva.LockUnlock(&par->riva, 0); + par->riva.LoadStateExt(&par->riva, &par->initial_state.ext); - DPRINTK("Requested: %dx%dx%d\n", var->xres, var->yres, - var->bits_per_pixel); - DPRINTK(" virtual: %dx%d\n", var->xres_virtual, - var->yres_virtual); - DPRINTK(" offset: (%d,%d)\n", var->xoffset, var->yoffset); - DPRINTK("grayscale: %d\n", var->grayscale); - - dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con]; - assert(dsp != NULL); - - /* if var has changed, we should call changevar() later */ - if (con >= 0) { - chgvar = ((dsp->var.xres != var->xres) || - (dsp->var.yres != var->yres) || - (dsp->var.xres_virtual != var->xres_virtual) || - (dsp->var.yres_virtual != var->yres_virtual) || - (dsp->var.accel_flags != var->accel_flags) || - (dsp->var.bits_per_pixel != var->bits_per_pixel) - || memcmp(&dsp->var.red, &var->red, - sizeof(var->red)) - || memcmp(&dsp->var.green, &var->green, - sizeof(var->green)) - || memcmp(&dsp->var.blue, &var->blue, - sizeof(var->blue))); + fb_restore_vga(&par->state); + par->riva.LockUnlock(&par->riva, 1); } - memcpy(&v, var, sizeof(v)); + atomic_dec(&par->ref_count); + + return 0; +} - accel = v.accel_flags & FB_ACCELF_TEXT; +static int rivafb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct riva_par *par = (struct riva_par *) info->par; + int nom, den; /* translating from pixels->bytes */ + + if (par->riva.Architecture == NV_ARCH_03 && + var->bits_per_pixel == 16) + var->bits_per_pixel = 15; - switch (v.bits_per_pixel) { -#ifdef FBCON_HAS_CFB8 + switch (var->bits_per_pixel) { case 1 ... 8: - v.bits_per_pixel = 8; + var->bits_per_pixel = 8; nom = 1; den = 1; - v.red.offset = 0; - v.red.length = 8; - v.green.offset = 0; - v.green.length = 8; - v.blue.offset = 0; - v.blue.length = 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; break; -#endif -#ifdef FBCON_HAS_CFB16 case 9 ... 15: - v.green.length = 5; + var->green.length = 5; /* fall through */ case 16: - v.bits_per_pixel = 16; + var->bits_per_pixel = 16; nom = 2; den = 1; - if (v.green.length == 5) { + if (var->green.length == 5) { /* 0rrrrrgg gggbbbbb */ - v.red.offset = 10; - v.green.offset = 5; - v.blue.offset = 0; - v.red.length = 5; - v.green.length = 5; - v.blue.length = 5; + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; } else { /* rrrrrggg gggbbbbb */ - v.red.offset = 11; - v.green.offset = 5; - v.blue.offset = 0; - v.red.length = 5; - v.green.length = 6; - v.blue.length = 5; + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; } break; -#endif -#ifdef FBCON_HAS_CFB32 case 17 ... 32: - v.bits_per_pixel = 32; + var->bits_per_pixel = 32; nom = 4; den = 1; - v.red.offset = 16; - v.green.offset = 8; - v.blue.offset = 0; - v.red.length = 8; - v.green.length = 8; - v.blue.length = 8; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; break; -#endif default: printk(KERN_ERR PFX "mode %dx%dx%d rejected...color depth not supported.\n", @@ -1448,122 +1267,53 @@ static int rivafb_set_var(struct fb_var_screeninfo *var, int con, return -EINVAL; } - if (rivafb_do_maximize(rivainfo, var, &v, nom, den) < 0) + if (rivafb_do_maximize(info, var, nom, den) < 0) return -EINVAL; - if (v.xoffset < 0) - v.xoffset = 0; - if (v.yoffset < 0) - v.yoffset = 0; + if (var->xoffset < 0) + var->xoffset = 0; + if (var->yoffset < 0) + var->yoffset = 0; /* truncate xoffset and yoffset to maximum if too high */ - if (v.xoffset > v.xres_virtual - v.xres) - v.xoffset = v.xres_virtual - v.xres - 1; - - if (v.yoffset > v.yres_virtual - v.yres) - v.yoffset = v.yres_virtual - v.yres - 1; - - v.red.msb_right = - v.green.msb_right = - v.blue.msb_right = - v.transp.offset = v.transp.length = v.transp.msb_right = 0; - - switch (v.activate & FB_ACTIVATE_MASK) { - case FB_ACTIVATE_TEST: - DPRINTK("EXIT - FB_ACTIVATE_TEST\n"); - return 0; - case FB_ACTIVATE_NXTOPEN: /* ?? */ - case FB_ACTIVATE_NOW: - break; /* continue */ - default: - DPRINTK("EXIT - unknown activation type\n"); - return -EINVAL; /* unknown */ - } - - memcpy(&dsp->var, &v, sizeof(v)); - if (chgvar) { - riva_set_dispsw(rivainfo, dsp); - - if (accel) { - if (nomove) - dsp->scrollmode = SCROLL_YNOMOVE; - else - dsp->scrollmode = 0; - } else - dsp->scrollmode = SCROLL_YREDRAW; + if (var->xoffset > var->xres_virtual - var->xres) + var->xoffset = var->xres_virtual - var->xres - 1; - if (info && info->changevar) - info->changevar(con); - } + if (var->yoffset > var->yres_virtual - var->yres) + var->yoffset = var->yres_virtual - var->yres - 1; - rivafb_create_cursor(rivainfo, fontwidth(dsp), fontheight(dsp)); - riva_load_video_mode(rivainfo, &v); - if (accel) riva_setup_accel(rivainfo); - - DPRINTK("EXIT, returning 0\n"); + var->red.msb_right = + var->green.msb_right = + var->blue.msb_right = + var->transp.offset = var->transp.length = var->transp.msb_right = 0; return 0; } -static int rivafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) +static int rivafb_set_par(struct fb_info *info) { - struct rivafb_info *rivainfo = (struct rivafb_info *)info; - struct display *dsp; - - DPRINTK("ENTER\n"); - - assert(rivainfo != NULL); - assert(cmap != NULL); - - dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con]; - - if (con == info->currcon) { /* current console? */ - int rc = fb_get_cmap(cmap, kspc, riva_getcolreg, info); - DPRINTK("EXIT - returning %d\n", rc); - return rc; - } else if (dsp->cmap.len) /* non default colormap? */ - fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2); - else - fb_copy_cmap(fb_default_cmap - (riva_get_cmap_len(&dsp->var)), cmap, - kspc ? 0 : 2); - - DPRINTK("EXIT, returning 0\n"); - - return 0; -} - -static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) -{ - struct rivafb_info *rivainfo = (struct rivafb_info *)info; - struct display *dsp; - unsigned int cmap_len; - - DPRINTK("ENTER\n"); - - assert(rivainfo != NULL); - assert(cmap != NULL); - - dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con]; - - cmap_len = riva_get_cmap_len(&dsp->var); - if (dsp->cmap.len != cmap_len) { - int err = fb_alloc_cmap(&dsp->cmap, cmap_len, 0); - if (err) { - DPRINTK("EXIT - returning %d\n", err); - return err; - } + 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); + info->fbops->fb_fillrect = rivafb_fillrect; + info->fbops->fb_copyarea = rivafb_copyarea; + info->fbops->fb_imageblit = rivafb_imageblit; + info->fbops->fb_cursor = rivafb_cursor; + info->fbops->fb_sync = rivafb_sync; + } + else { + info->fbops->fb_fillrect = cfb_fillrect; + info->fbops->fb_copyarea = cfb_copyarea; + info->fbops->fb_imageblit = cfb_imageblit; + info->fbops->fb_cursor = soft_cursor; + info->fbops->fb_sync = NULL; } - if (con == info->currcon) { /* current console? */ - int rc = fb_set_cmap(cmap, kspc, info); - DPRINTK("EXIT - returning %d\n", rc); - return rc; - } else - fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1); - - DPRINTK("EXIT, returning 0\n"); + info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3)); + info->fix.visual = (info->var.bits_per_pixel == 8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; return 0; } @@ -1580,135 +1330,58 @@ static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, * * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int rivafb_pan_display(struct fb_var_screeninfo *var, int con, +static int rivafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { + struct riva_par *par = (struct riva_par *) info->par; unsigned int base; - struct display *dsp; - struct rivafb_info *rivainfo = (struct rivafb_info *)info; - - DPRINTK("ENTER\n"); - - assert(rivainfo != NULL); - + if (var->xoffset > (var->xres_virtual - var->xres)) return -EINVAL; if (var->yoffset > (var->yres_virtual - var->yres)) return -EINVAL; - dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con]; - if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset < 0 - || var->yoffset >= dsp->var.yres_virtual + || var->yoffset >= info->var.yres_virtual || var->xoffset) return -EINVAL; } else { - if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual || - var->yoffset + dsp->var.yres > dsp->var.yres_virtual) + if (var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; } - base = var->yoffset * dsp->line_length + var->xoffset; + base = var->yoffset * info->fix.line_length + var->xoffset; - if (con == info->currcon) { - rivainfo->riva.SetStartAddress(&rivainfo->riva, base); - } + par->riva.SetStartAddress(&par->riva, base); - dsp->var.xoffset = var->xoffset; - dsp->var.yoffset = var->yoffset; + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) - dsp->var.vmode |= FB_VMODE_YWRAP; + info->var.vmode |= FB_VMODE_YWRAP; else - dsp->var.vmode &= ~FB_VMODE_YWRAP; - - DPRINTK("EXIT, returning 0\n"); - - return 0; -} - -static int rivafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, int con, struct fb_info *info) -{ - struct rivafb_info *rivainfo = (struct rivafb_info *)info; - - DPRINTK("ENTER\n"); - - assert(rivainfo != NULL); - - /* no rivafb-specific ioctls */ - - DPRINTK("EXIT, returning -EINVAL\n"); - - return -EINVAL; -} - -static int rivafb_rasterimg(struct fb_info *info, int start) -{ - struct rivafb_info *rinfo = (struct rivafb_info *)info; - - wait_for_idle(rinfo); - - return 0; -} - -static int rivafb_switch(int con, struct fb_info *info) -{ - struct rivafb_info *rivainfo = (struct rivafb_info *)info; - struct fb_cmap *cmap; - struct display *dsp; - - DPRINTK("ENTER\n"); - - assert(rivainfo != NULL); + info->var.vmode &= ~FB_VMODE_YWRAP; - dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con]; - - if (info->currcon >= 0) { - /* Do we have to save the colormap? */ - cmap = &(rivainfo->currcon_display->cmap); - DPRINTK("switch1: con = %d, cmap.len = %d\n", - info->currcon, cmap->len); - - if (cmap->len) { - DPRINTK("switch1a: %p %p %p %p\n", cmap->red, - cmap->green, cmap->blue, cmap->transp); - fb_get_cmap(cmap, 1, riva_getcolreg, info); - } - } - info->currcon = con; - rivainfo->currcon_display = dsp; - - rivafb_set_var(&dsp->var, con, info); - riva_set_dispsw(rivainfo, dsp); + /* + * HACK: The hardware cursor occasionally disappears during fast scrolling. + * We just reset the cursor each time we change the start address. + * This also has a beneficial side effect of restoring the cursor + * image when switching from X. + */ + par->cursor_reset = 1; DPRINTK("EXIT, returning 0\n"); return 0; } -static int rivafb_updatevar(int con, struct fb_info *info) -{ - int rc; - - DPRINTK("ENTER\n"); - - rc = (con < 0) ? -EINVAL : rivafb_pan_display(&fb_display[con].var, - con, info); - DPRINTK("EXIT, returning %d\n", rc); - return rc; -} - static int rivafb_blank(int blank, struct fb_info *info) { + struct riva_par *par = (struct riva_par *) info->par; unsigned char tmp, vesa; - struct rivafb_info *rinfo = (struct rivafb_info *)info; - - DPRINTK("ENTER\n"); - - assert(rinfo != NULL); - tmp = SEQin(rinfo, 0x01) & ~0x20; /* screen on/off */ - vesa = CRTCin(rinfo, 0x1a) & ~0xc0; /* sync on/off */ + tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */ + vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */ if (blank) { tmp |= 0x20; @@ -1727,14 +1400,127 @@ static int rivafb_blank(int blank, struct fb_info *info) } } - SEQout(rinfo, 0x01, tmp); - CRTCout(rinfo, 0x1a, vesa); + SEQout(par, 0x01, tmp); + CRTCout(par, 0x1a, vesa); DPRINTK("EXIT\n"); return 0; } +/** + * rivafb_setcolreg + * @regno: register index + * @red: red component + * @green: green component + * @blue: blue component + * @transp: transparency + * @info: pointer to rivafb_info object containing info for current riva board + * + * DESCRIPTION: + * Set a single color register. The values supplied have a 16 bit + * magnitude. + * + * RETURNS: + * Return != 0 for invalid regno. + * + * CALLED FROM: + * rivafb_set_cmap() + * fbcmap.c:fb_set_cmap() + * fbgen.c:fbgen_get_cmap() + * fbgen.c:do_install_cmap() + * fbgen.c:fbgen_set_var() + * fbgen.c:fbgen_switch() + * fbgen.c:fbgen_blank() + * fbgen.c:fbgen_blank() + */ +static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + struct riva_par *par = (struct riva_par *) info->par; + RIVA_HW_INST *chip = &par->riva; + int i; + + if (regno >= riva_get_cmap_len(&info->var)) + return -EINVAL; + + if (info->var.grayscale) { + /* gray = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = + (red * 77 + green * 151 + blue * 28) >> 8; + } + + if (!regno) { + for (i = 0; i < 256; i++) { + par->cmap[i].red = 0; + par->cmap[i].green = 0; + par->cmap[i].blue = 0; + } + } + par->cmap[regno].red = (u8) red; + par->cmap[regno].green = (u8) green; + par->cmap[regno].blue = (u8) blue; + + if (info->var.green.length == 5) { + /* RGB555: all components have 32 entries, 8 indices apart */ + for (i = 0; i < 8; i++) + riva_wclut(chip, (regno*8)+i, (u8) red, (u8) green, (u8) blue); + } + else if (info->var.green.length == 6) { + /* + * RGB 565: red and blue have 32 entries, 8 indices apart, while + * green has 64 entries, 4 indices apart + */ + if (regno < 32) { + for (i = 0; i < 8; i++) { + riva_wclut(chip, (regno*8)+i, (u8) red, + par->cmap[regno*2].green, + (u8) blue); + } + } + for (i = 0; i < 4; i++) { + riva_wclut(chip, (regno*4)+i, par->cmap[regno/2].red, + (u8) green, par->cmap[regno/2].blue); + + } + } + else { + riva_wclut(chip, regno, (u8) red, (u8) green, (u8) blue); + } + if (regno < 16) { + switch (info->var.bits_per_pixel) { + case 16: + if (info->var.green.length == 5) { + /* 0rrrrrgg gggbbbbb */ + ((u32 *)(info->pseudo_palette))[regno] = + (regno << 10) | (regno << 5) | regno; + par->riva_palette[regno] = + ((red & 0xf800) >> 1) | + ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); + + } else { + /* rrrrrggg gggbbbbb */ + ((u32 *)(info->pseudo_palette))[regno] = + (regno << 11) | (regno << 6) | regno; + par->riva_palette[regno] = ((red & 0xf800) >> 0) | + ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11); + } + break; + case 32: + ((u32 *)(info->pseudo_palette))[regno] = + (regno << 16) | (regno << 8) | regno; + par->riva_palette[regno] = + ((red & 0xff00) << 8) | + ((green & 0xff00)) | ((blue & 0xff00) >> 8); + break; + default: + /* do nothing */ + break; + } + } + return 0; +} /* ------------------------------------------------------------------------- * * @@ -1745,294 +1531,341 @@ static int rivafb_blank(int blank, struct fb_info *info) /* kernel interface */ static struct fb_ops riva_fb_ops = { .owner = THIS_MODULE, - .fb_get_fix = rivafb_get_fix, - .fb_get_var = rivafb_get_var, - .fb_set_var = rivafb_set_var, - .fb_get_cmap = rivafb_get_cmap, - .fb_set_cmap = rivafb_set_cmap, + .fb_open = rivafb_open, + .fb_release = rivafb_release, + .fb_check_var = rivafb_check_var, + .fb_set_par = rivafb_set_par, .fb_setcolreg = rivafb_setcolreg, - .fb_pan_display =rivafb_pan_display, + .fb_pan_display=rivafb_pan_display, .fb_blank = rivafb_blank, - .fb_ioctl = rivafb_ioctl, - .fb_rasterimg = rivafb_rasterimg, + .fb_fillrect = rivafb_fillrect, + .fb_copyarea = rivafb_copyarea, + .fb_imageblit = rivafb_imageblit, + .fb_cursor = rivafb_cursor, + .fb_sync = rivafb_sync, }; -static int __devinit riva_init_disp_var(struct rivafb_info *rinfo) -{ -#ifndef MODULE - if (mode_option) - fb_find_mode(&rinfo->disp.var, &rinfo->info, mode_option, - NULL, 0, NULL, 8); -#endif - return 0; -} - -static int __devinit riva_init_disp(struct rivafb_info *rinfo) -{ - struct fb_info *info; - struct display *disp; - - DPRINTK("ENTER\n"); - - assert(rinfo != NULL); - - info = &rinfo->info; - disp = &rinfo->disp; - - disp->var = rivafb_default_var; - - if (noaccel) - disp->var.accel_flags &= ~FB_ACCELF_TEXT; - else - disp->var.accel_flags |= FB_ACCELF_TEXT; - - info->disp = disp; - - /* FIXME: assure that disp->cmap is completely filled out */ - - rinfo->currcon_display = disp; - - if ((riva_init_disp_var(rinfo)) < 0) { - DPRINTK("EXIT, returning -1\n"); - return -1; - } - - riva_set_dispsw(rinfo, disp); - - DPRINTK("EXIT, returning 0\n"); - return 0; - -} - -static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo) +static int __devinit riva_set_fbinfo(struct fb_info *info) { - struct fb_info *info; - - assert(rinfo != NULL); - - info = &rinfo->info; + unsigned int cmap_len; - strcpy(info->modename, rinfo->drvr_name); info->node = NODEV; info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &riva_fb_ops; - info->screen_base = rinfo->fb_base; - /* FIXME: set monspecs to what??? */ + info->var = rivafb_default_var; + info->fix = rivafb_fix; + /* FIXME: set monspecs to what??? */ info->display_fg = NULL; - info->currcon = -1; - strncpy(info->fontname, fontname, sizeof(info->fontname)); - info->fontname[sizeof(info->fontname) - 1] = 0; - - info->changevar = NULL; - info->switch_con = rivafb_switch; - info->updatevar = rivafb_updatevar; - - if (riva_init_disp(rinfo) < 0) /* must be done last */ - return -1; + 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 return 0; } - - /* ------------------------------------------------------------------------- * * * PCI bus * * ------------------------------------------------------------------------- */ +static void __devinit rivafb_get_mem_len(struct riva_par *par, + struct fb_fix_screeninfo *fix) +{ + RIVA_HW_INST *chip = &par->riva; + + switch (chip->Architecture) { + case NV_ARCH_03: + if (chip->PFB[0x00000000/4] & 0x00000020) { + if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20) + && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) { + /* + * SDRAM 128 ZX. + */ + switch (chip->PFB[0x00000000/4] & 0x03) { + case 2: + fix->smem_len = 1024 * 1024 * 4; + break; + case 1: + fix->smem_len = 1024 * 1024 * 2; + break; + default: + fix->smem_len = 1024 * 1024 * 8; + break; + } + } + else { + fix->smem_len = 1024 * 1024 * 8; + } + } + else { + /* + * SGRAM 128. + */ + switch (chip->PFB[0x00000000/4] & 0x00000003) { + case 0: + fix->smem_len = 1024 * 1024 * 8; + break; + case 2: + fix->smem_len = 1024 * 1024 * 4; + break; + default: + fix->smem_len = 1024 * 1024 * 2; + break; + } + } + break; + case NV_ARCH_04: + if (chip->PFB[0x00000000/4] & 0x00000100) { + fix->smem_len = (((chip->PFB[0x00000000/4] >> 12) + & 0x0F) * 1024 * 2 + 1024 * 2) * 1024; + } + else { + switch (chip->PFB[0x00000000/4] & 0x00000003) { + case 0: + fix->smem_len = 1024 * 1024 * 32; + break; + case 1: + fix->smem_len = 1024 * 1024 * 4; + break; + case 2: + fix->smem_len = 1024 * 1024 * 8; + break; + case 3: + default: + fix->smem_len = 1024 * 1024 * 16; + break; + } + } + break; + case NV_ARCH_10: + case NV_ARCH_20: + switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF) { + case 0x02: + fix->smem_len = 1024 * 1024 * 2; + break; + case 0x04: + fix->smem_len = 1024 * 1024 * 4; + break; + case 0x08: + fix->smem_len = 1024 * 1024 * 8; + break; + case 0x10: + fix->smem_len = 1024 * 1024 * 16; + break; + case 0x20: + fix->smem_len = 1024 * 1024 * 32; + break; + case 0x40: + fix->smem_len = 1024 * 1024 * 64; + break; + case 0x80: + fix->smem_len = 1024 * 1024 * 128; + break; + default: + fix->smem_len = 1024 * 1024 * 16; + break; + } + } +} + static int __devinit rivafb_init_one(struct pci_dev *pd, const struct pci_device_id *ent) { - struct rivafb_info *rinfo; struct riva_chip_info *rci = &riva_chip_info[ent->driver_data]; + struct riva_par *default_par; + struct fb_info *info; assert(pd != NULL); assert(rci != NULL); - rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL); - if (!rinfo) + info = kmalloc(sizeof(struct fb_info), GFP_KERNEL); + if (!info) goto err_out; - memset(rinfo, 0, sizeof(struct rivafb_info)); + default_par = kmalloc(sizeof(struct riva_par), GFP_KERNEL); + if (!default_par) + goto err_out_kfree; - rinfo->drvr_name = rci->name; - rinfo->riva.Architecture = rci->arch_rev; + memset(info, 0, sizeof(struct fb_info)); + memset(default_par, 0, sizeof(struct riva_par)); - rinfo->pd = pd; - rinfo->base0_region_size = pci_resource_len(pd, 0); - rinfo->base1_region_size = pci_resource_len(pd, 1); + strcat(rivafb_fix.id, rci->name); + default_par->riva.Architecture = rci->arch_rev; - assert(rinfo->base0_region_size >= 0x00800000); /* from GGI */ - assert(rinfo->base1_region_size >= 0x01000000); /* from GGI */ + rivafb_fix.mmio_len = pci_resource_len(pd, 0); + rivafb_fix.smem_len = pci_resource_len(pd, 1); - rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0); - rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1); + rivafb_fix.mmio_start = pci_resource_start(pd, 0); + rivafb_fix.smem_start = pci_resource_start(pd, 1); - if (!request_mem_region(rinfo->ctrl_base_phys, - rinfo->base0_region_size, "rivafb")) { + if (!request_mem_region(rivafb_fix.mmio_start, + rivafb_fix.mmio_len, "rivafb")) { printk(KERN_ERR PFX "cannot reserve MMIO region\n"); goto err_out_kfree; } - if (!request_mem_region(rinfo->fb_base_phys, - rinfo->base1_region_size, "rivafb")) { - printk(KERN_ERR PFX "cannot reserve FB region\n"); - goto err_out_free_base0; - } - - rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys, - rinfo->base0_region_size); - if (!rinfo->ctrl_base) { + default_par->ctrl_base = ioremap(rivafb_fix.mmio_start, + rivafb_fix.mmio_len); + if (!default_par->ctrl_base) { printk(KERN_ERR PFX "cannot ioremap MMIO base\n"); goto err_out_free_base1; } - rinfo->fb_base = ioremap(rinfo->fb_base_phys, - rinfo->base1_region_size); - if (!rinfo->fb_base) { + 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 - if (!nomtrr) { - rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys, - rinfo->base1_region_size, MTRR_TYPE_WRCOMB, 1); - if (rinfo->mtrr.vram < 0) { - printk(KERN_ERR PFX "unable to setup MTRR\n"); - } else { - rinfo->mtrr.vram_valid = 1; - /* let there be speed */ - printk(KERN_INFO PFX "RIVA MTRR set to ON\n"); - } - } -#endif /* CONFIG_MTRR */ - - rinfo->riva.EnableIRQ = 0; - rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000); - rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000); - rinfo->riva.PFIFO = (unsigned *)(rinfo->ctrl_base + 0x00002000); - rinfo->riva.PGRAPH = (unsigned *)(rinfo->ctrl_base + 0x00400000); - rinfo->riva.PEXTDEV = (unsigned *)(rinfo->ctrl_base + 0x00101000); - rinfo->riva.PTIMER = (unsigned *)(rinfo->ctrl_base + 0x00009000); - rinfo->riva.PMC = (unsigned *)(rinfo->ctrl_base + 0x00000000); - rinfo->riva.FIFO = (unsigned *)(rinfo->ctrl_base + 0x00800000); - - rinfo->riva.PCIO = (U008 *)(rinfo->ctrl_base + 0x00601000); - rinfo->riva.PDIO = (U008 *)(rinfo->ctrl_base + 0x00681000); - rinfo->riva.PVIO = (U008 *)(rinfo->ctrl_base + 0x000C0000); - - rinfo->riva.IO = (MISCin(rinfo) & 0x01) ? 0x3D0 : 0x3B0; - - switch (rinfo->riva.Architecture) { + default_par->riva.EnableIRQ = 0; + default_par->riva.PRAMDAC = (unsigned *)(default_par->ctrl_base + + 0x00680000); + default_par->riva.PFB = (unsigned *)(default_par->ctrl_base + + 0x00100000); + default_par->riva.PFIFO = (unsigned *)(default_par->ctrl_base + + 0x00002000); + default_par->riva.PGRAPH = (unsigned *)(default_par->ctrl_base + + 0x00400000); + default_par->riva.PEXTDEV = (unsigned *)(default_par->ctrl_base + + 0x00101000); + default_par->riva.PTIMER = (unsigned *)(default_par->ctrl_base + + 0x00009000); + default_par->riva.PMC = (unsigned *)(default_par->ctrl_base + + 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; + + switch (default_par->riva.Architecture) { case NV_ARCH_03: - rinfo->riva.PRAMIN = (unsigned *)(rinfo->fb_base + 0x00C00000); + default_par->riva.PRAMIN = (unsigned *)(info->screen_base + + 0x00C00000); + default_par->dclk_max = 256000000; + rivafb_fix.accel = FB_ACCEL_NV3; break; case NV_ARCH_04: case NV_ARCH_10: - rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000); - rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000); + case NV_ARCH_20: + default_par->riva.PCRTC = (unsigned *)(default_par->ctrl_base + + 0x00600000); + default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + + 0x00710000); + default_par->dclk_max = 250000000; + rivafb_fix.accel = FB_ACCEL_NV4; break; } - RivaGetConfig(&rinfo->riva); + rivafb_get_mem_len(default_par, &rivafb_fix); - /* back to normal */ + info->par = default_par; - assert(rinfo->pd != NULL); - - /* unlock io */ - CRTCout(rinfo, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */ - rinfo->riva.LockUnlock(&rinfo->riva, 0); - - riva_save_state(rinfo, &rinfo->initial_state); - - rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024; - rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000; + 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; + } - if (!nohwcursor) rinfo->cursor = rivafb_init_cursor(rinfo); +#ifdef CONFIG_MTRR + if (!nomtrr) { + default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start, + rivafb_fix.smem_len, + MTRR_TYPE_WRCOMB, 1); + if (default_par->mtrr.vram < 0) { + printk(KERN_ERR PFX "unable to setup MTRR\n"); + } else { + default_par->mtrr.vram_valid = 1; + /* let there be speed */ + printk(KERN_INFO PFX "RIVA MTRR set to ON\n"); + } + } +#endif /* CONFIG_MTRR */ - if (riva_set_fbinfo(rinfo) < 0) { + if (riva_set_fbinfo(info) < 0) { printk(KERN_ERR PFX "error setting initial video mode\n"); goto err_out_cursor; } - if (register_framebuffer((struct fb_info *)rinfo) < 0) { + if (register_framebuffer(info) < 0) { printk(KERN_ERR PFX "error registering riva framebuffer\n"); goto err_out_load_state; } - riva_boards = riva_board_list_add(riva_boards, rinfo); - - pci_set_drvdata(pd, rinfo); + pci_set_drvdata(pd,info); printk(KERN_INFO PFX - "PCI nVidia NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n", - rinfo->riva.Architecture, + "PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n", + default_par->riva.Architecture, RIVAFB_VERSION, - rinfo->drvr_name, - rinfo->ram_amount / (1024 * 1024), - rinfo->fb_base_phys); + info->fix.id, + info->fix.smem_len / (1024 * 1024), + info->fix.smem_start); return 0; err_out_load_state: - riva_load_state(rinfo, &rinfo->initial_state); err_out_cursor: - rivafb_exit_cursor(rinfo); /* err_out_iounmap_fb: */ - iounmap(rinfo->fb_base); + iounmap(info->screen_base); err_out_iounmap_ctrl: - iounmap(rinfo->ctrl_base); + iounmap(default_par->ctrl_base); err_out_free_base1: - release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size); + release_mem_region(info->fix.smem_start, info->fix.smem_len); err_out_free_base0: - release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size); + release_mem_region(info->fix.mmio_start, info->fix.mmio_len); err_out_kfree: - kfree(rinfo); + kfree(info); err_out: return -ENODEV; } static void __devexit rivafb_remove_one(struct pci_dev *pd) { - struct rivafb_info *board = pci_get_drvdata(pd); + struct fb_info *info = pci_get_drvdata(pd); + struct riva_par *par = (struct riva_par *) info->par; - if (!board) + if (!info) return; - riva_boards = riva_board_list_del(riva_boards, board); - - riva_load_state(board, &board->initial_state); - - unregister_framebuffer((struct fb_info *)board); - - rivafb_exit_cursor(board); + unregister_framebuffer(info); #ifdef CONFIG_MTRR - if (board->mtrr.vram_valid) - mtrr_del(board->mtrr.vram, board->fb_base_phys, - board->base1_region_size); + if (par->mtrr.vram_valid) + mtrr_del(par->mtrr.vram, info->fix.smem_start, + info->fix.smem_len); #endif /* CONFIG_MTRR */ - iounmap(board->ctrl_base); - iounmap(board->fb_base); - - release_mem_region(board->ctrl_base_phys, - board->base0_region_size); - release_mem_region(board->fb_base_phys, - board->base1_region_size); - - kfree(board); + iounmap(par->ctrl_base); + iounmap(info->screen_base); + release_mem_region(info->fix.mmio_start, + info->fix.mmio_len); + release_mem_region(info->fix.smem_start, + info->fix.smem_len); + kfree(info); pci_set_drvdata(pd, NULL); } - - /* ------------------------------------------------------------------------- * * * initialization @@ -2050,30 +1883,11 @@ int __init rivafb_setup(char *options) while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; - if (!strncmp(this_opt, "font:", 5)) { - char *p; - int i; - - p = this_opt + 5; - for (i = 0; i < sizeof(fontname) - 1; i++) - if (!*p || *p == ' ' || *p == ',') - break; - memcpy(fontname, this_opt + 5, i); - fontname[i] = 0; - - } else if (!strncmp(this_opt, "noblink", 7)) { - noblink = 1; - } else if (!strncmp(this_opt, "noaccel", 7)) { - noaccel = 1; - } else if (!strncmp(this_opt, "nomove", 6)) { - nomove = 1; #ifdef CONFIG_MTRR - } else if (!strncmp(this_opt, "nomtrr", 6)) { + if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1; -#endif - } else if (!strncmp(this_opt, "nohwcursor", 10)) { - nohwcursor = 1; } else +#endif mode_option = this_opt; } return 0; @@ -2081,10 +1895,10 @@ int __init rivafb_setup(char *options) #endif /* !MODULE */ static struct pci_driver rivafb_driver = { - .name = "rivafb", - .id_table = rivafb_pci_tbl, - .probe = rivafb_init_one, - .remove = __devexit_p(rivafb_remove_one), + name: "rivafb", + id_table: rivafb_pci_tbl, + probe: rivafb_init_one, + remove: __devexit_p(rivafb_remove_one), }; @@ -2098,9 +1912,7 @@ static struct pci_driver rivafb_driver = { int __init rivafb_init(void) { int err; -#ifdef MODULE - if (font) strncpy(fontname, font, sizeof(fontname)-1); -#endif + err = pci_module_init(&rivafb_driver); if (err) return err; @@ -2121,12 +1933,6 @@ MODULE_PARM(font, "s"); MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (default=none)"); MODULE_PARM(noaccel, "i"); MODULE_PARM_DESC(noaccel, "Disables hardware acceleration (0 or 1=disabled) (default=0)"); -MODULE_PARM(nomove, "i"); -MODULE_PARM_DESC(nomove, "Enables YSCROLL_NOMOVE (0 or 1=enabled) (default=0)"); -MODULE_PARM(nohwcursor, "i"); -MODULE_PARM_DESC(nohwcursor, "Disables hardware cursor (0 or 1=disabled) (default=0)"); -MODULE_PARM(noblink, "i"); -MODULE_PARM_DESC(noblink, "Disables hardware cursor blinking (0 or 1=disabled) (default=0)"); #ifdef CONFIG_MTRR MODULE_PARM(nomtrr, "i"); MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)"); diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h index 708667d39ab6..22d056b0fd2e 100644 --- a/drivers/video/riva/riva_hw.h +++ b/drivers/video/riva/riva_hw.h @@ -74,6 +74,7 @@ typedef unsigned int U032; #define NV_ARCH_03 0x03 #define NV_ARCH_04 0x04 #define NV_ARCH_10 0x10 +#define NV_ARCH_20 0x20 /***************************************************************************\ * * * FIFO registers. * diff --git a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h index d0e64d2b0211..f36a1ea21521 100644 --- a/drivers/video/riva/rivafb.h +++ b/drivers/video/riva/rivafb.h @@ -3,11 +3,6 @@ #include <linux/config.h> #include <linux/fb.h> -#include <video/fbcon.h> -#include <video/fbcon-cfb4.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-cfb32.h> #include "riva_hw.h" /* GGI compatibility macros */ @@ -31,52 +26,20 @@ typedef struct { unsigned char red, green, blue, transp; } riva_cfb8_cmap_t; -struct rivafb_info; -struct rivafb_info { - struct fb_info info; /* kernel framebuffer info */ - +struct riva_par { RIVA_HW_INST riva; /* interface to riva_hw.c */ - const char *drvr_name; /* Riva hardware board type */ - - unsigned long ctrl_base_phys; /* physical control register base addr */ - unsigned long fb_base_phys; /* physical framebuffer base addr */ - caddr_t ctrl_base; /* virtual control register base addr */ - caddr_t fb_base; /* virtual framebuffer base addr */ - - unsigned ram_amount; /* amount of RAM on card, in bytes */ unsigned dclk_max; /* max DCLK */ struct riva_regs initial_state; /* initial startup video mode */ struct riva_regs current_state; - - struct display disp; - int currcon; - struct display *currcon_display; - - struct rivafb_info *next; - - struct pci_dev *pd; /* pointer to board's pci info */ - unsigned base0_region_size; /* size of control register region */ - unsigned base1_region_size; /* size of framebuffer region */ - - struct riva_cursor *cursor; - - struct display_switch dispsw; - - riva_cfb8_cmap_t palette[256]; /* VGA DAC palette cache */ - -#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) - union { -#ifdef FBCON_HAS_CFB16 - u_int16_t cfb16[16]; -#endif -#ifdef FBCON_HAS_CFB32 - u_int32_t cfb32[16]; -#endif - } con_cmap; -#endif /* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */ + struct fb_vgastate state; + atomic_t ref_count; + riva_cfb8_cmap_t cmap[256]; /* VGA DAC palette cache */ + u32 riva_palette[16]; + u32 cursor_data[32 * 32/4]; + int cursor_reset; #ifdef CONFIG_MTRR struct { int vram; int vram_valid; } mtrr; #endif diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index d8ac3095f2d0..e296037e6225 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -1432,7 +1432,7 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi) LCCR0 &= ~LCCR0_LEN; /* Disable LCD Controller */ schedule_timeout(20 * HZ / 1000); - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&fbi->ctrlr_wait, &wait); } diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c index 35c12a2da743..dd152737110f 100644 --- a/drivers/video/sbusfb.c +++ b/drivers/video/sbusfb.c @@ -1066,7 +1066,7 @@ sizechange: kfree(fb); return; } - printk(KERN_INFO "fb%d: %s\n", GET_FB_IDX(fb->info.node), p); + printk(KERN_INFO "fb%d: %s\n", minor(fb->info.node), p); } static inline int known_card(char *name) diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index 59400e61e448..fe9cc1d9c512 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -23,17 +23,16 @@ #include <asm/uaccess.h> #include <linux/fb.h> #include <linux/init.h> +#include <linux/ioport.h> #include <asm/io.h> #include <asm/mtrr.h> -#include <video/fbcon.h> - #define INCLUDE_TIMING_TABLE_DATA -#define DBE_REG_BASE regs -#include <video/sgivw.h> +#define DBE_REG_BASE default_par.regs +#include <asm/sgi-vwdbe.h> struct sgivw_par { - asregs *regs; + struct asregs *regs; u32 cmap_fifo; u_long timing_num; }; @@ -46,11 +45,12 @@ struct sgivw_par { */ /* set by arch/i386/kernel/setup.c */ -u_long sgivwfb_mem_phys; -u_long sgivwfb_mem_size; +extern unsigned long sgivwfb_mem_phys; +extern unsigned long sgivwfb_mem_size; -static struct fb_info fb_info; static struct sgivw_par default_par; +static u32 pseudo_palette[17]; +static struct fb_info fb_info; static int ypan = 0; static int ywrap = 0; @@ -60,7 +60,7 @@ static struct fb_fix_screeninfo sgivwfb_fix __initdata = { .visual = FB_VISUAL_PSEUDOCOLOR, .mmio_start = DBE_REG_PHYS, .mmio_len = DBE_REG_SIZE, - .accel_flags = FB_ACCEL_NONE + .accel = FB_ACCEL_NONE }; static struct fb_var_screeninfo sgivwfb_var __initdata = { @@ -85,9 +85,6 @@ static struct fb_var_screeninfo sgivwfb_var __initdata = { .vmode = FB_VMODE_NONINTERLACED }; -/* console related variables */ -static struct display disp; - /* * Interface used by the world */ @@ -104,15 +101,13 @@ static int sgivwfb_mmap(struct fb_info *info, struct file *file, static struct fb_ops sgivwfb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_check_var = sgivwfb_check_var, .fb_set_par = sgivwfb_set_par, .fb_setcolreg = sgivwfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, .fb_mmap = sgivwfb_mmap, }; @@ -159,8 +154,8 @@ static unsigned long bytes_per_pixel(int bpp) static void dbe_TurnOffDma(void) { - int i; unsigned int readVal; + int i; // Check to see if things are already turned off: // 1) Check to see if dbe is not using the internal dotclock. @@ -226,7 +221,7 @@ static void dbe_TurnOffDma(void) static int sgivwfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - int err, activate = var->activate; + struct sgivw_par *par = (struct sgivw_par *)info->par; struct dbe_timing_info *timing; u_long line_length; u_long min_mode; @@ -240,8 +235,8 @@ static int sgivwfb_check_var(struct fb_var_screeninfo *var, if (var->vmode & FB_VMODE_CONUPDATE) { var->vmode |= FB_VMODE_YWRAP; - var->xoffset = display->var.xoffset; - var->yoffset = display->var.yoffset; + var->xoffset = info->var.xoffset; + var->yoffset = info->var.yoffset; } /* XXX FIXME - forcing var's */ @@ -369,7 +364,7 @@ static int sgivwfb_set_par(struct fb_info *info) u32 readVal, outputVal; int wholeTilesX, maxPixelsPerTileX; int frmWrite1, frmWrite2, frmWrite3b; - dbe_timing_info_t *currentTiming; /* Current Video Timing */ + struct dbe_timing_info_t *currentTiming; /* Current Video Timing */ int xpmax, ypmax; // Monitor resolution int bytesPerPixel; // Bytes per pixel @@ -705,11 +700,16 @@ int __init sgivwfb_init(void) printk(KERN_INFO "sgivwfb: framebuffer at 0x%lx, size %ldk\n", sgivwfb_mem_phys, sgivwfb_mem_size / 1024); - default_par.regs = (asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE); + if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) { + printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n"); + goto fail_request_mem_region; + } + default_par.regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE); if (!default_par.regs) { printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n"); goto fail_ioremap_regs; } + #ifdef CONFIG_MTRR mtrr_add((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size, MTRR_TYPE_WRCOMB, 1); @@ -720,41 +720,29 @@ int __init sgivwfb_init(void) sgivwfb_fix.ywrapstep = ywrap; sgivwfb_fix.ypanstep = ypan; - strcpy(fb_info.modename, sgivwfb_fix.id); - fb_info.changevar = NULL; fb_info.node = NODEV; fb_info.fix = sgivwfb_fix; fb_info.var = sgivwfb_var; fb_info.fbops = &sgivwfb_ops; fb_info.pseudo_palette = pseudo_palette; fb_info.par = &default_par; - fb_info.disp = &disp; - fb_info.currcon = -1; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_info.flags = FBINFO_FLAG_DEFAULT; fb_info.screen_base = - ioremap_nocache((unsigned long) sgivwfb_mem_phys, - sgivwfb_mem_size); + fb_info.screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size); if (!fb_info.screen_base) { printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n"); goto fail_ioremap_fbmem; } - /* turn on default video mode */ - gen_set_var(&fb_info->var, -1, &fb_info); + fb_alloc_cmap(&fb_info.cmap, 256, 0); if (register_framebuffer(&fb_info) < 0) { - printk(KERN_ERR - "sgivwfb: couldn't register framebuffer\n"); + printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n"); goto fail_register_framebuffer; } - printk(KERN_INFO - "fb%d: Virtual frame buffer device, using %ldK of video memory\n", - GET_FB_IDX(fb_info.node), sgivwfb_mem_size >> 10); - + printk(KERN_INFO "fb%d: SGI BDE frame buffer device, using %ldK of video memory\n", minor(fb_info.node, sgivwfb_mem_size >> 10); return 0; fail_register_framebuffer: diff --git a/drivers/video/sis/Makefile b/drivers/video/sis/Makefile index 8987332dd1ce..c816cec01859 100644 --- a/drivers/video/sis/Makefile +++ b/drivers/video/sis/Makefile @@ -6,7 +6,7 @@ export-objs := sis_main.o obj-$(CONFIG_FB_SIS) += sisfb.o -sisfb-objs := sis_main.o init.o init301.o +sisfb-objs := sis_main.o sis_accel.o init.o init301.o include $(TOPDIR)/Rules.make diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c new file mode 100644 index 000000000000..fa0a1851f09b --- /dev/null +++ b/drivers/video/sis/sis_accel.c @@ -0,0 +1,495 @@ +/* + * SiS 300/630/730/540/315/550/650/740 frame buffer driver + * for Linux kernels 2.4.x and 2.5.x + * + * 2D acceleration part + * + * Based on the X driver's sis300_accel.c which is + * Copyright Xavier Ducoin <x.ducoin@lectra.com> + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * and sis310_accel.c which is + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * (see http://www.winischhofer.net/ + * for more information and updates) + */ + +#include <linux/config.h> +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/console.h> +#include <linux/selection.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/vt_kern.h> +#include <linux/capability.h> +#include <linux/fs.h> +#include <linux/agp_backend.h> + +#include <linux/types.h> +#include <linux/sisfb.h> + +#include <asm/io.h> +#include <asm/mtrr.h> + +#include <video/fbcon.h> +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) +#include <video/fbcon-cfb8.h> +#include <video/fbcon-cfb16.h> +#include <video/fbcon-cfb24.h> +#include <video/fbcon-cfb32.h> +#endif + +#include "osdef.h" +#include "vgatypes.h" +#include "vstruct.h" +#include "sis_accel.h" + +extern struct video_info ivideo; +extern VGA_ENGINE sisvga_engine; + +static const int sisALUConv[] = +{ + 0x00, /* dest = 0; 0, GXclear, 0 */ + 0x88, /* dest &= src; DSa, GXand, 0x1 */ + 0x44, /* dest = src & ~dest; SDna, GXandReverse, 0x2 */ + 0xCC, /* dest = src; S, GXcopy, 0x3 */ + 0x22, /* dest &= ~src; DSna, GXandInverted, 0x4 */ + 0xAA, /* dest = dest; D, GXnoop, 0x5 */ + 0x66, /* dest = ^src; DSx, GXxor, 0x6 */ + 0xEE, /* dest |= src; DSo, GXor, 0x7 */ + 0x11, /* dest = ~src & ~dest; DSon, GXnor, 0x8 */ + 0x99, /* dest ^= ~src ; DSxn, GXequiv, 0x9 */ + 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ + 0xDD, /* dest = src|~dest ; SDno, GXorReverse, 0xB */ + 0x33, /* dest = ~src; Sn, GXcopyInverted, 0xC */ + 0xBB, /* dest |= ~src; DSno, GXorInverted, 0xD */ + 0x77, /* dest = ~src|~dest; DSan, GXnand, 0xE */ + 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ +}; +/* same ROP but with Pattern as Source */ +static const int sisPatALUConv[] = +{ + 0x00, /* dest = 0; 0, GXclear, 0 */ + 0xA0, /* dest &= src; DPa, GXand, 0x1 */ + 0x50, /* dest = src & ~dest; PDna, GXandReverse, 0x2 */ + 0xF0, /* dest = src; P, GXcopy, 0x3 */ + 0x0A, /* dest &= ~src; DPna, GXandInverted, 0x4 */ + 0xAA, /* dest = dest; D, GXnoop, 0x5 */ + 0x5A, /* dest = ^src; DPx, GXxor, 0x6 */ + 0xFA, /* dest |= src; DPo, GXor, 0x7 */ + 0x05, /* dest = ~src & ~dest; DPon, GXnor, 0x8 */ + 0xA5, /* dest ^= ~src ; DPxn, GXequiv, 0x9 */ + 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ + 0xF5, /* dest = src|~dest ; PDno, GXorReverse, 0xB */ + 0x0F, /* dest = ~src; Pn, GXcopyInverted, 0xC */ + 0xAF, /* dest |= ~src; DPno, GXorInverted, 0xD */ + 0x5F, /* dest = ~src|~dest; DPan, GXnand, 0xE */ + 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) +static const unsigned char myrops[] = { + 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 + }; +#endif + +/* 300 series */ + +static void +SiS300Sync(void) +{ + SiS300Idle +} + +static void +SiS310Sync(void) +{ + SiS310Idle +} + +static void +SiS300SetupForScreenToScreenCopy(int xdir, int ydir, int rop, + unsigned int planemask, int trans_color) +{ + SiS300SetupDSTColorDepth(ivideo.DstColor); + SiS300SetupSRCPitch(ivideo.video_linelength) + SiS300SetupDSTRect(ivideo.video_linelength, -1) + + if(trans_color != -1) { + SiS300SetupROP(0x0A) + SiS300SetupSRCTrans(trans_color) + SiS300SetupCMDFlag(TRANSPARENT_BITBLT) + } else { + SiS300SetupROP(sisALUConv[rop]) + } + if(xdir > 0) { + SiS300SetupCMDFlag(X_INC) + } + if(ydir > 0) { + SiS300SetupCMDFlag(Y_INC) + } +} + +static void +SiS300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y, + int width, int height) +{ + long srcbase, dstbase; + + srcbase = dstbase = 0; + if (src_y >= 2048) { + srcbase = ivideo.video_linelength * src_y; + src_y = 0; + } + if (dst_y >= 2048) { + dstbase = ivideo.video_linelength * dst_y; + dst_y = 0; + } + + SiS300SetupSRCBase(srcbase); + SiS300SetupDSTBase(dstbase); + + if(!(ivideo.CommandReg & X_INC)) { + src_x += width-1; + dst_x += width-1; + } + if(!(ivideo.CommandReg & Y_INC)) { + src_y += height-1; + dst_y += height-1; + } + SiS300SetupRect(width, height) + SiS300SetupSRCXY(src_x, src_y) + SiS300SetupDSTXY(dst_x, dst_y) + SiS300DoCMD +} + +static void +SiS300SetupForSolidFill(int color, int rop, unsigned int planemask) +{ + SiS300SetupPATFG(color) + SiS300SetupDSTRect(ivideo.video_linelength, -1) + SiS300SetupDSTColorDepth(ivideo.DstColor); + SiS300SetupROP(sisPatALUConv[rop]) + SiS300SetupCMDFlag(PATFG) +} + +static void +SiS300SubsequentSolidFillRect(int x, int y, int w, int h) +{ + long dstbase; + + dstbase = 0; + if(y >= 2048) { + dstbase = ivideo.video_linelength * y; + y = 0; + } + SiS300SetupDSTBase(dstbase) + SiS300SetupDSTXY(x,y) + SiS300SetupRect(w,h) + SiS300SetupCMDFlag(X_INC | Y_INC | BITBLT) + SiS300DoCMD +} + +/* 310/325 series ------------------------------------------------ */ + +static void +SiS310SetupForScreenToScreenCopy(int xdir, int ydir, int rop, + unsigned int planemask, int trans_color) +{ + SiS310SetupDSTColorDepth(ivideo.DstColor); + SiS310SetupSRCPitch(ivideo.video_linelength) + SiS310SetupDSTRect(ivideo.video_linelength, -1) + if (trans_color != -1) { + SiS310SetupROP(0x0A) + SiS310SetupSRCTrans(trans_color) + SiS310SetupCMDFlag(TRANSPARENT_BITBLT) + } else { + SiS310SetupROP(sisALUConv[rop]) + /* Set command - not needed, both 0 */ + /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */ + } + SiS310SetupCMDFlag(ivideo.SiS310_AccelDepth) + /* TW: The 310/325 series is smart enough to know the direction */ +} + +static void +SiS310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y, + int width, int height) +{ + long srcbase, dstbase; + + srcbase = dstbase = 0; + if (src_y >= 2048) { + srcbase = ivideo.video_linelength * src_y; + src_y = 0; + } + if (dst_y >= 2048) { + dstbase = ivideo.video_linelength * dst_y; + dst_y = 0; + } + + SiS310SetupSRCBase(srcbase); + SiS310SetupDSTBase(dstbase); + SiS310SetupRect(width, height) + SiS310SetupSRCXY(src_x, src_y) + SiS310SetupDSTXY(dst_x, dst_y) + SiS310DoCMD +} + +static void +SiS310SetupForSolidFill(int color, int rop, unsigned int planemask) +{ + SiS310SetupPATFG(color) + SiS310SetupDSTRect(ivideo.video_linelength, -1) + SiS310SetupDSTColorDepth(ivideo.DstColor); + SiS310SetupROP(sisPatALUConv[rop]) + SiS310SetupCMDFlag(PATFG | ivideo.SiS310_AccelDepth) +} + +static void +SiS310SubsequentSolidFillRect(int x, int y, int w, int h) +{ + long dstbase; + + dstbase = 0; + if(y >= 2048) { + dstbase = ivideo.video_linelength * y; + y = 0; + } + SiS310SetupDSTBase(dstbase) + SiS310SetupDSTXY(x,y) + SiS310SetupRect(w,h) + SiS310SetupCMDFlag(BITBLT) + SiS310DoCMD +} + +/* --------------------------------------------------------------------- */ + +/* The exported routines */ + +int sisfb_initaccel(void) +{ +#ifdef SISFB_USE_SPINLOCKS + spin_lock_init(&ivideo.lockaccel); +#endif + return(0); +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) /* --- KERNEL 2.5.34 and later --- */ + +void fbcon_sis_fillrect(struct fb_info *info, struct fb_fillrect *rect) +{ + CRITFLAGS + + if(!rect->width || !rect->height) + return; + + if(sisvga_engine == SIS_300_VGA) { + CRITBEGIN + SiS300SetupForSolidFill(rect->color, myrops[rect->rop], 0); + SiS300SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height); + CRITEND + SiS300Sync(); + } else { + CRITBEGIN + SiS310SetupForSolidFill(rect->color, myrops[rect->rop], 0); + SiS310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height); + CRITEND + SiS310Sync(); + } + +} + +void fbcon_sis_copyarea(struct fb_info *info, struct fb_copyarea *area) +{ + int xdir, ydir; + CRITFLAGS + + if(!area->width || !area->height) + return; + + if(area->sx < area->dx) xdir = 0; + else xdir = 1; + if(area->sy < area->dy) ydir = 0; + else ydir = 1; + + if(sisvga_engine == SIS_300_VGA) { + CRITBEGIN + SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1); + SiS300SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height); + CRITEND + SiS300Sync(); + } else { + CRITBEGIN + SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1); + SiS310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height); + CRITEND + SiS310Sync(); + } +} + +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) /* ------ KERNEL <2.5.34 ------ */ + +void fbcon_sis_bmove(struct display *p, int srcy, int srcx, + int dsty, int dstx, int height, int width) +{ + int xdir, ydir; + CRITFLAGS + + srcx *= fontwidth(p); + srcy *= fontheight(p); + dstx *= fontwidth(p); + dsty *= fontheight(p); + width *= fontwidth(p); + height *= fontheight(p); + + + if(srcx < dstx) xdir = 0; + else xdir = 1; + if(srcy < dsty) ydir = 0; + else ydir = 1; + + if(sisvga_engine == SIS_300_VGA) { + CRITBEGIN + SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1); + SiS300SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height); + CRITEND + SiS300Sync(); + } else { + CRITBEGIN + SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1); + SiS310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height); + CRITEND + SiS310Sync(); + } +} + + +static void fbcon_sis_clear(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width, int color) +{ + CRITFLAGS + + srcx *= fontwidth(p); + srcy *= fontheight(p); + width *= fontwidth(p); + height *= fontheight(p); + + if(sisvga_engine == SIS_300_VGA) { + CRITBEGIN + SiS300SetupForSolidFill(color, 3, 0); + SiS300SubsequentSolidFillRect(srcx, srcy, width, height); + CRITEND + SiS300Sync(); + } else { + CRITBEGIN + SiS310SetupForSolidFill(color, 3, 0); + SiS310SubsequentSolidFillRect(srcx, srcy, width, height); + CRITEND + SiS310Sync(); + } +} + +void fbcon_sis_clear8(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + u32 bgx; + + bgx = attr_bgcol_ec(p, conp); + fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx); +} + +void fbcon_sis_clear16(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + u32 bgx; + + bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; + fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx); +} + +void fbcon_sis_clear32(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + u32 bgx; + + bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; + fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx); +} + +void fbcon_sis_revc(struct display *p, int srcx, int srcy) +{ + CRITFLAGS + + srcx *= fontwidth(p); + srcy *= fontheight(p); + + if(sisvga_engine == SIS_300_VGA) { + CRITBEGIN + SiS300SetupForSolidFill(0, 0x0a, 0); + SiS300SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p)); + CRITEND + SiS300Sync(); + } else { + CRITBEGIN + SiS310SetupForSolidFill(0, 0x0a, 0); + SiS310SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p)); + CRITEND + SiS310Sync(); + } +} + +#ifdef FBCON_HAS_CFB8 +struct display_switch fbcon_sis8 = { + setup: fbcon_cfb8_setup, + bmove: fbcon_sis_bmove, + clear: fbcon_sis_clear8, + putc: fbcon_cfb8_putc, + putcs: fbcon_cfb8_putcs, + revc: fbcon_cfb8_revc, + clear_margins: fbcon_cfb8_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif +#ifdef FBCON_HAS_CFB16 +struct display_switch fbcon_sis16 = { + setup: fbcon_cfb16_setup, + bmove: fbcon_sis_bmove, + clear: fbcon_sis_clear16, + putc: fbcon_cfb16_putc, + putcs: fbcon_cfb16_putcs, + revc: fbcon_sis_revc, + clear_margins: fbcon_cfb16_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif +#ifdef FBCON_HAS_CFB32 +struct display_switch fbcon_sis32 = { + setup: fbcon_cfb32_setup, + bmove: fbcon_sis_bmove, + clear: fbcon_sis_clear32, + putc: fbcon_cfb32_putc, + putcs: fbcon_cfb32_putcs, + revc: fbcon_sis_revc, + clear_margins: fbcon_cfb32_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif + +#endif /* KERNEL VERSION */ + + diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 83b4f07c6652..a6cb38550bc7 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -3391,7 +3391,7 @@ int __init sisfb_init(void) return -EINVAL; printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n", - GET_FB_IDX(fb_info.node), fb_info.modename, VER_MAJOR, VER_MINOR, + minor(fb_info.node), fb_info.modename, VER_MAJOR, VER_MINOR, VER_LEVEL); printk(KERN_INFO "sisfb: Added SISFB_GET_INFO ioctl = %x\n", SISFB_GET_INFO); diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 110e85dea332..fd6aba8342d7 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -125,9 +125,6 @@ static struct fb_info info; */ static struct xxx_par __initdata current_par; - /* To go away in the near future */ -static struct display disp; - int xxxfb_init(void); int xxxfb_setup(char*); @@ -287,6 +284,12 @@ 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 @@ -298,7 +301,7 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, * Returns negative errno on error, or zero on success. * */ -static int xxxfb_pan_display(struct fb_var_screeninfo *var, int con, +static int xxxfb_pan_display(struct fb_var_screeninfo *var, const struct fb_info *info) { /* ... */ @@ -421,15 +424,6 @@ int __init xxxfb_init(void) info.flags = FBINFO_FLAG_DEFAULT; info.par = current_par; - /* The following has to be set but in th efuture will go away */ - strcpy(info.modename, xxxfb_fix.id); - info.changevar = NULL; - info.currcon = -1; - info.disp = &disp; - info.switch_con = gen_switch; - info.updatevar = gen_update_var; - - /* * This should give a reasonable default video mode. The following is * done when we can set a video mode. @@ -450,11 +444,10 @@ int __init xxxfb_init(void) * mode. If we are setting the mode ourselves we don't call this. */ info.var = xxxfb_var; - gen_set_disp(-1, &fb_info); if (register_framebuffer(&info) < 0) return -EINVAL; - printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(info.node), + printk(KERN_INFO "fb%d: %s frame buffer device\n", minor(info.node), info.fix.id); return 0; } @@ -510,11 +503,6 @@ 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 */ - /* Stuff to go away. Use generic functions for now */ - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, - .fb_check_var = xxxfb_check_var, .fb_set_par = xxxfb_set_par, /* optional */ .fb_setcolreg = xxxfb_setcolreg, diff --git a/drivers/video/softcursor.c b/drivers/video/softcursor.c new file mode 100644 index 000000000000..28b378925d47 --- /dev/null +++ b/drivers/video/softcursor.c @@ -0,0 +1,62 @@ +/* + * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices + * + * Created 14 Nov 2002 by James Simmons + * + * 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/string.h> +#include <linux/tty.h> +#include <linux/fb.h> +#include <linux/slab.h> + +#include <asm/uaccess.h> +#include <asm/io.h> + +int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + int i, size = ((cursor->image.width + 7) / 8) * cursor->image.height; + struct fb_image image; + static char data[64]; + + if (cursor->enable) { + 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; + } + } else + memcpy(data, cursor->dest, size); + + image.bg_color = cursor->image.bg_color; + image.fg_color = cursor->image.fg_color; + image.dx = cursor->image.dx; + image.dy = cursor->image.dy; + image.width = cursor->image.width; + image.height = cursor->image.height; + image.depth = cursor->image.depth; + image.data = data; + + if (info->fbops->fb_imageblit) + info->fbops->fb_imageblit(info, &image); + return 0; +} + +EXPORT_SYMBOL(soft_cursor); + +MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); +MODULE_DESCRIPTION("Generic software cursor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index cb78eeb93607..024a4fb2e963 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -1906,7 +1906,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i goto fail; } printk(KERN_INFO "fb%d: %s frame buffer device\n", - GET_FB_IDX(sst_info->info.node),sst_info->info.modename); + minor(sst_info->info.node),sst_info->info.modename); return 0; fail: diff --git a/drivers/video/sti-bmode.h b/drivers/video/sti-bmode.h deleted file mode 100644 index 4aa38f6d9daa..000000000000 --- a/drivers/video/sti-bmode.h +++ /dev/null @@ -1,287 +0,0 @@ -#define STI_REGION_MAX 8 -#define STI_DEV_NAME_LENGTH 32 - -typedef struct { - u8 res[3]; - u8 data; -} __attribute__((packed)) sti_u8; - -typedef struct { - sti_u8 data[2]; -} __attribute__((packed)) sti_u16; - -typedef struct { - sti_u8 data[4]; -} __attribute__((packed)) sti_u32; - -#define STI_U8( u8) ((u8).data) -#define STI_U16(u16) ((STI_U8((u16).data[0])<<8) | STI_U8((u16).data[1])) -#define STI_U32(u32) ((STI_U8((u32).data[0])<<24) | \ - (STI_U8((u32).data[1])<<16) | \ - (STI_U8((u32).data[2])<< 8) | \ - (STI_U8((u32).data[3])<< 0)) - -struct sti_rom_region { - sti_u32 region; -}; - -struct sti_rom_font { - sti_u16 first_char; - sti_u16 last_char; - sti_u8 width; - sti_u8 height; - sti_u8 font_type; - sti_u8 bytes_per_char; - sti_u32 next_font; - sti_u8 underline_height; - sti_u8 underline_pos; - sti_u8 res008[2]; -}; - -struct sti_rom { - sti_u8 type; - sti_u8 num_mons; - sti_u8 revno[2]; - - sti_u8 graphics_id[8]; /* 0x010 */ - - sti_u32 font_start; /* 0x030 */ - sti_u32 statesize; - sti_u32 last_addr; - sti_u32 region_list; - - sti_u16 reentsize; /* 0x070 */ - sti_u16 maxtime; - sti_u32 mon_tbl_addr; - sti_u32 user_data_addr; - sti_u32 sti_mem_req; - - sti_u32 user_data_size; /* 0x0b0 */ - sti_u16 power; /* 0x0c0 */ - sti_u8 bus_support; - sti_u8 ext_bus_support; - sti_u8 alt_code_type; /* 0x0d0 */ - sti_u8 ext_dd_struct[3]; - sti_u32 cfb_addr; /* 0x0e0 */ - - sti_u8 res0f0[4]; - - sti_u32 init_graph; /* 0x0e0 */ - sti_u32 state_mgmt; - sti_u32 font_unpmv; - sti_u32 block_move; - sti_u32 self_test; - sti_u32 excep_hdlr; - sti_u32 inq_conf; - sti_u32 set_cm_entry; - sti_u32 dma_ctrl; - sti_u32 flow_ctrl; - sti_u32 user_timing; - sti_u32 process_mgr; - sti_u32 sti_util; - sti_u32 end_addr; - sti_u32 res0b8; - sti_u32 res0bc; - - sti_u32 init_graph_m68k; /* 0x0e0 */ - sti_u32 state_mgmt_m68k; - sti_u32 font_unpmv_m68k; - sti_u32 block_move_m68k; - sti_u32 self_test_m68k; - sti_u32 excep_hdlr_m68k; - sti_u32 inq_conf_m68k; - sti_u32 set_cm_entry_m68k; - sti_u32 dma_ctrl_m68k; - sti_u32 flow_ctrl_m68k; - sti_u32 user_timing_m68k; - sti_u32 process_mgr_m68k; - sti_u32 sti_util_m68k; - sti_u32 end_addr_m68k; - sti_u32 res0b8_m68k; - sti_u32 res0bc_m68k; - - sti_u8 res040[7 * 4]; -}; - -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); \ - }) - diff --git a/drivers/video/sticon-bmode.c b/drivers/video/sticon-bmode.c deleted file mode 100644 index 3ab5077ac27a..000000000000 --- a/drivers/video/sticon-bmode.c +++ /dev/null @@ -1,895 +0,0 @@ -/* -TPG CVS users: please don't commit changes to this file directly, send -them to prumpf@tux.org and wait for a new version instead. Otherwise, -your changes will get lost when prumpf releases the next version, as -this file *will* be replaced with it. You have been warned. - -2000-05-30, <deller@gmx.de> -*/ -#if 1 -#define DPRINTK(x) printk x -#else -#define DPRINTK(x) -#endif - -/* - * linux/drivers/video/sticon.c - console driver using HP's STI firmware - * - * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * - * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c, - * which were - * - * Created 28 Sep 1997 by Geert Uytterhoeven - * Rewritten by Martin Mares <mj@ucw.cz>, July 1998 - * Copyright (C) 1991, 1992 Linus Torvalds - * 1995 Jay Estabrook - * Copyright (C) 1995 Geert Uytterhoeven - * Copyright (C) 1993 Bjoern Brauel - * Roman Hodek - * Copyright (C) 1993 Hamish Macdonald - * Greg Harp - * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] - * - * with work by William Rucklidge (wjr@cs.cornell.edu) - * Geert Uytterhoeven - * Jes Sorensen (jds@kom.auc.dk) - * Martin Apel - * with work by Guenther Kelleter - * Martin Schaller - * Andreas Schwab - * Emmanuel Marty (core@ggi-project.org) - * Jakub Jelinek (jj@ultra.linux.cz) - * Martin Mares <mj@ucw.cz> - * - * 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/types.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/kd.h> -#include <linux/slab.h> -#include <linux/vt_kern.h> -#include <linux/selection.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/delay.h> - -#include <asm/io.h> -#include <asm/real.h> - -#include <linux/module.h> -#include <linux/fb.h> -#include <linux/smp.h> - -#include <asm/irq.h> -#include <asm/system.h> -#include <asm/uaccess.h> - -#include <video/fbcon.h> -#include <video/font.h> - -#include "sti-bmode.h" - -/* 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) ) - -static struct sti_struct default_sti = { - SPIN_LOCK_UNLOCKED, -}; - -static struct sti_font_flags default_font_flags = { - STI_WAIT, 0, 0, NULL -}; - -/* The colour indices used by STI are - * 0 - Black - * 1 - White - * 2 - Red - * 3 - Yellow/Brown - * 4 - Green - * 5 - Cyan - * 6 - Blue - * 7 - Magenta - * - * 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] = { - 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) - -#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) (STI_U8(PTR_STI(sti->font)->width)) -#define sti_font_y(sti) (STI_U8(PTR_STI(sti->font)->height)) - -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 -}; - -static void sti_init_graph(struct sti_struct *sti) -{ - struct sti_init_inptr_ext inptr_ext = { - 0, { 0 }, 0, NULL - }; - struct sti_init_inptr inptr = { - 3, STI_PTR(&inptr_ext) - }; - struct sti_init_outptr outptr = { 0 }; - unsigned long flags; - s32 ret; - - spin_lock_irqsave(&sti->lock, flags); - - ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr, - &outptr, sti->glob_cfg); - - spin_unlock_irqrestore(&sti->lock, flags); - - sti->text_planes = outptr.text_planes; -} - -#if 0 -static struct sti_conf_flags default_conf_flags = { - STI_WAIT, 0, NULL -}; - -static 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) - }; - unsigned long flags; - s32 ret; - - do { - spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->inq_conf, &default_conf_flags, - &inptr, &outptr, sti->glob_cfg); - spin_unlock_irqrestore(&sti->lock, flags); - } while(ret == 1); -} -#endif - -static 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 - }; - s32 ret; - unsigned long flags; - - do { - spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->font_unpmv, &default_font_flags, - &inptr, &outptr, sti->glob_cfg); - spin_unlock_irqrestore(&sti->lock, flags); - } while(ret == 1); -} - -static struct sti_blkmv_flags clear_blkmv_flags = { - STI_WAIT, 1, 1, 0, 0, NULL -}; - -static void sti_set(struct sti_struct *sti, int src_y, int src_x, - int height, int width, u8 color) -{ - struct sti_blkmv_inptr inptr = { - color, color, - src_x, src_y , - src_x, src_y , - width, height, - NULL - }; - struct sti_blkmv_outptr outptr = { 0, NULL }; - s32 ret = 0; - unsigned long flags; - - do { - spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &clear_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); - spin_unlock_irqrestore(&sti->lock, flags); - } while(ret == 1); -} - -static void sti_clear(struct sti_struct *sti, int src_y, int src_x, - int height, int width) -{ - 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 - }; - struct sti_blkmv_outptr outptr = { 0, NULL }; - s32 ret = 0; - unsigned long flags; - - do { - spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &clear_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); - spin_unlock_irqrestore(&sti->lock, flags); - } while(ret == 1); -} - -static struct sti_blkmv_flags default_blkmv_flags = { - STI_WAIT, 0, 0, 0, 0, NULL -}; - -static void sti_bmove(struct sti_struct *sti, int src_y, int src_x, - int dst_y, int dst_x, int height, int width) -{ - 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 - }; - struct sti_blkmv_outptr outptr = { 0, NULL }; - s32 ret = 0; - unsigned long flags; - - do { - spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &default_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); - spin_unlock_irqrestore(&sti->lock, flags); - } while(ret == 1); -} - - -/* STICON */ - -static const char __init *sticon_startup(void) -{ - return "STI console"; -} - -static int sticon_set_palette(struct vc_data *c, unsigned char *table) -{ - 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); -} - -static void sticon_putcs(struct vc_data *conp, const unsigned short *s, - int count, int ypos, int xpos) -{ - while(count--) { - sti_putc(&default_sti, scr_readw(s++), ypos, xpos++); - } -} - -static void sticon_cursor(struct vc_data *conp, int mode) -{ -} - -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); - - 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); - - 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); - - break; - } - - return 0; -} - -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); -} - -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_con(vc_rows, vc_cols, c->vc_num); -} - -static void sticon_deinit(struct vc_data *c) -{ -} - -static void sticon_clear(struct vc_data *conp, int sy, int sx, int height, - int width) -{ - sti_clear(&default_sti, sy, sx, height, width); -} - -static int sticon_switch(struct vc_data *conp) -{ - return 0; -} - -static int sticon_blank(struct vc_data *conp, int blank) -{ - return 0; -} - -static int sticon_scrolldelta(struct vc_data *conp, int lines) -{ - return 0; -} - -static int sticon_set_origin(struct vc_data *conp) -{ - return 0; -} - -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; -} - -static 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, -}; - -#include <asm/pgalloc.h> /* need cache flush routines */ -static void __init sti_rom_copy(unsigned long base, unsigned long offset, - unsigned long count, void *dest) -{ - void *savedest = dest; - int savecount = count; - - while(count >= 4) { - count -= 4; - *(u32 *)dest = gsc_readl(base + offset); -#if 0 - DPRINTK(("%08x\n", *(u32 *)dest)); - if(*(u32 *)dest == 0x64646464) { - DPRINTK(("!!!!\n")); - { u32 foo = 0; while(foo += 0x100); } - } -#endif - offset += 4; - dest += 4; - } - while(count) { - count--; - *(u8 *)dest = gsc_readb(base + offset); - offset++; - 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 byte mode ROM type %d\n", STI_U8(rom->type)); - printk(" supports %d monitors\n", STI_U8(rom->num_mons)); - printk(" conforms to STI ROM spec revision %d.%02x\n", - STI_U8(rom->revno[0]) >> 4, STI_U8(rom->revno[0]) & 0x0f); - printk(__FUNCTION__ ": %d\n", __LINE__); - printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02x\n", - (unsigned int) STI_U8(rom->graphics_id[0]), - (unsigned int) STI_U8(rom->graphics_id[1]), - (unsigned int) STI_U8(rom->graphics_id[2]), - (unsigned int) STI_U8(rom->graphics_id[3]), - (unsigned int) STI_U8(rom->graphics_id[4]), - (unsigned int) STI_U8(rom->graphics_id[5]), - (unsigned int) STI_U8(rom->graphics_id[6]), - (unsigned int) STI_U8(rom->graphics_id[7])); - printk(__FUNCTION__ ": %d\n", __LINE__); - printk(" font start %08x\n", STI_U32(rom->font_start)); - printk(__FUNCTION__ ": %d\n", __LINE__); - printk(" region list %08x\n", STI_U32(rom->region_list)); - printk(__FUNCTION__ ": %d\n", __LINE__); - printk(" init_graph %08x\n", STI_U32(rom->init_graph)); - printk(__FUNCTION__ ": %d\n", __LINE__); - printk(" alternate code type %d\n", STI_U8(rom->alt_code_type)); - printk(__FUNCTION__ ": %d\n", __LINE__); -} - -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; - -#if 0 - DPRINTK(("%p = %p + %08x\n", - ((void *)raw_rom) + (STI_U32(raw_rom->font_start)), - ((void *)raw_rom), (STI_U32(raw_rom->font_start)))); -#endif - raw_font = ((void *)raw_rom) + STI_U32(raw_rom->font_start) - 3; - - font_start = raw_font; - cooked_font->raw = raw_font; - - DPRINTK(("next font %08x\n", STI_U32(raw_font->next_font))); - - while(0 && STI_U32(raw_font->next_font)) { - raw_font = ((void *)font_start) + STI_U32(raw_font->next_font); - - cooked_font->next_font = - kmalloc(sizeof *cooked_font, GFP_KERNEL); - if(!cooked_font->next_font) - return; - - cooked_font = cooked_font->next_font; - -// cooked_font->raw = raw_font; - - DPRINTK(("raw_font %p\n", - raw_font)); - DPRINTK(("next_font %08x %p\n", - STI_U32(raw_font->next_font), - ((void *)font_start) + STI_U32(raw_font->next_font))); - } - - cooked_font->next_font = NULL; -} - -static unsigned long __init sti_cook_function(void *function, - u32 size) -{ - sti_u32 *func = (sti_u32 *)function; - u32 *ret; - int i; - - ret = kmalloc(size, GFP_KERNEL); - if(!ret) { - printk(KERN_ERR __FILE__ ": could not get memory.\n"); - return 0; - } - - for(i=0; i<(size/4); i++) - ret[i] = STI_U32(func[i]); - - flush_all_caches(); - - return virt_to_phys(ret); -} - -static int font_index, font_height, font_width; - -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((STI_U8(font->raw->width) == width) && - (STI_U8(font->raw->height) == height)) - return 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); - - 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; -} - -/* address is a pointer to a word mode or pci rom */ -static struct sti_struct * __init sti_read_rom(unsigned long address) -{ - struct sti_struct *ret = NULL; - struct sti_cooked_rom *cooked = NULL; - struct sti_rom *raw = NULL; - unsigned long size; - - ret = &default_sti; - - if(!ret) - goto out_err; - - cooked = kmalloc(sizeof *cooked, GFP_KERNEL); - raw = kmalloc(sizeof *raw, GFP_KERNEL); - - if(!(raw && cooked)) - goto out_err; - - /* reallocate raw */ - sti_rom_copy(address, 0, sizeof *raw, raw); - - dump_sti_rom(raw); - - size = STI_U32(raw->last_addr) + 1; - size = 128*1024; -// DPRINTK(("size %08lx\n", size)); -// DPRINTK(("font_start %08x\n", STI_U32(raw->font_start))); -// kfree(raw); - raw = kmalloc(size, GFP_KERNEL); - if(!raw) - goto out_err; - sti_rom_copy(address, 0, size-1, raw); - - sti_cook_fonts(cooked, raw); -// sti_cook_regions(cooked, raw); -// sti_cook_functions(cooked, raw); - - if(STI_U32(raw->region_list)) { - struct sti_rom_region *region = - ((void *)raw) + STI_U32(raw->region_list) - 3; - -// DPRINTK(("region_list %08x\n", STI_U32(raw->region_list))); - - ret->regions = kmalloc(32, GFP_KERNEL); /* FIXME!! */ - - ret->regions[0] = STI_U32(region[0].region); - ret->regions[1] = STI_U32(region[1].region); - ret->regions[2] = STI_U32(region[2].region); - ret->regions[3] = STI_U32(region[3].region); - ret->regions[4] = STI_U32(region[4].region); - ret->regions[5] = STI_U32(region[5].region); - ret->regions[6] = STI_U32(region[6].region); - ret->regions[7] = STI_U32(region[7].region); - } - - address = virt_to_phys(raw); - -#if 0 - DPRINTK(("init_graph %08x %08x\n" - "state_mgmt %08x %08x\n" - "font_unpmv %08x %08x\n" - "block_move %08x %08x\n" - "self_test %08x %08x\n" - "excep_hdlr %08x %08x\n" - "irq_conf %08x %08x\n" - "set_cm_e %08x %08x\n" - "dma_ctrl %08x %08x\n" - "flow_ctrl %08x %08x\n" - "user_timin %08x %08x\n" - "process_m %08x %08x\n" - "sti_util %08x %08x\n" - "end_addr %08x %08x\n", - STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k), - STI_U32(raw->state_mgmt), STI_U32(raw->state_mgmt_m68k), - STI_U32(raw->font_unpmv), STI_U32(raw->font_unpmv_m68k), - STI_U32(raw->block_move), STI_U32(raw->block_move_m68k), - STI_U32(raw->self_test), STI_U32(raw->self_test_m68k), - STI_U32(raw->excep_hdlr), STI_U32(raw->excep_hdlr_m68k), - STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k), - STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k), - STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k), - STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k), - STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k), - STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k), - STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k), - STI_U32(raw->end_addr), STI_U32(raw->end_addr_m68k) ) ); -#endif - - ret->init_graph = sti_cook_function(((void *)raw)+STI_U32(raw->init_graph)-3, - (STI_U32(raw->state_mgmt) - - STI_U32(raw->init_graph))/4); - - - ret->font_unpmv = sti_cook_function(((void *)raw)+STI_U32(raw->font_unpmv)-3, - (STI_U32(raw->block_move) - - STI_U32(raw->font_unpmv))/4); - - ret->block_move = sti_cook_function(((void *)raw)+STI_U32(raw->block_move)-3, - (STI_U32(raw->self_test) - - STI_U32(raw->block_move))/4); - - ret->inq_conf = sti_cook_function(((void *)raw)+STI_U32(raw->inq_conf), - STI_U32(raw->set_cm_entry) - - STI_U32(raw->inq_conf)); - - ret->rom = cooked; - ret->rom->raw = raw; - - ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw); - - return ret; - -out_err: - if(raw) - kfree(raw); - if(cooked) - kfree(cooked); - - return NULL; -} - -#if 0 -static void dump_globcfg_ext(struct sti_glob_cfg_ext *cfg) -{ - DPRINTK(("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)); -} - -static void dump_globcfg(struct sti_glob_cfg *glob_cfg) -{ - DPRINTK(("%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", - glob_cfg->text_planes, - glob_cfg->onscreen_x, glob_cfg->onscreen_y, - glob_cfg->offscreen_x, glob_cfg->offscreen_y, - glob_cfg->total_x, glob_cfg->total_y, - glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1], - glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3], - 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)); - dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr)); -} -#endif - -static void __init sti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa, - unsigned long rom_address) -{ - struct sti_glob_cfg *glob_cfg; - struct sti_glob_cfg_ext *glob_cfg_ext; - void *save_addr; - void *sti_mem_addr; - - 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); - - if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr)) - return; - - 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); - - 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; - - glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr); - - sti->glob_cfg = STI_PTR(glob_cfg); -} - -static void __init sti_try_rom(unsigned long address, unsigned long hpa) -{ - struct sti_struct *sti = NULL; - u16 sig; - - /* 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; - - printk("found potential STI ROM at %08lx\n", address); - - sig = le16_to_cpu(gsc_readw(address)); - - if((sig&0xff) == 0x01) { - sti = sti_read_rom(address); - } - - if(sig == 0x0303) { - printk("STI word mode ROM at %08lx, ignored\n", - address); - - sti = NULL; - } - - if(!sti) - return; - - /* 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)) DPRINTK(("f4000000 b\n")); - if (!pdc_add_valid((void *)0xf7000000)) DPRINTK(("f6000000 b\n")); - if (!pdc_add_valid((void *)0xf9000000)) DPRINTK(("f8000000 b\n")); - if (!pdc_add_valid((void *)0xfb000000)) DPRINTK(("fa000000 b\n")); - sti_init_glob_cfg(sti, hpa, address); - - sti_init_graph(sti); - - //sti_inq_conf(sti); -#if !defined(SERIAL_CONSOLE) - { - extern void pdc_console_die(void); - pdc_console_die(); - } -#endif - - take_over_console(&sti_con, 0, MAX_NR_CONSOLES-1, 1); - - /* sti_inq_conf(sti); */ -} - -static unsigned long sti_address; -static unsigned long sti_hpa; - -static void __init sti_init_roms(void) -{ - /* handle the command line */ - if(sti_address && sti_hpa) { - sti_try_rom(sti_address, sti_hpa); - - return; - } - - /* 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_try_rom(PAGE0->proc_sti, 0xf8000000); - else if(!pdc_add_valid((void *)0xf5000000)) - sti_try_rom(PAGE0->proc_sti, 0xf4000000); - else if(!pdc_add_valid((void *)0xf7000000)) - sti_try_rom(PAGE0->proc_sti, 0xf6000000); - else if(!pdc_add_valid((void *)0xfb000000)) - sti_try_rom(PAGE0->proc_sti, 0xfa000000); - } - - /* standard locations for GSC graphic devices */ - if(!pdc_add_valid((void *)0xf4000000)) - sti_try_rom(0xf4000000, 0xf4000000); - if(!pdc_add_valid((void *)0xf6000000)) - sti_try_rom(0xf6000000, 0xf6000000); - if(!pdc_add_valid((void *)0xf8000000)) - sti_try_rom(0xf8000000, 0xf8000000); - if(!pdc_add_valid((void *)0xfa000000)) - sti_try_rom(0xfa000000, 0xfa000000); -} - -static int __init sti_init(void) -{ - printk("searching for byte mode STI ROMs\n"); - sti_init_roms(); - return 0; -} - -module_init(sti_init) - -MODULE_LICENSE("GPL"); diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h new file mode 100644 index 000000000000..0572f4fb1d5e --- /dev/null +++ b/drivers/video/sticore.h @@ -0,0 +1,407 @@ +#ifndef STICORE_H +#define STICORE_H + +/* generic STI structures & functions */ + +#if 0 +#define DPRINTK(x) printk x +#else +#define DPRINTK(x) +#endif + +#define MAX_STI_ROMS 4 /* max no. of ROMs which this driver handles */ + +#define STI_REGION_MAX 8 /* hardcoded STI constants */ +#define STI_DEV_NAME_LENGTH 32 +#define STI_MONITOR_MAX 256 + +#define STI_FONT_HPROMAN8 1 +#define STI_FONT_KANA8 2 + +/* 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 + */ + +#define STI_WAIT 1 + +#include <asm/io.h> /* for USE_HPPA_IOREMAP */ + +#if USE_HPPA_IOREMAP + +#define STI_PTR(p) (p) +#define PTR_STI(p) (p) +static int inline STI_CALL( unsigned long func, + void *flags, void *inptr, void *outptr, void *glob_cfg ) +{ + int (*f)(void *,void *,void *,void *); + f = (void*)func; + return f(flags, inptr, outptr, glob_cfg); +} + +#else /* !USE_HPPA_IOREMAP */ + +#define STI_PTR(p) ( virt_to_phys(p) ) +#define PTR_STI(p) ( phys_to_virt((long)p) ) +#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \ + ({ \ + pdc_sti_call( func, (unsigned long)STI_PTR(flags), \ + (unsigned long)STI_PTR(inptr), \ + (unsigned long)STI_PTR(outptr), \ + (unsigned long)STI_PTR(glob_cfg)); \ + }) + +#endif /* USE_HPPA_IOREMAP */ + + +#define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x) +#define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y) + +/* sti_font_xy() use the native font ROM ! */ +#define sti_font_x(sti) (PTR_STI(sti->font)->width) +#define sti_font_y(sti) (PTR_STI(sti->font)->height) + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER) +#endif + +extern struct sti_struct *sti_init_roms(void); + +/* 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; + +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); +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, int c); +void sti_bmove(struct sti_struct *sti, int src_y, int src_x, + int dst_y, int dst_x, int height, int width); + + +/* STI function configuration structs */ + +typedef union region { + struct { + u32 offset : 14; /* offset in 4kbyte page */ + u32 sys_only : 1; /* don't map to user space */ + u32 cache : 1; /* map to data cache */ + u32 btlb : 1; /* map to block tlb */ + u32 last : 1; /* last region in list */ + u32 length : 14; /* length in 4kbyte page */ + } region_desc; + + u32 region; /* complete region value */ +} region_t; + +#define REGION_OFFSET_TO_PHYS( rt, hpa ) \ + (((rt).region_desc.offset << 12) + (hpa)) + +struct sti_glob_cfg_ext { + u8 curr_mon; /* current monitor configured */ + u8 friendly_boot; /* in friendly boot mode */ + s16 power; /* power calculation (in Watts) */ + s32 freq_ref; /* frequency refrence */ + u32 sti_mem_addr; /* pointer to global sti memory (size=sti_mem_request) */ + u32 future_ptr; /* pointer to future data */ +}; + +struct sti_glob_cfg { + s32 text_planes; /* number of planes used for text */ + s16 onscreen_x; /* screen width in pixels */ + s16 onscreen_y; /* screen height in pixels */ + s16 offscreen_x; /* offset width in pixels */ + s16 offscreen_y; /* offset height in pixels */ + s16 total_x; /* frame buffer width in pixels */ + s16 total_y; /* frame buffer height in pixels */ + u32 region_ptrs[STI_REGION_MAX]; /* region pointers */ + s32 reent_lvl; /* storage for reentry level value */ + u32 save_addr; /* where to save or restore reentrant state */ + u32 ext_ptr; /* pointer to extended glob_cfg data structure */ +}; + + +/* STI init function structs */ + +struct sti_init_flags { + u32 wait : 1; /* should routine idle wait or not */ + u32 reset : 1; /* hard reset the device? */ + u32 text : 1; /* turn on text display planes? */ + u32 nontext : 1; /* turn on non-text display planes? */ + u32 clear : 1; /* clear text display planes? */ + u32 cmap_blk : 1; /* non-text planes cmap black? */ + u32 enable_be_timer : 1; /* enable bus error timer */ + u32 enable_be_int : 1; /* enable bus error timer interrupt */ + u32 no_chg_tx : 1; /* don't change text settings */ + u32 no_chg_ntx : 1; /* don't change non-text settings */ + u32 no_chg_bet : 1; /* don't change berr timer settings */ + u32 no_chg_bei : 1; /* don't change berr int settings */ + u32 init_cmap_tx : 1; /* initialize cmap for text planes */ + u32 cmt_chg : 1; /* change current monitor type */ + u32 retain_ie : 1; /* don't allow reset to clear int enables */ + u32 caller_bootrom : 1; /* set only by bootrom for each call */ + u32 caller_kernel : 1; /* set only by kernel for each call */ + u32 caller_other : 1; /* set only by non-[BR/K] caller */ + u32 pad : 14; /* pad to word boundary */ + u32 future_ptr; /* pointer to future data */ +}; + +struct sti_init_inptr_ext { + u8 config_mon_type; /* configure to monitor type */ + u8 pad[1]; /* pad to word boundary */ + u16 inflight_data; /* inflight data possible on PCI */ + u32 future_ptr; /* pointer to future data */ +}; + +struct sti_init_inptr { + s32 text_planes; /* number of planes to use for text */ + u32 ext_ptr; /* pointer to extended init_graph inptr data structure*/ +}; + + +struct sti_init_outptr { + s32 errno; /* error number on failure */ + s32 text_planes; /* number of planes used for text */ + u32 future_ptr; /* pointer to future data */ +}; + + + +/* STI configuration function structs */ + +struct sti_conf_flags { + u32 wait : 1; /* should routine idle wait or not */ + u32 pad : 31; /* pad to word boundary */ + u32 future_ptr; /* pointer to future data */ +}; + +struct sti_conf_inptr { + u32 future_ptr; /* pointer to future data */ +}; + +struct sti_conf_outptr_ext { + u32 crt_config[3]; /* hardware specific X11/OGL information */ + u32 crt_hdw[3]; + u32 future_ptr; +}; + +struct sti_conf_outptr { + s32 errno; /* error number on failure */ + s16 onscreen_x; /* screen width in pixels */ + s16 onscreen_y; /* screen height in pixels */ + s16 offscreen_x; /* offscreen width in pixels */ + s16 offscreen_y; /* offscreen height in pixels */ + s16 total_x; /* frame buffer width in pixels */ + s16 total_y; /* frame buffer height in pixels */ + s32 bits_per_pixel; /* bits/pixel device has configured */ + s32 bits_used; /* bits which can be accessed */ + s32 planes; /* number of fb planes in system */ + u8 dev_name[STI_DEV_NAME_LENGTH]; /* null terminated product name */ + u32 attributes; /* flags denoting attributes */ + u32 ext_ptr; /* pointer to future data */ +}; + +struct sti_rom { + u8 type[4]; + u8 res004; + u8 num_mons; + u8 revno[2]; + u32 graphics_id[2]; + + 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_addr; + u32 state_mgmt_addr; + u32 font_unp_addr; + u32 block_move_addr; + u32 self_test_addr; + u32 excep_hdlr_addr; + u32 inq_conf_addr; + u32 set_cm_entry_addr; + u32 image_unpack_addr; + u32 pa_risx_addrs[7]; +}; + +struct sti_rom_font { + u16 first_char; + u16 last_char; + u8 width; + u8 height; + u8 font_type; /* language type */ + u8 bytes_per_char; + u32 next_font; + u8 underline_height; + u8 underline_pos; + u8 res008[2]; +}; + +/* sticore internal font handling */ + +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; +}; + +/* STI font printing function structs */ + +struct sti_font_inptr { + u32 font_start_addr; /* address of font start */ + s16 index; /* index into font table of character */ + u8 fg_color; /* foreground color of character */ + u8 bg_color; /* background color of character */ + s16 dest_x; /* X location of character upper left */ + s16 dest_y; /* Y location of character upper left */ + u32 future_ptr; /* pointer to future data */ +}; + +struct sti_font_flags { + u32 wait : 1; /* should routine idle wait or not */ + u32 non_text : 1; /* font unpack/move in non_text planes =1, text =0 */ + u32 pad : 30; /* pad to word boundary */ + u32 future_ptr; /* pointer to future data */ +}; + +struct sti_font_outptr { + s32 errno; /* error number on failure */ + u32 future_ptr; /* pointer to future data */ +}; + +/* STI blockmove structs */ + +struct sti_blkmv_flags { + u32 wait : 1; /* should routine idle wait or not */ + u32 color : 1; /* change color during move? */ + u32 clear : 1; /* clear during move? */ + u32 non_text : 1; /* block move in non_text planes =1, text =0 */ + u32 pad : 28; /* pad to word boundary */ + u32 future_ptr; /* pointer to future data */ +}; + +struct sti_blkmv_inptr { + u8 fg_color; /* foreground color after move */ + u8 bg_color; /* background color after move */ + s16 src_x; /* source upper left pixel x location */ + s16 src_y; /* source upper left pixel y location */ + s16 dest_x; /* dest upper left pixel x location */ + s16 dest_y; /* dest upper left pixel y location */ + s16 width; /* block width in pixels */ + s16 height; /* block height in pixels */ + u32 future_ptr; /* pointer to future data */ +}; + +struct sti_blkmv_outptr { + s32 errno; /* error number on failure */ + u32 future_ptr; /* pointer to future data */ +}; + + +/* internal generic STI struct */ + +struct sti_struct { + spinlock_t lock; + + /* the following fields needs to be filled in by the word/byte routines */ + int font_width; + int font_height; + /* char **mon_strings; */ + int sti_mem_request; + u32 graphics_id[2]; + + struct sti_cooked_rom *rom; + + unsigned long font_unpmv; + unsigned long block_move; + unsigned long init_graph; + unsigned long inq_conf; + + /* all following fields are initialized by the generic routines */ + int text_planes; + region_t regions[STI_REGION_MAX]; + unsigned long regions_phys[STI_REGION_MAX]; + + struct sti_glob_cfg *glob_cfg; + struct sti_cooked_font *font; /* ptr to selected font (cooked) */ + + struct sti_conf_outptr outptr; /* configuration */ + struct sti_conf_outptr_ext outptr_ext; + + /* PCI data structures (pg. 17ff from sti.pdf) */ + struct pci_dev *pd; + u8 rm_entry[16]; /* pci region mapper array == pci config space offset */ +}; + + + +/* helper functions */ +struct sti_struct *sti_init_roms(void); +struct sti_struct *sti_get_rom(int); +void sti_rom_copy(unsigned long base, unsigned long count, void *dest); +struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom, + int (*search_font_fnc) (struct sti_cooked_rom *,int,int) ); + +int sti_read_rom(int wordmode, struct sti_struct *sti, + unsigned long address); + + +/* FIXME: Do we have another solution for this ? */ +#include <linux/kernel.h> +#include <linux/slab.h> +#include <asm/cacheflush.h> +static inline void sti_flush(unsigned long from, unsigned long len) +{ + flush_data_cache(); + flush_kernel_dcache_range(from, len); + flush_icache_range(from, from+len); +} + +#endif /* STICORE_H */ diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 9f4af7cf66e1..27bf51f207bd 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1,27 +1,59 @@ /* - * linux/drivers/video/stifb.c - Generic frame buffer driver for HP - * workstations with STI (standard text interface) video firmware. + * linux/drivers/video/sti/stifb.c - + * 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> + * * Based on: - * linux/drivers/video/artistfb.c -- Artist frame buffer driver - * + * - linux/drivers/video/artistfb.c -- Artist frame buffer driver * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * - * based on skeletonfb, which was + * - based on skeletonfb, which was * Created 28 Dec 1997 by Geert Uytterhoeven + * - HP Xhp cfb-based X11 window driver for XFree86 + * (c)Copyright 1992 Hewlett-Packard Co. + * + * + * The following graphics display devices (NGLE family) are supported by this driver: + * + * HPA4070A known as "HCRX", a 1280x1024 color device with 8 planes + * HPA4071A known as "HCRX24", a 1280x1024 color device with 24 planes, + * optionally available with a hardware accelerator as HPA4071A_Z + * HPA1659A known as "CRX", a 1280x1024 color device with 8 planes + * HPA1439A known as "CRX24", a 1280x1024 color device with 24 planes, + * optionally available with a hardware accelerator. + * HPA1924A known as "GRX", a 1280x1024 grayscale device with 8 planes + * HPA2269A known as "Dual CRX", a 1280x1024 color device with 8 planes, + * implements support for two displays on a single graphics card. + * HP710C internal graphics support optionally available on the HP9000s710 SPU, + * supports 1280x1024 color displays with 8 planes. + * HP710G same as HP710C, 1280x1024 grayscale only + * HP710L same as HP710C, 1024x768 color only + * HP712 internal graphics support on HP9000s712 SPU, supports 640x480, + * 1024x768 or 1280x1024 color displays on 8 planes (Artist) * * 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. */ + * for more details. + */ -/* - * Notes: - * - * This driver assumes that the video has been set up in 1bpp mode by - * the firmware. Since HP video tends to be planar rather than - * packed-pixel this will probably work anyway even if it isn't. +/* TODO: + * - remove the static fb_info to support multiple cards + * - remove the completely untested 1bpp mode + * - add support for h/w acceleration + * - add hardware cursor + * - */ + +/* on supported graphic devices you may: + * #define FALLBACK_TO_1BPP to fall back to 1 bpp, or + * #undef FALLBACK_TO_1BPP to reject support for unsupported cards */ +#undef FALLBACK_TO_1BPP + + +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -32,179 +64,1322 @@ #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" -#include "sti.h" +#ifdef __LP64__ +/* return virtual address */ +#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) \ + fb_info->sti->glob_cfg->region_ptrs[index] +#endif -static struct fb_ops stifb_ops; +#define NGLEDEVDEPROM_CRT_REGION 1 + +typedef struct { + __s32 video_config_reg; + __s32 misc_video_start; + __s32 horiz_timing_fmt; + __s32 serr_timing_fmt; + __s32 vert_timing_fmt; + __s32 horiz_state; + __s32 vert_state; + __s32 vtg_state_elements; + __s32 pipeline_delay; + __s32 misc_video_end; +} video_setup_t; + +typedef struct { + __s16 sizeof_ngle_data; + __s16 x_size_visible; /* visible screen dim in pixels */ + __s16 y_size_visible; + __s16 pad2[15]; + __s16 cursor_pipeline_delay; + __s16 video_interleaves; + __s32 pad3[11]; +} ngle_rom_t; struct stifb_info { - struct fb_info_gen gen; + struct fb_info info; + unsigned int id; + ngle_rom_t ngle_rom; struct sti_struct *sti; + int deviceSpecificConfig; + struct display disp; }; -struct stifb_par { -}; +static int stifb_force_bpp[MAX_STI_ROMS] = {0, }; -static struct stifb_info fb_info; -static struct display disp; +/* ------------------- chipset specific functions -------------------------- */ -int stifb_init(void); -int stifb_setup(char*); +/* offsets to graphic-chip internal registers */ -extern struct display_switch fbcon_sti; +#define REG_1 0x000118 +#define REG_2 0x000480 +#define REG_3 0x0004a0 +#define REG_4 0x000600 +#define REG_6 0x000800 +#define REG_8 0x000820 +#define REG_9 0x000a04 +#define REG_10 0x018000 +#define REG_11 0x018004 +#define REG_12 0x01800c +#define REG_13 0x018018 +#define REG_14 0x01801c +#define REG_15 0x200000 +#define REG_15b0 0x200000 +#define REG_16b1 0x200005 +#define REG_16b3 0x200007 +#define REG_21 0x200218 +#define REG_22 0x0005a0 +#define REG_23 0x0005c0 +#define REG_26 0x200118 +#define REG_27 0x200308 +#define REG_32 0x21003c +#define REG_33 0x210040 +#define REG_34 0x200008 +#define REG_35 0x018010 +#define REG_38 0x210020 +#define REG_39 0x210120 +#define REG_40 0x210130 +#define REG_42 0x210028 +#define REG_43 0x21002c +#define REG_44 0x210030 +#define REG_45 0x210034 -/* ------------------- chipset specific functions -------------------------- */ +#define READ_BYTE(fb,reg) __raw_readb((fb)->info.fix.mmio_start + (reg)) +#define READ_WORD(fb,reg) __raw_readl((fb)->info.fix.mmio_start + (reg)) +#define WRITE_BYTE(value,fb,reg) __raw_writeb((value),(fb)->info.fix.mmio_start + (reg)) +#define WRITE_WORD(value,fb,reg) __raw_writel((value),(fb)->info.fix.mmio_start + (reg)) -static int -sti_encode_fix(struct fb_fix_screeninfo *fix, - const void *par, struct fb_info_gen *info) +#define ENABLE 1 /* for enabling/disabling screen */ +#define DISABLE 0 + +#define NGLE_LOCK(fb_info) do { } while (0) +#define NGLE_UNLOCK(fb_info) do { } while (0) + +static void +SETUP_HW(struct stifb_info *fb) { - /* XXX: what about smem_len? */ - fix->smem_start = PTR_STI(fb_info.sti->glob_cfg)->region_ptrs[1]; - fix->type = FB_TYPE_PLANES; /* well, sort of */ + char stat; - return 0; + do { + stat = READ_BYTE(fb, REG_15b0); + if (!stat) + stat = READ_BYTE(fb, REG_15b0); + } while (stat); } -static int -sti_decode_var(const struct fb_var_screeninfo *var, - void *par, struct fb_info_gen *info) + +static void +SETUP_FB(struct stifb_info *fb) +{ + unsigned int reg10_value = 0; + + SETUP_HW(fb); + switch (fb->id) + { + case CRT_ID_VISUALIZE_EG: + case S9000_ID_ARTIST: + case S9000_ID_A1659A: + reg10_value = 0x13601000; + break; + case S9000_ID_A1439A: + if (fb->info.var.bits_per_pixel == 32) + reg10_value = 0xBBA0A000; + else + reg10_value = 0x13601000; + break; + case S9000_ID_HCRX: + if (fb->info.var.bits_per_pixel == 32) + reg10_value = 0xBBA0A000; + else + reg10_value = 0x13602000; + break; + case S9000_ID_TIMBER: + case CRX24_OVERLAY_PLANES: + reg10_value = 0x13602000; + break; + } + if (reg10_value) + WRITE_WORD(reg10_value, fb, REG_10); + WRITE_WORD(0x83000300, fb, REG_14); + SETUP_HW(fb); + WRITE_BYTE(1, fb, REG_16b1); +} + +static void +START_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb) { - return 0; + SETUP_HW(fb); + WRITE_WORD(0xBBE0F000, fb, REG_10); + WRITE_WORD(0x03000300, fb, REG_14); + WRITE_WORD(~0, fb, REG_13); } -static int -sti_encode_var(struct fb_var_screeninfo *var, - const void *par, struct fb_info_gen *info) +static void +WRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color) { - var->xres = PTR_STI(fb_info.sti->glob_cfg)->onscreen_x; - var->yres = PTR_STI(fb_info.sti->glob_cfg)->onscreen_y; - var->xres_virtual = PTR_STI(fb_info.sti->glob_cfg)->total_x; - var->yres_virtual = PTR_STI(fb_info.sti->glob_cfg)->total_y; - var->xoffset = var->yoffset = 0; + SETUP_HW(fb); + WRITE_WORD(((0x100+index)<<2), fb, REG_3); + WRITE_WORD(color, fb, REG_4); +} - var->bits_per_pixel = 1; - var->grayscale = 0; +static void +FINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb) +{ + WRITE_WORD(0x400, fb, REG_2); + if (fb->info.var.bits_per_pixel == 32) { + WRITE_WORD(0x83000100, fb, REG_1); + } else { + if (fb->id == S9000_ID_ARTIST || fb->id == CRT_ID_VISUALIZE_EG) + WRITE_WORD(0x80000100, fb, REG_26); + else + WRITE_WORD(0x80000100, fb, REG_1); + } + SETUP_FB(fb); +} - return 0; +static void +SETUP_RAMDAC(struct stifb_info *fb) +{ + SETUP_HW(fb); + WRITE_WORD(0x04000000, fb, 0x1020); + WRITE_WORD(0xff000000, fb, 0x1028); +} + +static void +CRX24_SETUP_RAMDAC(struct stifb_info *fb) +{ + SETUP_HW(fb); + WRITE_WORD(0x04000000, fb, 0x1000); + WRITE_WORD(0x02000000, fb, 0x1004); + WRITE_WORD(0xff000000, fb, 0x1008); + WRITE_WORD(0x05000000, fb, 0x1000); + WRITE_WORD(0x02000000, fb, 0x1004); + WRITE_WORD(0x03000000, fb, 0x1008); +} + +#if 0 +static void +HCRX_SETUP_RAMDAC(struct stifb_info *fb) +{ + WRITE_WORD(0xffffffff, fb, REG_32); +} +#endif + +static void +CRX24_SET_OVLY_MASK(struct stifb_info *fb) +{ + SETUP_HW(fb); + WRITE_WORD(0x13a02000, fb, REG_11); + WRITE_WORD(0x03000300, fb, REG_14); + WRITE_WORD(0x000017f0, fb, REG_3); + WRITE_WORD(0xffffffff, fb, REG_13); + WRITE_WORD(0xffffffff, fb, REG_22); + WRITE_WORD(0x00000000, fb, REG_23); +} + +static void +ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) +{ + unsigned int value = enable ? 0x43000000 : 0x03000000; + SETUP_HW(fb); + WRITE_WORD(0x06000000, fb, 0x1030); + WRITE_WORD(value, fb, 0x1038); +} + +static void +CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) +{ + unsigned int value = enable ? 0x10000000 : 0x30000000; + SETUP_HW(fb); + WRITE_WORD(0x01000000, fb, 0x1000); + WRITE_WORD(0x02000000, fb, 0x1004); + WRITE_WORD(value, fb, 0x1008); +} + +static void +ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) +{ + u32 DregsMiscVideo = REG_21; + u32 DregsMiscCtl = REG_27; + + SETUP_HW(fb); + if (enable) { + WRITE_WORD(READ_WORD(fb, DregsMiscVideo) | 0x0A000000, fb, DregsMiscVideo); + WRITE_WORD(READ_WORD(fb, DregsMiscCtl) | 0x00800000, fb, DregsMiscCtl); + } else { + WRITE_WORD(READ_WORD(fb, DregsMiscVideo) & ~0x0A000000, fb, DregsMiscVideo); + WRITE_WORD(READ_WORD(fb, DregsMiscCtl) & ~0x00800000, fb, DregsMiscCtl); + } +} + +#define GET_ROMTABLE_INDEX(fb) \ + (READ_BYTE(fb, REG_16b3) - 1) + +#define HYPER_CONFIG_PLANES_24 0x00000100 + +#define IS_24_DEVICE(fb) \ + (fb->deviceSpecificConfig & HYPER_CONFIG_PLANES_24) + +#define IS_888_DEVICE(fb) \ + (!(IS_24_DEVICE(fb))) + +#define GET_FIFO_SLOTS(fb, cnt, numslots) \ +{ while (cnt < numslots) \ + cnt = READ_WORD(fb, REG_34); \ + cnt -= numslots; \ } +#define IndexedDcd 0 /* Pixel data is indexed (pseudo) color */ +#define Otc04 2 /* Pixels in each longword transfer (4) */ +#define Otc32 5 /* Pixels in each longword transfer (32) */ +#define Ots08 3 /* Each pixel is size (8)d transfer (1) */ +#define OtsIndirect 6 /* Each bit goes through FG/BG color(8) */ +#define AddrLong 5 /* FB address is Long aligned (pixel) */ +#define BINovly 0x2 /* 8 bit overlay */ +#define BINapp0I 0x0 /* Application Buffer 0, Indexed */ +#define BINapp1I 0x1 /* Application Buffer 1, Indexed */ +#define BINapp0F8 0xa /* Application Buffer 0, Fractional 8-8-8 */ +#define BINattr 0xd /* Attribute Bitmap */ +#define RopSrc 0x3 +#define BitmapExtent08 3 /* Each write hits ( 8) bits in depth */ +#define BitmapExtent32 5 /* Each write hits (32) bits in depth */ +#define DataDynamic 0 /* Data register reloaded by direct access */ +#define MaskDynamic 1 /* Mask register reloaded by direct access */ +#define MaskOtc 0 /* Mask contains Object Count valid bits */ + +#define MaskAddrOffset(offset) (offset) +#define StaticReg(en) (en) +#define BGx(en) (en) +#define FGx(en) (en) + +#define BAJustPoint(offset) (offset) +#define BAIndexBase(base) (base) +#define BA(F,C,S,A,J,B,I) \ + (((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I)) + +#define IBOvals(R,M,X,S,D,L,B,F) \ + (((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F)) + +#define NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, val) \ + WRITE_WORD(val, fb, REG_14) + +#define NGLE_QUICK_SET_DST_BM_ACCESS(fb, val) \ + WRITE_WORD(val, fb, REG_11) + +#define NGLE_QUICK_SET_CTL_PLN_REG(fb, val) \ + WRITE_WORD(val, fb, REG_12) + +#define NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, plnmsk32) \ + WRITE_WORD(plnmsk32, fb, REG_13) + +#define NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, fg32) \ + WRITE_WORD(fg32, fb, REG_35) + +#define NGLE_SET_TRANSFERDATA(fb, val) \ + WRITE_WORD(val, fb, REG_8) + +#define NGLE_SET_DSTXY(fb, val) \ + WRITE_WORD(val, fb, REG_6) + +#define NGLE_LONG_FB_ADDRESS(fbaddrbase, x, y) ( \ + (u32) (fbaddrbase) + \ + ( (unsigned int) ( (y) << 13 ) | \ + (unsigned int) ( (x) << 2 ) ) \ + ) + +#define NGLE_BINC_SET_DSTADDR(fb, addr) \ + WRITE_WORD(addr, fb, REG_3) + +#define NGLE_BINC_SET_SRCADDR(fb, addr) \ + WRITE_WORD(addr, fb, REG_2) + +#define NGLE_BINC_SET_DSTMASK(fb, mask) \ + WRITE_WORD(mask, fb, REG_22) + +#define NGLE_BINC_WRITE32(fb, data32) \ + WRITE_WORD(data32, fb, REG_23) + +#define START_COLORMAPLOAD(fb, cmapBltCtlData32) \ + WRITE_WORD((cmapBltCtlData32), fb, REG_38) + +#define SET_LENXY_START_RECFILL(fb, lenxy) \ + WRITE_WORD(lenxy, fb, REG_9) + +static void +HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) +{ + u32 DregsHypMiscVideo = REG_33; + unsigned int value; + SETUP_HW(fb); + value = READ_WORD(fb, DregsHypMiscVideo); + if (enable) + value |= 0x0A000000; + else + value &= ~0x0A000000; + WRITE_WORD(value, fb, DregsHypMiscVideo); +} + + +/* BufferNumbers used by SETUP_ATTR_ACCESS() */ +#define BUFF0_CMAP0 0x00001e02 +#define BUFF1_CMAP0 0x02001e02 +#define BUFF1_CMAP3 0x0c001e02 +#define ARTIST_CMAP0 0x00000102 +#define HYPER_CMAP8 0x00000100 +#define HYPER_CMAP24 0x00000800 + +static void +SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber) +{ + SETUP_HW(fb); + WRITE_WORD(0x2EA0D000, fb, REG_11); + WRITE_WORD(0x23000302, fb, REG_14); + WRITE_WORD(BufferNumber, fb, REG_12); + WRITE_WORD(0xffffffff, fb, REG_8); +} + +static void +SET_ATTR_SIZE(struct stifb_info *fb, int width, int height) +{ + WRITE_WORD(0x00000000, fb, REG_6); + WRITE_WORD((width<<16) | height, fb, REG_9); + WRITE_WORD(0x05000000, fb, REG_6); + WRITE_WORD(0x00040001, fb, REG_9); +} + +static void +FINISH_ATTR_ACCESS(struct stifb_info *fb) +{ + SETUP_HW(fb); + WRITE_WORD(0x00000000, fb, REG_12); +} + +static void +elkSetupPlanes(struct stifb_info *fb) +{ + SETUP_RAMDAC(fb); + SETUP_FB(fb); +} + +static void +ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber) +{ + SETUP_ATTR_ACCESS(fb, BufferNumber); + SET_ATTR_SIZE(fb, fb->info.var.xres, fb->info.var.yres); + FINISH_ATTR_ACCESS(fb); + SETUP_FB(fb); +} + + static void -sti_get_par(void *par, struct fb_info_gen *info) +rattlerSetupPlanes(struct stifb_info *fb) +{ + CRX24_SETUP_RAMDAC(fb); + + /* replacement for: SETUP_FB(fb, CRX24_OVERLAY_PLANES); */ + WRITE_WORD(0x83000300, fb, REG_14); + SETUP_HW(fb); + WRITE_BYTE(1, fb, REG_16b1); + + /* XXX: replace by fb_setmem(), smem_start or screen_base ? */ + memset_io(fb->info.fix.smem_start, 0xff, + fb->info.var.yres*fb->info.fix.line_length); + + CRX24_SET_OVLY_MASK(fb); + SETUP_FB(fb); +} + + +#define HYPER_CMAP_TYPE 0 +#define NGLE_CMAP_INDEXED0_TYPE 0 +#define NGLE_CMAP_OVERLAY_TYPE 3 + +/* typedef of LUT (Colormap) BLT Control Register */ +typedef union /* Note assumption that fields are packed left-to-right */ +{ u32 all; + struct + { + unsigned enable : 1; + unsigned waitBlank : 1; + unsigned reserved1 : 4; + unsigned lutOffset : 10; /* Within destination LUT */ + unsigned lutType : 2; /* Cursor, image, overlay */ + unsigned reserved2 : 4; + unsigned length : 10; + } fields; +} NgleLutBltCtl; + + +#if 0 +static NgleLutBltCtl +setNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length) +{ + NgleLutBltCtl lutBltCtl; + + /* set enable, zero reserved fields */ + lutBltCtl.all = 0x80000000; + lutBltCtl.fields.length = length; + + switch (fb->id) + { + case S9000_ID_A1439A: /* CRX24 */ + if (fb->var.bits_per_pixel == 8) { + lutBltCtl.fields.lutType = NGLE_CMAP_OVERLAY_TYPE; + lutBltCtl.fields.lutOffset = 0; + } else { + lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE; + lutBltCtl.fields.lutOffset = 0 * 256; + } + break; + + case S9000_ID_ARTIST: + lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE; + lutBltCtl.fields.lutOffset = 0 * 256; + break; + + default: + lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE; + lutBltCtl.fields.lutOffset = 0; + break; + } + + /* Offset points to start of LUT. Adjust for within LUT */ + lutBltCtl.fields.lutOffset += offsetWithinLut; + + return lutBltCtl; +} +#endif + +static NgleLutBltCtl +setHyperLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length) +{ + NgleLutBltCtl lutBltCtl; + + /* set enable, zero reserved fields */ + lutBltCtl.all = 0x80000000; + + lutBltCtl.fields.length = length; + lutBltCtl.fields.lutType = HYPER_CMAP_TYPE; + + /* Expect lutIndex to be 0 or 1 for image cmaps, 2 or 3 for overlay cmaps */ + if (fb->info.var.bits_per_pixel == 8) + lutBltCtl.fields.lutOffset = 2 * 256; + else + lutBltCtl.fields.lutOffset = 0 * 256; + + /* Offset points to start of LUT. Adjust for within LUT */ + lutBltCtl.fields.lutOffset += offsetWithinLut; + + return lutBltCtl; +} + + +static void hyperUndoITE(struct stifb_info *fb) +{ + int nFreeFifoSlots = 0; + u32 fbAddr; + + NGLE_LOCK(fb); + + GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1); + WRITE_WORD(0xffffffff, fb, REG_32); + + /* Write overlay transparency mask so only entry 255 is transparent */ + + /* Hardware setup for full-depth write to "magic" location */ + GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7); + NGLE_QUICK_SET_DST_BM_ACCESS(fb, + BA(IndexedDcd, Otc04, Ots08, AddrLong, + BAJustPoint(0), BINovly, BAIndexBase(0))); + NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, + IBOvals(RopSrc, MaskAddrOffset(0), + BitmapExtent08, StaticReg(0), + DataDynamic, MaskOtc, BGx(0), FGx(0))); + + /* Now prepare to write to the "magic" location */ + fbAddr = NGLE_LONG_FB_ADDRESS(0, 1532, 0); + NGLE_BINC_SET_DSTADDR(fb, fbAddr); + NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffff); + NGLE_BINC_SET_DSTMASK(fb, 0xffffffff); + + /* Finally, write a zero to clear the mask */ + NGLE_BINC_WRITE32(fb, 0); + + NGLE_UNLOCK(fb); +} + +static void +ngleDepth8_ClearImagePlanes(struct stifb_info *fb) { + /* FIXME! */ +} + +static void +ngleDepth24_ClearImagePlanes(struct stifb_info *fb) +{ + /* FIXME! */ } static void -sti_set_par(const void *par, struct fb_info_gen *info) +ngleResetAttrPlanes(struct stifb_info *fb, unsigned int ctlPlaneReg) +{ + int nFreeFifoSlots = 0; + u32 packed_dst; + u32 packed_len; + + NGLE_LOCK(fb); + + GET_FIFO_SLOTS(fb, nFreeFifoSlots, 4); + NGLE_QUICK_SET_DST_BM_ACCESS(fb, + BA(IndexedDcd, Otc32, OtsIndirect, + AddrLong, BAJustPoint(0), + BINattr, BAIndexBase(0))); + NGLE_QUICK_SET_CTL_PLN_REG(fb, ctlPlaneReg); + NGLE_SET_TRANSFERDATA(fb, 0xffffffff); + + NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, + IBOvals(RopSrc, MaskAddrOffset(0), + BitmapExtent08, StaticReg(1), + DataDynamic, MaskOtc, + BGx(0), FGx(0))); + packed_dst = 0; + packed_len = (fb->info.var.xres << 16) | fb->info.var.yres; + GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2); + NGLE_SET_DSTXY(fb, packed_dst); + SET_LENXY_START_RECFILL(fb, packed_len); + + /* + * In order to work around an ELK hardware problem (Buffy doesn't + * always flush it's buffers when writing to the attribute + * planes), at least 4 pixels must be written to the attribute + * planes starting at (X == 1280) and (Y != to the last Y written + * by BIF): + */ + + if (fb->id == S9000_ID_A1659A) { /* ELK_DEVICE_ID */ + /* It's safe to use scanline zero: */ + packed_dst = (1280 << 16); + GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2); + NGLE_SET_DSTXY(fb, packed_dst); + packed_len = (4 << 16) | 1; + SET_LENXY_START_RECFILL(fb, packed_len); + } /* ELK Hardware Kludge */ + + /**** Finally, set the Control Plane Register back to zero: ****/ + GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1); + NGLE_QUICK_SET_CTL_PLN_REG(fb, 0); + + NGLE_UNLOCK(fb); +} + +static void +ngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data) +{ + int nFreeFifoSlots = 0; + u32 packed_dst; + u32 packed_len; + + NGLE_LOCK(fb); + + /* Hardware setup */ + GET_FIFO_SLOTS(fb, nFreeFifoSlots, 8); + NGLE_QUICK_SET_DST_BM_ACCESS(fb, + BA(IndexedDcd, Otc04, Ots08, AddrLong, + BAJustPoint(0), BINovly, BAIndexBase(0))); + + NGLE_SET_TRANSFERDATA(fb, 0xffffffff); /* Write foreground color */ + + NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, data); + NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, mask); + + packed_dst = 0; + packed_len = (fb->info.var.xres << 16) | fb->info.var.yres; + NGLE_SET_DSTXY(fb, packed_dst); + + /* Write zeroes to overlay planes */ + NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, + IBOvals(RopSrc, MaskAddrOffset(0), + BitmapExtent08, StaticReg(0), + DataDynamic, MaskOtc, BGx(0), FGx(0))); + + SET_LENXY_START_RECFILL(fb, packed_len); + + NGLE_UNLOCK(fb); +} + +static void +hyperResetPlanes(struct stifb_info *fb, int enable) +{ + unsigned int controlPlaneReg; + + NGLE_LOCK(fb); + + if (IS_24_DEVICE(fb)) + if (fb->info.var.bits_per_pixel == 32) + controlPlaneReg = 0x04000F00; + else + controlPlaneReg = 0x00000F00; /* 0x00000800 should be enought, but lets clear all 4 bits */ + else + controlPlaneReg = 0x00000F00; /* 0x00000100 should be enought, but lets clear all 4 bits */ + + switch (enable) { + case 1: /* ENABLE */ + /* clear screen */ + if (IS_24_DEVICE(fb)) + ngleDepth24_ClearImagePlanes(fb); + else + ngleDepth8_ClearImagePlanes(fb); + + /* Paint attribute planes for default case. + * On Hyperdrive, this means all windows using overlay cmap 0. */ + ngleResetAttrPlanes(fb, controlPlaneReg); + + /* clear overlay planes */ + ngleClearOverlayPlanes(fb, 0xff, 255); + + /************************************************** + ** Also need to counteract ITE settings + **************************************************/ + hyperUndoITE(fb); + break; + + case 0: /* DISABLE */ + /* clear screen */ + if (IS_24_DEVICE(fb)) + ngleDepth24_ClearImagePlanes(fb); + else + ngleDepth8_ClearImagePlanes(fb); + ngleResetAttrPlanes(fb, controlPlaneReg); + ngleClearOverlayPlanes(fb, 0xff, 0); + break; + + case -1: /* RESET */ + hyperUndoITE(fb); + ngleResetAttrPlanes(fb, controlPlaneReg); + break; + } + + NGLE_UNLOCK(fb); +} + +/* Return pointer to in-memory structure holding ELK device-dependent ROM values. */ + +static void +ngleGetDeviceRomData(struct stifb_info *fb) { +#if 0 +XXX: FIXME: !!! + int *pBytePerLongDevDepData;/* data byte == LSB */ + int *pRomTable; + NgleDevRomData *pPackedDevRomData; + int sizePackedDevRomData = sizeof(*pPackedDevRomData); + char *pCard8; + int i; + char *mapOrigin = NULL; + + int romTableIdx; + + pPackedDevRomData = fb->ngle_rom; + + SETUP_HW(fb); + if (fb->id == S9000_ID_ARTIST) { + pPackedDevRomData->cursor_pipeline_delay = 4; + pPackedDevRomData->video_interleaves = 4; + } else { + /* Get pointer to unpacked byte/long data in ROM */ + pBytePerLongDevDepData = fb->sti->regions[NGLEDEVDEPROM_CRT_REGION]; + + /* Tomcat supports several resolutions: 1280x1024, 1024x768, 640x480 */ + if (fb->id == S9000_ID_TOMCAT) + { + /* jump to the correct ROM table */ + GET_ROMTABLE_INDEX(romTableIdx); + while (romTableIdx > 0) + { + pCard8 = (Card8 *) pPackedDevRomData; + pRomTable = pBytePerLongDevDepData; + /* Pack every fourth byte from ROM into structure */ + for (i = 0; i < sizePackedDevRomData; i++) + { + *pCard8++ = (Card8) (*pRomTable++); + } + + pBytePerLongDevDepData = (Card32 *) + ((Card8 *) pBytePerLongDevDepData + + pPackedDevRomData->sizeof_ngle_data); + + romTableIdx--; + } + } + + pCard8 = (Card8 *) pPackedDevRomData; + + /* Pack every fourth byte from ROM into structure */ + for (i = 0; i < sizePackedDevRomData; i++) + { + *pCard8++ = (Card8) (*pBytePerLongDevDepData++); + } + } + + SETUP_FB(fb); +#endif +} + + +#define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES 4 +#define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE 8 +#define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE 10 +#define HYPERBOWL_MODE2_8_24 15 + +/* HCRX specific boot-time initialization */ +static void __init +SETUP_HCRX(struct stifb_info *fb) +{ + int hyperbowl; + int nFreeFifoSlots = 0; + + if (fb->id != S9000_ID_HCRX) + return; + + /* Initialize Hyperbowl registers */ + GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7); + + if (IS_24_DEVICE(fb)) { + hyperbowl = (fb->info.var.bits_per_pixel == 32) ? + HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE : + HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE; + + /* First write to Hyperbowl must happen twice (bug) */ + WRITE_WORD(hyperbowl, fb, REG_40); + WRITE_WORD(hyperbowl, fb, REG_40); + + WRITE_WORD(HYPERBOWL_MODE2_8_24, fb, REG_39); + + WRITE_WORD(0x014c0148, fb, REG_42); /* Set lut 0 to be the direct color */ + WRITE_WORD(0x404c4048, fb, REG_43); + WRITE_WORD(0x034c0348, fb, REG_44); + WRITE_WORD(0x444c4448, fb, REG_45); + } else { + hyperbowl = HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES; + + /* First write to Hyperbowl must happen twice (bug) */ + WRITE_WORD(hyperbowl, fb, REG_40); + WRITE_WORD(hyperbowl, fb, REG_40); + + WRITE_WORD(0x00000000, fb, REG_42); + WRITE_WORD(0x00000000, fb, REG_43); + WRITE_WORD(0x00000000, fb, REG_44); + WRITE_WORD(0x444c4048, fb, REG_45); + } } + +/* ------------------- driver specific functions --------------------------- */ + + static int -sti_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, struct fb_info *info) +stifb_setcolreg(u_int regno, u_int red, u_int green, + u_int blue, u_int transp, struct fb_info *info) { + struct stifb_info *fb = (struct stifb_info *) info; + u32 color; + + if (regno >= 256) /* no. of hw registers */ + return 1; + + START_IMAGE_COLORMAP_ACCESS(fb); + + if (fb->info.var.grayscale) { + /* gray = 0.30*R + 0.59*G + 0.11*B */ + color = ((red * 77) + + (green * 151) + + (blue * 28)) >> 8; + } else { + color = ((red << 16) | + (green << 8) | + (blue)); + } + + WRITE_IMAGE_COLOR(fb, regno, 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); + } + return 0; } +#if 0 static void -sti_set_disp(const void *par, struct display *disp, - struct fb_info_gen *info) +stifb_loadcmap(struct stifb_info *fb) { - disp->dispsw = &fbcon_sti; + 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 void -sti_detect(void) +static int +stifb_blank(int blank_mode, struct fb_info *info) { + struct stifb_info *fb = (struct stifb_info *) info; + int enable = (blank_mode == 0) ? ENABLE : DISABLE; + + switch (fb->id) { + case S9000_ID_A1439A: + CRX24_ENABLE_DISABLE_DISPLAY(fb, enable); + break; + case CRT_ID_VISUALIZE_EG: + case S9000_ID_ARTIST: + ARTIST_ENABLE_DISABLE_DISPLAY(fb, enable); + break; + case S9000_ID_HCRX: + HYPER_ENABLE_DISABLE_DISPLAY(fb, enable); + break; + case S9000_ID_A1659A:; /* fall through */ + case S9000_ID_TIMBER:; + case CRX24_OVERLAY_PLANES:; + default: + ENABLE_DISABLE_DISPLAY(fb, enable); + break; + } + + SETUP_FB(fb); + return 0; +} + +static void __init +stifb_init_display(struct stifb_info *fb) +{ + int id = fb->id; + + SETUP_FB(fb); + + /* HCRX specific initialization */ + SETUP_HCRX(fb); + + /* + if (id == S9000_ID_HCRX) + hyperInitSprite(fb); + else + ngleInitSprite(fb); + */ + + /* Initialize the image planes. */ + switch (id) { + case S9000_ID_HCRX: + hyperResetPlanes(fb, ENABLE); + break; + case S9000_ID_A1439A: + rattlerSetupPlanes(fb); + break; + case S9000_ID_A1659A: + case S9000_ID_ARTIST: + case CRT_ID_VISUALIZE_EG: + elkSetupPlanes(fb); + break; + } + + /* Clear attribute planes on non HCRX devices. */ + switch (id) { + case S9000_ID_A1659A: + case S9000_ID_A1439A: + if (fb->info.var.bits_per_pixel == 32) + ngleSetupAttrPlanes(fb, BUFF1_CMAP3); + else { + ngleSetupAttrPlanes(fb, BUFF1_CMAP0); + } + if (id == S9000_ID_A1439A) + ngleClearOverlayPlanes(fb, 0xff, 0); + break; + case S9000_ID_ARTIST: + case CRT_ID_VISUALIZE_EG: + if (fb->info.var.bits_per_pixel == 32) + ngleSetupAttrPlanes(fb, BUFF1_CMAP3); + else { + ngleSetupAttrPlanes(fb, ARTIST_CMAP0); + } + break; + } + stifb_blank(0, (struct fb_info *)fb); /* 0=enable screen */ + + SETUP_FB(fb); } + /* ------------ Interfaces to hardware functions ------------ */ -struct fbgen_hwswitch sti_switch = { - .detect = sti_detect, - .encode_fix = sti_encode_fix, - .decode_var = sti_decode_var, - .encode_var = sti_encode_var, - .get_par = sti_get_par, - .set_par = sti_set_par, - .getcolreg = sti_getcolreg, - .set_disp = sti_set_disp -}; +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, + */ +}; -/* ------------ Hardware Independent Functions ------------ */ /* * Initialization */ int __init -stifb_init(void) +stifb_init_fb(struct sti_struct *sti, int force_bpp) { - printk("searching for word mode STI ROMs\n"); - /* XXX: in the future this will return a list of ROMs */ - if ((fb_info.sti = sti_init_roms()) == NULL) - return -ENXIO; - - fb_info.gen.info.node = NODEV; - fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT; - fb_info.gen.info.fbops = &stifb_ops; - fb_info.gen.info.disp = &disp; - fb_info.gen.info.changevar = NULL; - fb_info.gen.info.switch_con = &fbgen_switch; - fb_info.gen.info.updatevar = &fbgen_update_var; - strcpy(fb_info.gen.info.modename, "STI Generic"); - fb_info.gen.fbhw = &sti_switch; - fb_info.gen.fbhw->detect(); - fb_info.gen.info.screen_base = - (void *) PTR_STI(fb_info.sti->glob_cfg)->region_ptrs[1]; - /* This should give a reasonable default video mode */ - fbgen_get_var(&disp.var, -1, &fb_info.gen.info); - fbgen_do_set_var(&disp.var, 1, &fb_info.gen); - fbgen_set_disp(-1, &fb_info.gen); - do_install_cmap(0, &fb_info.gen); - pdc_console_die(); - if (register_framebuffer(&fb_info.gen.info) < 0) - return -EINVAL; - - printk(KERN_INFO "fb%d: %s frame buffer device\n", - GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename); + 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; + char *dev_name; + int bpp, xres, yres; + + fb = kmalloc(sizeof(*fb), GFP_ATOMIC); + if (!fb) { + printk(KERN_ERR "stifb: Could not allocate stifb structure\n"); + return -ENODEV; + } + + info = &fb->info; + + /* set struct to a known state */ + 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 */ + fb->id = fb->sti->graphics_id[0]; + + /* only supported cards are allowed */ + switch (fb->id) { + case S9000_ID_ARTIST: + case S9000_ID_HCRX: + case S9000_ID_TIMBER: + case S9000_ID_A1659A: + case S9000_ID_A1439A: + case CRT_ID_VISUALIZE_EG: + break; + default: + printk(KERN_WARNING "stifb: Unsupported gfx card id 0x%08x\n", + fb->id); + goto out_err1; + } + + /* default to 8 bpp on most graphic chips */ + bpp = 8; + xres = sti_onscreen_x(fb->sti); + yres = sti_onscreen_y(fb->sti); + + ngleGetDeviceRomData(fb); + + /* get (virtual) io region base addr */ + fix->mmio_start = REGION_BASE(fb,2); + fix->mmio_len = 0x400000; + + /* Reject any device not in the NGLE family */ + switch (fb->id) { + case S9000_ID_A1659A: /* CRX/A1659A */ + break; + case S9000_ID_ELM: /* GRX, grayscale but else same as A1659A */ + var->grayscale = 1; + fb->id = S9000_ID_A1659A; + break; + case S9000_ID_TIMBER: /* HP9000/710 Any (may be a grayscale device) */ + dev_name = fb->sti->outptr.dev_name; + if (strstr(dev_name, "GRAYSCALE") || + strstr(dev_name, "Grayscale") || + strstr(dev_name, "grayscale")) + var->grayscale = 1; + break; + case S9000_ID_TOMCAT: /* Dual CRX, behaves else like a CRX */ + /* FIXME: TomCat supports two heads: + * fb.iobase = REGION_BASE(fb_info,3); + * fb.screen_base = (void*) REGION_BASE(fb_info,2); + * for now we only support the left one ! */ + xres = fb->ngle_rom.x_size_visible; + yres = fb->ngle_rom.y_size_visible; + fb->id = S9000_ID_A1659A; + break; + case S9000_ID_A1439A: /* CRX24/A1439A */ + bpp = 32; + break; + case S9000_ID_HCRX: /* Hyperdrive/HCRX */ + memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom)); + if ((fb->sti->regions_phys[0] & 0xfc000000) == + (fb->sti->regions_phys[2] & 0xfc000000)) + sti_rom_address = fb->sti->regions_phys[0]; + else + sti_rom_address = fb->sti->regions_phys[1]; +#ifdef __LP64__ + sti_rom_address |= 0xffffffff00000000; +#endif + fb->deviceSpecificConfig = __raw_readl(sti_rom_address); + if (IS_24_DEVICE(fb)) { + if (force_bpp == 8 || force_bpp == 32) + bpp = force_bpp; + else + bpp = 32; + } else + bpp = 8; + READ_WORD(fb, REG_15); + SETUP_HW(fb); + break; + case CRT_ID_VISUALIZE_EG: + case S9000_ID_ARTIST: /* Artist */ + break; + default: +#ifdef FALLBACK_TO_1BPP + printk(KERN_WARNING + "stifb: Unsupported graphics card (id=0x%08x) " + "- now trying 1bpp mode instead\n", + fb->id); + bpp = 1; /* default to 1 bpp */ + break; +#else + printk(KERN_WARNING + "stifb: Unsupported graphics card (id=0x%08x) " + "- skipping.\n", + fb->id); + goto out_err1; +#endif + } + + + /* get framebuffer pysical and virtual base addr & len (64bit ready) */ + fix->smem_start = fb->sti->regions_phys[1] | 0xffffffff00000000; + fix->smem_len = fb->sti->regions[1].region_desc.length * 4096; + + fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8; + if (!fix->line_length) + fix->line_length = 2048; /* default */ + fix->accel = FB_ACCEL_NONE; + + switch (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; + } + + var->xres = var->xres_virtual = xres; + var->yres = var->yres_virtual = yres; + var->bits_per_pixel = bpp; + + strcpy(info->modename, "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", + fix->smem_start, fix->smem_start+fix->smem_len); + goto out_err1; + } + + if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) { + printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n", + fix->mmio_start, fix->mmio_start+fix->mmio_len); + goto out_err2; + } + + if (register_framebuffer(&fb->info) < 0) + goto out_err3; + + 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, + fb->id, + fix->mmio_start); return 0; -} - /* - * Cleanup - */ +out_err3: + release_mem_region(fix->mmio_start, fix->mmio_len); +out_err2: + release_mem_region(fix->smem_start, fix->smem_len); +out_err1: + kfree(fb); + return -ENXIO; +} -void -stifb_cleanup(struct fb_info *info) +int __init +stifb_init(void) { - printk("stifb_cleanup: you're on crack\n"); + struct sti_struct *sti; + int i; + + + if (sti_init_roms() == NULL) + return -ENXIO; /* no STI cards available */ + + for (i = 0; i < MAX_STI_ROMS; i++) { + sti = sti_get_rom(i); + if (sti) + stifb_init_fb(sti, stifb_force_bpp[i]); + else + break; + } + return 0; } +/* + * Cleanup + */ + +static void __exit +stifb_cleanup(void) +{ + // unregister_framebuffer(); +} int __init stifb_setup(char *options) { - /* XXX: we should take the resolution, bpp as command line arguments. */ + int i; + + if (!options || !*options) + return 0; + + if (strncmp(options, "bpp", 3) == 0) { + options += 3; + for (i = 0; i < MAX_STI_ROMS; i++) { + if (*options++ == ':') + stifb_force_bpp[i] = simple_strtoul(options, &options, 10); + else + break; + } + } return 0; } +__setup("stifb=", stifb_setup); -/* ------------------------------------------------------------------------- */ +#ifdef MODULE +module_init(stifb_init); +#endif +module_exit(stifb_cleanup); +MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); +MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(bpp, "i"); +MODULE_PARM_DESC(mem, "Bits per pixel (default: 8)"); -static struct fb_ops stifb_ops = { - .owner = THIS_MODULE, - .fb_get_fix = fbgen_get_fix, - .fb_get_var = fbgen_get_var, - .fb_set_var = fbgen_set_var, - .fb_get_cmap = fbgen_get_cmap, - .fb_set_cmap = gen_set_cmap, - .fb_pan_display =fbgen_pan_display, - .fb_blank = fbgen_blank, -}; diff --git a/drivers/video/sun3fb.c b/drivers/video/sun3fb.c index a278639af752..57b37fa4084b 100644 --- a/drivers/video/sun3fb.c +++ b/drivers/video/sun3fb.c @@ -646,7 +646,7 @@ sizechange: kfree(fb); return -EINVAL; } - printk("fb%d: %s\n", GET_FB_IDX(fb->info.node), p); + printk("fb%d: %s\n", minor(fb->info.node), p); return 0; } diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index bde930eb65f3..7a828918c948 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -77,7 +77,6 @@ #include <linux/spinlock.h> #include <video/tdfx.h> -#include <video/fbcon.h> #undef TDFXFB_DEBUG #ifdef TDFXFB_DEBUG @@ -143,10 +142,10 @@ static struct pci_device_id tdfxfb_id_table[] __devinitdata = { }; static struct pci_driver tdfxfb_driver = { - .name = "tdfxfb", - .id_table = tdfxfb_id_table, - .probe = tdfxfb_probe, - .remove = __devexit_p(tdfxfb_remove), + .name = "tdfxfb", + .id_table = tdfxfb_id_table, + .probe = tdfxfb_probe, + .remove = __devexit_p(tdfxfb_remove), }; MODULE_DEVICE_TABLE(pci, tdfxfb_id_table); @@ -162,16 +161,14 @@ static int tdfxfb_set_par(struct fb_info *info); static int tdfxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int tdfxfb_blank(int blank, struct fb_info *info); -static int tdfxfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info); +static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); 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 struct fb_ops tdfxfb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_check_var = tdfxfb_check_var, .fb_set_par = tdfxfb_set_par, .fb_setcolreg = tdfxfb_setcolreg, @@ -180,20 +177,20 @@ static struct fb_ops tdfxfb_ops = { .fb_fillrect = tdfxfb_fillrect, .fb_copyarea = tdfxfb_copyarea, .fb_imageblit = tdfxfb_imageblit, + .fb_sync = banshee_wait_idle, + .fb_cursor = soft_cursor, }; /* * do_xxx: Hardware-specific functions */ static u32 do_calc_pll(int freq, int *freq_out); -static void do_write_regs(struct banshee_reg *reg); -static unsigned long do_lfb_size(unsigned short); +static void do_write_regs(struct fb_info *info, struct banshee_reg *reg); +static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short); /* * Driver data */ -static struct tdfx_par default_par; - static int nopan = 0; static int nowrap = 1; // not implemented (yet) static int inverse = 0; @@ -204,132 +201,133 @@ static char *mode_option __initdata = NULL; * ------------------------------------------------------------------------- */ #ifdef VGA_REG_IO -static inline u8 vga_inb(u32 reg) { return inb(reg); } -static inline u16 vga_inw(u32 reg) { return inw(reg); } -static inline u16 vga_inl(u32 reg) { return inl(reg); } +static inline u8 vga_inb(struct tdfx_par *par, u32 reg) { return inb(reg); } +static inline u16 vga_inw(struct tdfx_par *par, u32 reg) { return inw(reg); } +static inline u16 vga_inl(struct tdfx_par *par, u32 reg) { return inl(reg); } -static inline void vga_outb(u32 reg, u8 val) { outb(val, reg); } -static inline void vga_outw(u32 reg, u16 val) { outw(val, reg); } -static inline void vga_outl(u32 reg, u32 val) { outl(val, reg); } +static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val) { outb(val, reg); } +static inline void vga_outw(struct tdfx_par *par, u32 reg, u16 val) { outw(val, reg); } +static inline void vga_outl(struct tdfx_par *par, u32 reg, u32 val) { outl(val, reg); } #else -static inline u8 vga_inb(u32 reg) { - return inb(default_par.iobase + reg - 0x300); +static inline u8 vga_inb(struct tdfx_par *par, u32 reg) { + return inb(par->iobase + reg - 0x300); } -static inline u16 vga_inw(u32 reg) { - return inw(default_par.iobase + reg - 0x300); +static inline u16 vga_inw(struct tdfx_par *par, u32 reg) { + return inw(par->iobase + reg - 0x300); } -static inline u16 vga_inl(u32 reg) { - return inl(default_par.iobase + reg - 0x300); +static inline u16 vga_inl(struct tdfx_par *par, u32 reg) { + return inl(par->iobase + reg - 0x300); } -static inline void vga_outb(u32 reg, u8 val) { - outb(val, default_par.iobase + reg - 0x300); +static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val) { + outb(val, par->iobase + reg - 0x300); } -static inline void vga_outw(u32 reg, u16 val) { - outw(val, default_par.iobase + reg - 0x300); +static inline void vga_outw(struct tdfx_par *par, u32 reg, u16 val) { + outw(val, par->iobase + reg - 0x300); } -static inline void vga_outl(u32 reg, u32 val) { - outl(val, default_par.iobase + reg - 0x300); +static inline void vga_outl(struct tdfx_par *par, u32 reg, u32 val) { + outl(val, par->iobase + reg - 0x300); } #endif -static inline void gra_outb(u32 idx, u8 val) { - vga_outb(GRA_I, idx); vga_outb(GRA_D, val); +static inline void gra_outb(struct tdfx_par *par, u32 idx, u8 val) { + vga_outb(par, GRA_I, idx); vga_outb(par, GRA_D, val); } -static inline u8 gra_inb(u32 idx) { - vga_outb(GRA_I, idx); return vga_inb(GRA_D); +static inline u8 gra_inb(struct tdfx_par *par, u32 idx) { + vga_outb(par, GRA_I, idx); return vga_inb(par, GRA_D); } -static inline void seq_outb(u32 idx, u8 val) { - vga_outb(SEQ_I, idx); vga_outb(SEQ_D, val); +static inline void seq_outb(struct tdfx_par *par, u32 idx, u8 val) { + vga_outb(par, SEQ_I, idx); vga_outb(par, SEQ_D, val); } -static inline u8 seq_inb(u32 idx) { - vga_outb(SEQ_I, idx); return vga_inb(SEQ_D); +static inline u8 seq_inb(struct tdfx_par *par, u32 idx) { + vga_outb(par, SEQ_I, idx); return vga_inb(par, SEQ_D); } -static inline void crt_outb(u32 idx, u8 val) { - vga_outb(CRT_I, idx); vga_outb(CRT_D, val); +static inline void crt_outb(struct tdfx_par *par, u32 idx, u8 val) { + vga_outb(par, CRT_I, idx); vga_outb(par, CRT_D, val); } -static inline u8 crt_inb(u32 idx) { - vga_outb(CRT_I, idx); return vga_inb(CRT_D); +static inline u8 crt_inb(struct tdfx_par *par, u32 idx) { + vga_outb(par, CRT_I, idx); return vga_inb(par, CRT_D); } -static inline void att_outb(u32 idx, u8 val) +static inline void att_outb(struct tdfx_par *par, u32 idx, u8 val) { unsigned char tmp; - tmp = vga_inb(IS1_R); - vga_outb(ATT_IW, idx); - vga_outb(ATT_IW, val); + tmp = vga_inb(par, IS1_R); + vga_outb(par, ATT_IW, idx); + vga_outb(par, ATT_IW, val); } -static inline u8 att_inb(u32 idx) +static inline u8 att_inb(struct tdfx_par *par, u32 idx) { unsigned char tmp; - tmp = vga_inb(IS1_R); - vga_outb(ATT_IW, idx); - return vga_inb(ATT_IW); + tmp = vga_inb(par, IS1_R); + vga_outb(par, ATT_IW, idx); + return vga_inb(par, ATT_IW); } -static inline void vga_disable_video(void) +static inline void vga_disable_video(struct tdfx_par *par) { unsigned char s; - s = seq_inb(0x01) | 0x20; - seq_outb(0x00, 0x01); - seq_outb(0x01, s); - seq_outb(0x00, 0x03); + s = seq_inb(par, 0x01) | 0x20; + seq_outb(par, 0x00, 0x01); + seq_outb(par, 0x01, s); + seq_outb(par, 0x00, 0x03); } -static inline void vga_enable_video(void) +static inline void vga_enable_video(struct tdfx_par *par) { unsigned char s; - s = seq_inb(0x01) & 0xdf; - seq_outb(0x00, 0x01); - seq_outb(0x01, s); - seq_outb(0x00, 0x03); + s = seq_inb(par, 0x01) & 0xdf; + seq_outb(par, 0x00, 0x01); + seq_outb(par, 0x01, s); + seq_outb(par, 0x00, 0x03); } -static inline void vga_disable_palette(void) +static inline void vga_disable_palette(struct tdfx_par *par) { - vga_inb(IS1_R); - vga_outb(ATT_IW, 0x00); + vga_inb(par, IS1_R); + vga_outb(par, ATT_IW, 0x00); } -static inline void vga_enable_palette(void) +static inline void vga_enable_palette(struct tdfx_par *par) { - vga_inb(IS1_R); - vga_outb(ATT_IW, 0x20); + vga_inb(par, IS1_R); + vga_outb(par, ATT_IW, 0x20); } -static inline u32 tdfx_inl(unsigned int reg) +static inline u32 tdfx_inl(struct tdfx_par *par, unsigned int reg) { - return readl(default_par.regbase_virt + reg); + return readl(par->regbase_virt + reg); } -static inline void tdfx_outl(unsigned int reg, u32 val) +static inline void tdfx_outl(struct tdfx_par *par, unsigned int reg, u32 val) { - writel(val, default_par.regbase_virt + reg); + writel(val, par->regbase_virt + reg); } -static inline void banshee_make_room(int size) +static inline void banshee_make_room(struct tdfx_par *par, int size) { - while((tdfx_inl(STATUS) & 0x1f) < size); + while((tdfx_inl(par, STATUS) & 0x1f) < size); } -static inline void banshee_wait_idle(void) +static inline void banshee_wait_idle(struct fb_info *info) { + struct tdfx_par *par = (struct tdfx_par *) info->par; int i = 0; - banshee_make_room(1); - tdfx_outl(COMMAND_3D, COMMAND_3D_NOP); + banshee_make_room(par, 1); + tdfx_outl(par, COMMAND_3D, COMMAND_3D_NOP); while(1) { - i = (tdfx_inl(STATUS) & STATUS_BUSY) ? 0 : i + 1; + i = (tdfx_inl(par, STATUS) & STATUS_BUSY) ? 0 : i + 1; if(i == 3) break; } } @@ -337,11 +335,11 @@ static inline void banshee_wait_idle(void) /* * Set the color of a palette entry in 8bpp mode */ -static inline void do_setpalentry(unsigned regno, u32 c) +static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c) { - banshee_make_room(2); - tdfx_outl(DACADDR, regno); - tdfx_outl(DACDATA, c); + banshee_make_room(par, 2); + tdfx_outl(par, DACADDR, regno); + tdfx_outl(par, DACDATA, c); } static u32 do_calc_pll(int freq, int* freq_out) @@ -373,71 +371,72 @@ static u32 do_calc_pll(int freq, int* freq_out) return (n << 8) | (m << 2) | k; } -static void do_write_regs(struct banshee_reg* reg) +static void do_write_regs(struct fb_info *info, struct banshee_reg* reg) { + struct tdfx_par *par = (struct tdfx_par *) info->par; int i; - banshee_wait_idle(); + banshee_wait_idle(info); - tdfx_outl(MISCINIT1, tdfx_inl(MISCINIT1) | 0x01); + tdfx_outl(par, MISCINIT1, tdfx_inl(par, MISCINIT1) | 0x01); - crt_outb(0x11, crt_inb(0x11) & 0x7f); /* CRT unprotect */ + crt_outb(par, 0x11, crt_inb(par, 0x11) & 0x7f); /* CRT unprotect */ - banshee_make_room(3); - tdfx_outl(VGAINIT1, reg->vgainit1 & 0x001FFFFF); - tdfx_outl(VIDPROCCFG, reg->vidcfg & ~0x00000001); + banshee_make_room(par, 3); + tdfx_outl(par, VGAINIT1, reg->vgainit1 & 0x001FFFFF); + tdfx_outl(par, VIDPROCCFG, reg->vidcfg & ~0x00000001); #if 0 - tdfx_outl(PLLCTRL1, reg->mempll); - tdfx_outl(PLLCTRL2, reg->gfxpll); + tdfx_outl(par, PLLCTRL1, reg->mempll); + tdfx_outl(par, PLLCTRL2, reg->gfxpll); #endif - tdfx_outl(PLLCTRL0, reg->vidpll); + tdfx_outl(par, PLLCTRL0, reg->vidpll); - vga_outb(MISC_W, reg->misc[0x00] | 0x01); + vga_outb(par, MISC_W, reg->misc[0x00] | 0x01); for (i = 0; i < 5; i++) - seq_outb(i, reg->seq[i]); + seq_outb(par, i, reg->seq[i]); for (i = 0; i < 25; i++) - crt_outb(i, reg->crt[i]); + crt_outb(par, i, reg->crt[i]); for (i = 0; i < 9; i++) - gra_outb(i, reg->gra[i]); + gra_outb(par, i, reg->gra[i]); for (i = 0; i < 21; i++) - att_outb(i, reg->att[i]); + att_outb(par, i, reg->att[i]); - crt_outb(0x1a, reg->ext[0]); - crt_outb(0x1b, reg->ext[1]); + crt_outb(par, 0x1a, reg->ext[0]); + crt_outb(par, 0x1b, reg->ext[1]); - vga_enable_palette(); - vga_enable_video(); + vga_enable_palette(par); + vga_enable_video(par); - banshee_make_room(11); - tdfx_outl(VGAINIT0, reg->vgainit0); - tdfx_outl(DACMODE, reg->dacmode); - tdfx_outl(VIDDESKSTRIDE, reg->stride); - tdfx_outl(HWCURPATADDR, 0); + banshee_make_room(par, 11); + tdfx_outl(par, VGAINIT0, reg->vgainit0); + tdfx_outl(par, DACMODE, reg->dacmode); + tdfx_outl(par, VIDDESKSTRIDE, reg->stride); + tdfx_outl(par, HWCURPATADDR, 0); - tdfx_outl(VIDSCREENSIZE,reg->screensize); - tdfx_outl(VIDDESKSTART, reg->startaddr); - tdfx_outl(VIDPROCCFG, reg->vidcfg); - tdfx_outl(VGAINIT1, reg->vgainit1); - tdfx_outl(MISCINIT0, reg->miscinit0); - - banshee_make_room(8); - tdfx_outl(SRCBASE, reg->srcbase); - tdfx_outl(DSTBASE, reg->dstbase); - tdfx_outl(COMMANDEXTRA_2D, 0); - tdfx_outl(CLIP0MIN, 0); - tdfx_outl(CLIP0MAX, 0x0fff0fff); - tdfx_outl(CLIP1MIN, 0); - tdfx_outl(CLIP1MAX, 0x0fff0fff); - tdfx_outl(SRCXY, 0); - - banshee_wait_idle(); + tdfx_outl(par, VIDSCREENSIZE,reg->screensize); + tdfx_outl(par, VIDDESKSTART, reg->startaddr); + tdfx_outl(par, VIDPROCCFG, reg->vidcfg); + tdfx_outl(par, VGAINIT1, reg->vgainit1); + tdfx_outl(par, MISCINIT0, reg->miscinit0); + + banshee_make_room(par, 8); + tdfx_outl(par, SRCBASE, reg->srcbase); + tdfx_outl(par, DSTBASE, reg->dstbase); + tdfx_outl(par, COMMANDEXTRA_2D, 0); + tdfx_outl(par, CLIP0MIN, 0); + tdfx_outl(par, CLIP0MAX, 0x0fff0fff); + tdfx_outl(par, CLIP1MIN, 0); + tdfx_outl(par, CLIP1MAX, 0x0fff0fff); + tdfx_outl(par, SRCXY, 0); + + banshee_wait_idle(info); } -static unsigned long do_lfb_size(unsigned short dev_id) +static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) { u32 draminit0 = 0; u32 draminit1 = 0; @@ -445,8 +444,8 @@ static unsigned long do_lfb_size(unsigned short dev_id) u32 lfbsize = 0; int sgram_p = 0; - draminit0 = tdfx_inl(DRAMINIT0); - draminit1 = tdfx_inl(DRAMINIT1); + draminit0 = tdfx_inl(par, DRAMINIT0); + draminit1 = tdfx_inl(par, DRAMINIT1); if ((dev_id == PCI_DEVICE_ID_3DFX_BANSHEE) || (dev_id == PCI_DEVICE_ID_3DFX_VOODOO3)) { @@ -467,12 +466,12 @@ static unsigned long do_lfb_size(unsigned short dev_id) lfbsize <<= 20; } /* disable block writes for SDRAM (why?) */ - miscinit1 = tdfx_inl(MISCINIT1); + miscinit1 = tdfx_inl(par, MISCINIT1); miscinit1 |= sgram_p ? 0 : MISCINIT1_2DBLOCK_DIS; miscinit1 |= MISCINIT1_CLUT_INV; - banshee_make_room(1); - tdfx_outl(MISCINIT1, miscinit1); + banshee_make_room(par, 1); + tdfx_outl(par, MISCINIT1, miscinit1); return lfbsize; } @@ -710,7 +709,7 @@ static int tdfxfb_set_par(struct fb_info *info) VGAINIT0_WAKEUP_3C3 | VGAINIT0_ALT_READBACK | VGAINIT0_EXTSHIFTOUT; - reg.vgainit1 = tdfx_inl(VGAINIT1) & 0x1fffff; + reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff; reg.cursloc = 0; @@ -740,7 +739,7 @@ static int tdfxfb_set_par(struct fb_info *info) reg.screensize = info->var.xres | (info->var.yres << 12); reg.vidcfg &= ~VIDCFG_HALF_MODE; - reg.miscinit0 = tdfx_inl(MISCINIT0); + reg.miscinit0 = tdfx_inl(par, MISCINIT0); #if defined(__BIG_ENDIAN) switch (info->var.bits_per_pixel) { @@ -758,8 +757,8 @@ static int tdfxfb_set_par(struct fb_info *info) reg.miscinit0 &= ~(1 << 31); break; } -#endif - do_write_regs(®); +#endif + do_write_regs(par, ®); /* Now change fb_fix_screeninfo according to changes in par */ info->fix.line_length = info->var.xres * ((info->var.bits_per_pixel + 7)>>3); @@ -773,6 +772,7 @@ static int tdfxfb_set_par(struct fb_info *info) static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,unsigned transp,struct fb_info *info) { + struct tdfx_par *par = (struct tdfx_par *) info->par; u32 rgbcol; if (regno >= info->cmap.len) return 1; @@ -782,7 +782,7 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, rgbcol =(((u32)red & 0xff00) << 8) | (((u32)green & 0xff00) << 0) | (((u32)blue & 0xff00) >> 8); - do_setpalentry(regno, rgbcol); + do_setpalentry(par, regno, rgbcol); break; /* Truecolor has no hardware color palettes. */ case FB_VISUAL_TRUECOLOR: @@ -805,9 +805,10 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ static int tdfxfb_blank(int blank, struct fb_info *info) { + struct tdfx_par *par = (struct tdfx_par *) info->par; u32 dacmode, state = 0, vgablank = 0; - dacmode = tdfx_inl(DACMODE); + dacmode = tdfx_inl(par, DACMODE); switch (blank) { case 0: /* Screen: On; HSync: On, VSync: On */ @@ -834,21 +835,22 @@ static int tdfxfb_blank(int blank, struct fb_info *info) dacmode &= ~(BIT(1) | BIT(3)); dacmode |= state; - banshee_make_room(1); - tdfx_outl(DACMODE, dacmode); + banshee_make_room(par, 1); + tdfx_outl(par, DACMODE, dacmode); if (vgablank) - vga_disable_video(); + vga_disable_video(par); else - vga_enable_video(); + vga_enable_video(par); return 0; } /* * Set the starting position of the visible screen to var->yoffset */ -static int tdfxfb_pan_display(struct fb_var_screeninfo *var, int con, +static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { + struct tdfx_par *par = (struct tdfx_par *) info->par; u32 addr; if (nopan || var->xoffset || (var->yoffset > var->yres_virtual)) @@ -857,8 +859,8 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var, int con, return -EINVAL; addr = var->yoffset * info->fix.line_length; - banshee_make_room(1); - tdfx_outl(VIDDESKSTART, addr); + banshee_make_room(par, 1); + tdfx_outl(par, VIDDESKSTART, addr); info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; @@ -870,6 +872,7 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var, int con, */ static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect) { + struct tdfx_par *par = (struct tdfx_par *) info->par; u32 bpp = info->var.bits_per_pixel; u32 stride = info->fix.line_length; u32 fmt= stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); @@ -880,13 +883,13 @@ static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect) else tdfx_rop = TDFX_ROP_XOR; - banshee_make_room(5); - tdfx_outl(DSTFORMAT, fmt); - tdfx_outl(COLORFORE, rect->color); - tdfx_outl(COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24)); - tdfx_outl(DSTSIZE, rect->width | (rect->height << 16)); - tdfx_outl(LAUNCH_2D, rect->dx | (rect->dy << 16)); - banshee_wait_idle(); + banshee_make_room(par, 5); + tdfx_outl(par, DSTFORMAT, fmt); + tdfx_outl(par, COLORFORE, rect->color); + tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24)); + tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16)); + tdfx_outl(par, LAUNCH_2D, rect->dx | (rect->dy << 16)); + banshee_wait_idle(info); } /* @@ -894,6 +897,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) { + struct tdfx_par *par = (struct tdfx_par *) info->par; u32 bpp = info->var.bits_per_pixel; u32 stride = info->fix.line_length; u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24); @@ -912,19 +916,20 @@ static void tdfxfb_copyarea(struct fb_info *info, struct fb_copyarea *area) area->dy += area->height - 1; } - banshee_make_room(6); - - tdfx_outl(SRCFORMAT, fmt); - tdfx_outl(DSTFORMAT, fmt); - tdfx_outl(COMMAND_2D, blitcmd); - tdfx_outl(DSTSIZE, area->width | (area->height << 16)); - tdfx_outl(DSTXY, area->dx | (area->dy << 16)); - tdfx_outl(LAUNCH_2D, area->sx | (area->sy << 16)); - banshee_wait_idle(); + banshee_make_room(par, 6); + + tdfx_outl(par, SRCFORMAT, fmt); + tdfx_outl(par, DSTFORMAT, fmt); + tdfx_outl(par, COMMAND_2D, blitcmd); + tdfx_outl(par, DSTSIZE, area->width | (area->height << 16)); + tdfx_outl(par, DSTXY, area->dx | (area->dy << 16)); + tdfx_outl(par, LAUNCH_2D, area->sx | (area->sy << 16)); + banshee_wait_idle(info); } static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap) { + struct tdfx_par *par = (struct tdfx_par *) info->par; int size = pixmap->height*((pixmap->width*pixmap->depth + 7)>>3); int i, stride = info->fix.line_length; u32 bpp = info->var.bits_per_pixel; @@ -933,25 +938,25 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap) u32 srcfmt; if (pixmap->depth == 1) { - banshee_make_room(8 + ((size + 3) >> 2)); - tdfx_outl(COLORFORE, pixmap->fg_color); - tdfx_outl(COLORBACK, pixmap->bg_color); + banshee_make_room(par, 8 + ((size + 3) >> 2)); + tdfx_outl(par, COLORFORE, pixmap->fg_color); + tdfx_outl(par, COLORBACK, pixmap->bg_color); srcfmt = 0x400000; } else { - banshee_make_room(6 + ((size + 3) >> 2)); - srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000; + //banshee_make_room(par, 6 + ((size + 3) >> 2)); + //srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000; } - tdfx_outl(SRCXY, 0); - tdfx_outl(DSTXY, pixmap->dx | (pixmap->dy << 16)); - tdfx_outl(COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24)); - tdfx_outl(SRCFORMAT, srcfmt); - tdfx_outl(DSTFORMAT, dstfmt); - tdfx_outl(DSTSIZE, pixmap->width | (pixmap->height << 16)); + tdfx_outl(par, SRCXY, 0); + tdfx_outl(par, DSTXY, pixmap->dx | (pixmap->dy << 16)); + tdfx_outl(par, COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24)); + tdfx_outl(par, SRCFORMAT, srcfmt); + tdfx_outl(par, DSTFORMAT, dstfmt); + tdfx_outl(par, DSTSIZE, pixmap->width | (pixmap->height << 16)); /* Send four bytes at a time of data */ for (i = (size >> 2) ; i > 0; i--) { - tdfx_outl(LAUNCH_2D,*(u32*)chardata); + tdfx_outl(par, LAUNCH_2D,*(u32*)chardata); chardata += 4; } @@ -959,11 +964,148 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap) i = size%4; switch (i) { case 0: break; - case 1: tdfx_outl(LAUNCH_2D,*chardata); break; - case 2: tdfx_outl(LAUNCH_2D,*(u16*)chardata); break; - case 3: tdfx_outl(LAUNCH_2D,*(u16*)chardata | ((chardata[3]) << 24)); break; + case 1: tdfx_outl(par, LAUNCH_2D,*chardata); break; + case 2: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata); break; + case 3: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata | ((chardata[3]) << 24)); break; } - banshee_wait_idle(); + banshee_wait_idle(info); +} + +static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + struct tdfx_par *par = (struct tdfx_par *) info->par; + unsigned long flags; + + /* + * If the cursor is not be changed this means either we want the + * current cursor state (if enable is set) or we want to query what + * we can do with the cursor (if enable is not set) + */ + if (!cursor->set) return 0; + + /* Too large of a cursor :-( */ + if (cursor->image.width > 64 || cursor->image.height > 64) + return -ENXIO; + + /* + * If we are going to be changing things we should disable + * the cursor first + */ + if (info->cursor.enable) { + spin_lock_irqsave(&par->DAClock, flags); + info->cursor.enable = 0; + del_timer(&(par->hwcursor.timer)); + tdfx_outl(par, VIDPROCCFG, par->hwcursor.disable); + spin_unlock_irqrestore(&par->DAClock, flags); + } + + /* Disable the Cursor */ + if ((cursor->set && FB_CUR_SETCUR) && !cursor->enable) + return 0; + + /* fix cursor color - XFree86 forgets to restore it properly */ + if (cursor->set && FB_CUR_SETCMAP) { + struct fb_cmap cmap = cursor->image.cmap; + unsigned long bg_color, fg_color; + + cmap.len = 2;/* Voodoo 3+ only support 2 color cursors*/ + fg_color = ((cmap.red[cmap.start] << 16) | + (cmap.green[cmap.start] << 8) | + (cmap.blue[cmap.start])); + bg_color = ((cmap.red[cmap.start+1] << 16) | + (cmap.green[cmap.start+1] << 8) | + (cmap.blue[cmap.start+1])); + fb_copy_cmap(&cmap, &info->cursor.image.cmap, 0); + spin_lock_irqsave(&par->DAClock, flags); + banshee_make_room(par, 2); + tdfx_outl(par, HWCURC0, bg_color); + tdfx_outl(par, HWCURC1, fg_color); + spin_unlock_irqrestore(&par->DAClock, flags); + } + + if (cursor->set && FB_CUR_SETPOS) { + int x, y; + + x = cursor->image.dx; + y = cursor->image.dy; + y -= info->var.yoffset; + info->cursor.image.dx = x; + info->cursor.image.dy = y; + x += 63; + y += 63; + spin_lock_irqsave(&par->DAClock, flags); + banshee_make_room(par, 1); + tdfx_outl(par, HWCURLOC, (y << 16) + x); + spin_unlock_irqrestore(&par->DAClock, flags); + } + + /* Not supported so we fake it */ + if (cursor->set && FB_CUR_SETHOT) { + info->cursor.hot.x = cursor->hot.x; + info->cursor.hot.y = cursor->hot.y; + } + + if (cursor->set && FB_CUR_SETSHAPE) { + /* + * Voodoo 3 and above cards use 2 monochrome cursor patterns. + * The reason is so the card can fetch 8 words at a time + * and are stored on chip for use for the next 8 scanlines. + * This reduces the number of times for access to draw the + * cursor for each screen refresh. + * Each pattern is a bitmap of 64 bit wide and 64 bit high + * (total of 8192 bits or 1024 Kbytes). The two patterns are + * stored in such a way that pattern 0 always resides in the + * lower half (least significant 64 bits) of a 128 bit word + * and pattern 1 the upper half. If you examine the data of + * the cursor image the graphics card uses then from the + * begining you see line one of pattern 0, line one of + * pattern 1, line two of pattern 0, line two of pattern 1, + * etc etc. The linear stride for the cursor is always 16 bytes + * (128 bits) which is the maximum cursor width times two for + * the two monochrome patterns. + */ + u8 *cursorbase = (u8 *) info->cursor.image.data; + char *bitmap = cursor->image.data; + char *mask = cursor->mask; + int i, j, k, h = 0; + + for (i = 0; i < 64; i++) { + if (i < cursor->image.height) { + j = (cursor->image.width + 7) >> 3; + k = 8 - j; + + for (;j > 0; j--) { + /* Pattern 0. Copy the cursor bitmap to it */ + fb_writeb(*bitmap, cursorbase + h); + bitmap++; + /* Pattern 1. Copy the cursor mask to it */ + fb_writeb(*mask, cursorbase + h + 8); + mask++; + h++; + } + for (;k > 0; k--) { + fb_writeb(0, cursorbase + h); + fb_writeb(~0, cursorbase + h + 8); + h++; + } + } else { + fb_writel(0, cursorbase + h); + fb_writel(0, cursorbase + h + 4); + fb_writel(~0, cursorbase + h + 8); + fb_writel(~0, cursorbase + h + 12); + h += 16; + } + } + } + /* Turn the cursor on */ + cursor->enable = 1; + info->cursor = *cursor; + mod_timer(&par->hwcursor.timer, jiffies+HZ/2); + spin_lock_irqsave(&par->DAClock, flags); + banshee_make_room(par, 1); + tdfx_outl(par, VIDPROCCFG, par->hwcursor.enable); + spin_unlock_irqrestore(&par->DAClock, flags); + return 0; } /** @@ -978,6 +1120,7 @@ static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap) static int __devinit tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + struct tdfx_par *default_par; struct fb_info *info; int size, err; @@ -986,33 +1129,36 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, return err; } - info = kmalloc(sizeof(struct fb_info) + sizeof(struct display) + - sizeof(u32) * 16, GFP_KERNEL); + size = sizeof(struct fb_info)+sizeof(struct tdfx_par)+16*sizeof(u32); + + info = kmalloc(size, GFP_KERNEL); if (!info) return -ENOMEM; - memset(info, 0, sizeof(info) + sizeof(struct display) + sizeof(u32) * 16); - + memset(info, 0, size); + + default_par = (struct tdfx_par *) (info + 1); + /* Configure the default fb_fix_screeninfo first */ switch (pdev->device) { case PCI_DEVICE_ID_3DFX_BANSHEE: strcat(tdfx_fix.id, " Banshee"); - default_par.max_pixclock = BANSHEE_MAX_PIXCLOCK; + default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK; break; case PCI_DEVICE_ID_3DFX_VOODOO3: strcat(tdfx_fix.id, " Voodoo3"); - default_par.max_pixclock = VOODOO3_MAX_PIXCLOCK; + default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK; break; case PCI_DEVICE_ID_3DFX_VOODOO5: strcat(tdfx_fix.id, " Voodoo5"); - default_par.max_pixclock = VOODOO5_MAX_PIXCLOCK; + default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK; break; } tdfx_fix.mmio_start = pci_resource_start(pdev, 0); tdfx_fix.mmio_len = pci_resource_len(pdev, 0); - default_par.regbase_virt = ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len); - if (!default_par.regbase_virt) { + default_par->regbase_virt = ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len); + if (!default_par->regbase_virt) { printk("fb: Can't remap %s register area.\n", tdfx_fix.id); goto out_err; } @@ -1024,7 +1170,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, } tdfx_fix.smem_start = pci_resource_start(pdev, 1); - if (!(tdfx_fix.smem_len = do_lfb_size(pdev->device))) { + if (!(tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device))) { printk("fb: Can't count %s memory.\n", tdfx_fix.id); release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); @@ -1050,7 +1196,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, goto out_err; } - default_par.iobase = pci_resource_start(pdev, 2); + default_par->iobase = pci_resource_start(pdev, 2); if (!request_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2), "tdfx iobase")) { @@ -1073,17 +1219,10 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, info->node = NODEV; info->fbops = &tdfxfb_ops; info->fix = tdfx_fix; - info->par = &default_par; - info->disp = (struct display *)(info + 1); - info->pseudo_palette = (void *)(info->disp + 1); + info->par = default_par; + info->pseudo_palette = (void *)(default_par + 1); info->flags = FBINFO_FLAG_DEFAULT; - /* The below feilds will go away !!!! */ - strcpy(info->modename, info->fix.id); - info->currcon = -1; - info->switch_con = gen_switch; - info->updatevar = gen_update_var; - if (!mode_option) mode_option = "640x480@60"; @@ -1094,8 +1233,6 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, size = (info->var.bits_per_pixel == 8) ? 256 : 16; fb_alloc_cmap(&info->cmap, size, 0); - gen_set_var(&info->var, -1, info); - if (register_framebuffer(info) < 0) { printk("tdfxfb: can't register framebuffer\n"); goto out_err; @@ -1110,8 +1247,8 @@ out_err: /* * Cleanup after anything that was remapped/allocated. */ - if (default_par.regbase_virt) - iounmap(default_par.regbase_virt); + if (default_par->regbase_virt) + iounmap(default_par->regbase_virt); if (info->screen_base) iounmap(info->screen_base); kfree(info); @@ -1160,8 +1297,6 @@ static void __exit tdfxfb_exit(void) MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>"); MODULE_DESCRIPTION("3Dfx framebuffer device driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(noaccel, "i"); -MODULE_PARM_DESC(noaccel, "Disable hardware acceleration (1 = disabled), enabled by default."); #ifdef MODULE module_init(tdfxfb_init); diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 3fcbcc1de024..427ce6364e7d 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -982,7 +982,7 @@ int __init tgafb_init(void) if (register_framebuffer(&fb_info.gen.info) < 0) return -EINVAL; printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n", - GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename, + minor(fb_info.gen.info.node), fb_info.gen.info.modename, pdev->resource[0].start); return 0; } diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 2e53e6d53287..6ed9c651892b 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -1235,7 +1235,7 @@ int __init tridentfb_init(void) } output("fb%d: %s frame buffer device %dx%d-%dbpp\n", - GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename,default_var.xres, + minor(fb_info.gen.info.node), fb_info.gen.info.modename,default_var.xres, default_var.yres,default_var.bits_per_pixel); return 0; } diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c index d395664206ec..bcdf2e61f240 100644 --- a/drivers/video/tx3912fb.c +++ b/drivers/video/tx3912fb.c @@ -21,7 +21,6 @@ #include <linux/init.h> #include <linux/pm.h> #include <linux/fb.h> -#include <video/fbcon.h> #include <asm/io.h> #include <asm/bootinfo.h> #include <asm/uaccess.h> @@ -33,7 +32,6 @@ */ static struct fb_info fb_info; static u32 cfb8[16]; -static struct display disp; static struct fb_fix_screeninfo tx3912fb_fix __initdata = { .id = "tx3912fb", @@ -96,13 +94,11 @@ static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green, */ static struct fb_ops tx3912fb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = tx3912fb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) @@ -215,6 +211,7 @@ static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green, int __init tx3912fb_init(void) { u_long tx3912fb_paddr = 0; + int size = (info->var.bits_per_pixel == 8) ? 256 : 16; /* Disable the video logic */ outl(inl(TX3912_VIDEO_CTRL1) & @@ -295,17 +292,11 @@ int __init tx3912fb_init(void) if ((tx3912fb_fix.line_length * tx3912fb_var.yres_virtual) > tx3912fb_fix.smem_len) return -ENOMEM; - strcpy(fb_info.modename, tx3912fb_fix.id); - fb_info.changevar = NULL; fb_info.node = NODEV; - fb_info.currcon = -1; fb_info.fbops = &tx3912fb_ops; fb_info.var = tx3912fb_var; fb_info.fix = tx3912fb_fix; fb_info.pseudo_palette = pseudo_palette; - fb_info.disp = &disp; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_info.flags = FBINFO_FLAG_DEFAULT; /* Clear the framebuffer */ @@ -313,17 +304,16 @@ int __init tx3912fb_init(void) udelay(200); fb_alloc_cmap(&info->cmap, size, 0); - gen_set_disp(-1, &disp); if (register_framebuffer(&fb_info) < 0) return -1; printk(KERN_INFO "fb%d: TX3912 frame buffer using %uKB.\n", - GET_FB_IDX(fb_info.node), (u_int) (fb_info.fix.smem_len >> 10)); + minor(fb_info.node), (u_int) (fb_info.fix.smem_len >> 10)); return 0; } -void __init tx3912fb_setup(char *options) +int __init tx3912fb_setup(char *options) { char *this_opt; @@ -334,6 +324,7 @@ void __init tx3912fb_setup(char *options) if (!strncmp(options, "bpp:", 4)) tx3912fb_var.bits_per_pixel = simple_strtoul(options+4, NULL, 0); } + return 0; } MODULE_LICENSE("GPL"); diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index a6e4e367a1b2..e447ab48969d 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -127,10 +127,6 @@ struct fb_info_valkyrie { int valkyriefb_init(void); int valkyriefb_setup(char*); -static int valkyrie_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *info); -static int valkyrie_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info); static int valkyrie_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info); static int valkyrie_get_cmap(struct fb_cmap *cmap, int kspc, int con, @@ -157,8 +153,6 @@ static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valk static struct fb_ops valkyriefb_ops = { .owner = THIS_MODULE, - .fb_get_fix = valkyrie_get_fix, - .fb_get_var = valkyrie_get_var, .fb_set_var = valkyrie_set_var, .fb_get_cmap = valkyrie_get_cmap, .fb_set_cmap = gen_set_cmap, @@ -169,24 +163,6 @@ static struct fb_ops valkyriefb_ops = { static int valkyriefb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info); -static int valkyrie_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *info) -{ - struct fb_info_valkyrie *cp = (struct fb_info_valkyrie *) info; - - *fix = cp->fix; - return 0; -} - -static int valkyrie_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) -{ - struct fb_info_valkyrie *cp = (struct fb_info_valkyrie *) info; - - *var = cp->var; - return 0; -} - /* Sets everything according to var */ static int valkyrie_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) @@ -705,7 +681,6 @@ static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, static void valkyrie_init_display(struct display *disp) { memset(disp, 0, sizeof(*disp)); - disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS; disp->can_soft_blank = can_soft_blank; disp->scrollmode = SCROLL_YREDRAW; } @@ -714,8 +689,6 @@ static void valkyrie_par_to_display(struct fb_par_valkyrie *par, struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p) { disp->var = p->var; - disp->visual = fix->visual; - disp->line_length = fix->line_length; if(disp->scrollmode != SCROLL_YREDRAW) { printk(KERN_ERR "Scroll mode not YREDRAW in valkyrie_par_to_display\n"); diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 1326c71bd697..1f64653ece3d 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -17,16 +17,12 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/fb.h> -#include <linux/console.h> -#include <linux/selection.h> #include <linux/ioport.h> #include <linux/init.h> #include <asm/io.h> #include <asm/mtrr.h> -#include <video/fbcon.h> - #define dac_reg (0x3c8) #define dac_val (0x3c9) @@ -49,7 +45,6 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = { .accel = FB_ACCEL_NONE, }; -static struct display disp; static struct fb_info fb_info; static u32 pseudo_palette[17]; @@ -64,7 +59,7 @@ static void (*pmi_pal)(void); /* --------------------------------------------------------------------- */ -static int vesafb_pan_display(struct fb_var_screeninfo *var, int con, +static int vesafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { int offset; @@ -175,22 +170,18 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, static struct fb_ops vesafb_ops = { .owner = THIS_MODULE, - .fb_set_var = gen_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, .fb_setcolreg = vesafb_setcolreg, .fb_pan_display = vesafb_pan_display, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, }; int __init vesafb_setup(char *options) { char *this_opt; - fb_info.fontname[0] = '\0'; - if (!options || !*options) return 0; @@ -211,8 +202,6 @@ int __init vesafb_setup(char *options) pmi_setpal=1; else if (! strcmp(this_opt, "mtrr")) mtrr=1; - else if (!strncmp(this_opt, "font:", 5)) - strcpy(fb_info.fontname, this_opt+5); } return 0; } @@ -351,27 +340,20 @@ int __init vesafb_init(void) } } - strcpy(fb_info.modename, vesafb_fix.id); - fb_info.changevar = NULL; fb_info.node = NODEV; fb_info.fbops = &vesafb_ops; fb_info.var = vesafb_defined; fb_info.fix = vesafb_fix; - fb_info.currcon = -1; - fb_info.disp = &disp; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; fb_info.pseudo_palette = pseudo_palette; fb_info.flags = FBINFO_FLAG_DEFAULT; fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); - gen_set_disp(-1, &fb_info); if (register_framebuffer(&fb_info)<0) return -EINVAL; printk(KERN_INFO "fb%d: %s frame buffer device\n", - GET_FB_IDX(fb_info.node), fb_info.fix.id); + minor(fb_info.node), fb_info.fix.id); return 0; } diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 5ed50a49b234..2963d032b054 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -24,8 +24,6 @@ #include <linux/fb.h> #include <linux/init.h> -#include <video/fbcon.h> - /* * RAM we reserve for the frame buffer. This defines the maximum screen * size @@ -42,7 +40,6 @@ static const char *mode_option __initdata = NULL; static struct fb_info fb_info; static u32 vfb_pseudo_palette[17]; -static struct display disp; static struct fb_var_screeninfo vfb_default __initdata = { .xres = 640, @@ -90,23 +87,21 @@ static int vfb_check_var(struct fb_var_screeninfo *var, static int vfb_set_par(struct fb_info *info); static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); -static int vfb_pan_display(struct fb_var_screeninfo *var, int con, +static int vfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static int vfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); static struct fb_ops vfb_ops = { - .fb_set_var gen_set_var, - .fb_get_cmap gen_set_cmap, - .fb_set_cmap gen_set_cmap, - .fb_check_var vfb_check_var, - .fb_set_par vfb_set_par, - .fb_setcolreg vfb_setcolreg, - .fb_pan_display vfb_pan_display, - .fb_fillrect cfb_fillrect, - .fb_copyarea cfb_copyarea, - .fb_imageblit cfb_imageblit, - .fb_mmap vfb_mmap, + .fb_check_var = vfb_check_var, + .fb_set_par = vfb_set_par, + .fb_setcolreg = vfb_setcolreg, + .fb_pan_display = vfb_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, + .fb_mmap = vfb_mmap, }; /* @@ -356,7 +351,7 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int vfb_pan_display(struct fb_var_screeninfo *var, int con, +static int vfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { if (var->vmode & FB_VMODE_YWRAP) { @@ -444,13 +439,6 @@ int __init vfb_init(void) fb_info.pseudo_palette = &vfb_pseudo_palette; fb_info.flags = FBINFO_FLAG_DEFAULT; - strcpy(fb_info.modename, vfb_fix.id); - fb_info.changevar = NULL; - fb_info.currcon = -1; - fb_info.disp = &disp; - fb_info.switch_con = gen_switch; - fb_info.updatevar = gen_update_var; - fb_alloc_cmap(&fb_info.cmap, 256, 0); if (register_framebuffer(&fb_info) < 0) { @@ -460,7 +448,7 @@ int __init vfb_init(void) printk(KERN_INFO "fb%d: Virtual frame buffer device, using %ldK of video memory\n", - GET_FB_IDX(fb_info.node), videomemorysize >> 10); + minor(fb_info.node), videomemorysize >> 10); return 0; } diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index a80ecae5e07f..7a38893b34b0 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -7,7 +7,8 @@ * * 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. */ + * archive for more details. + */ #include <linux/module.h> #include <linux/kernel.h> @@ -18,35 +19,41 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/fb.h> -#include <linux/console.h> -#include <linux/selection.h> #include <linux/ioport.h> #include <linux/init.h> -#include <linux/interrupt.h> #include <asm/io.h> - -#include <video/fbcon.h> -#include <video/fbcon-vga-planes.h> #include "vga.h" -#define dac_reg (0x3c8) -#define dac_val (0x3c9) +#define GRAPHICS_ADDR_REG VGA_GFX_I /* Graphics address register. */ +#define GRAPHICS_DATA_REG VGA_GFX_D /* Graphics data register. */ + +#define SET_RESET_INDEX VGA_GFX_SR_VALUE /* Set/Reset Register index. */ +#define ENABLE_SET_RESET_INDEX VGA_GFX_SR_ENABLE /* Enable Set/Reset Register index. */ +#define DATA_ROTATE_INDEX VGA_GFX_DATA_ROTATE /* Data Rotate Register index. */ +#define GRAPHICS_MODE_INDEX VGA_GFX_MODE /* Graphics Mode Register index. */ +#define BIT_MASK_INDEX VGA_GFX_BIT_MASK /* Bit Mask Register index. */ + +#define dac_reg (VGA_PEL_IW) +#define dac_val (VGA_PEL_D) #define VGA_FB_PHYS 0xA0000 #define VGA_FB_PHYS_LEN 65536 +#define MODE_SKIP4 1 +#define MODE_8BPP 2 +#define MODE_CFB 4 +#define MODE_TEXT 8 + /* --------------------------------------------------------------------- */ /* * card parameters */ -static struct vga16fb_info { - struct fb_info fb_info; - char *video_vbase; /* 0xa0000 map address */ - int isVGA; - +static struct fb_info vga16fb; + +static struct vga16fb_par { /* structure holding original VGA register settings when the screen is blanked */ struct { @@ -63,109 +70,200 @@ static struct vga16fb_info { unsigned char ModeControl; /* CRT-Controller:17h */ unsigned char ClockingMode; /* Seq-Controller:01h */ } vga_state; - - int palette_blanked; - int vesa_blanked; -} vga16fb; - - -struct vga16fb_par { + struct fb_vgastate state; + atomic_t ref_count; + int palette_blanked, vesa_blanked, mode, isVGA; + u8 misc, pel_msk, vss, clkdiv; u8 crtc[VGA_CRT_C]; - u8 atc[VGA_ATT_C]; - u8 gdc[VGA_GFX_C]; - u8 seq[VGA_SEQ_C]; - u8 misc; - u8 vss; - struct fb_var_screeninfo var; -}; +} vga16_par; /* --------------------------------------------------------------------- */ static struct fb_var_screeninfo vga16fb_defined = { - .xres = 640, - .yres = 480, - .xres_virtual = 640, - .yres_virtual = 480, - .bits_per_pixel = 4, - .activate = FB_ACTIVATE_NOW, - .height = -1, - .width = -1, - .pixclock = 39721, - .left_margin = 48, - .right_margin = 16, - .upper_margin = 39, - .lower_margin = 8, - .hsync_len = 96, - .vsync_len = 2, - .vmode = FB_VMODE_NONINTERLACED, + .xres = 640, + .yres = 480, + .xres_virtual = 640, + .yres_virtual = 480, + .bits_per_pixel = 4, + .activate = FB_ACTIVATE_TEST, + .height = -1, + .width = -1, + .pixclock = 39721, + .left_margin = 48, + .right_margin = 16, + .upper_margin = 39, + .lower_margin = 8, + .hsync_len = 96, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED, }; +/* name should not depend on EGA/VGA */ static struct fb_fix_screeninfo vga16fb_fix __initdata = { - .id = "VGA16 VGA", - .smem_start = VGA_FB_PHYS, - .smem_len = VGA_FB_PHYS_LEN, - .type = FB_TYPE_VGA_PLANES, - .visual = FB_VISUAL_PSEUDOCOLOR, - .xpanstep = 8, - .ypanstep = 1, - .line_length = 640 / 8, + .id = "VGA16 VGA", + .smem_start = VGA_FB_PHYS, + .smem_len = VGA_FB_PHYS_LEN, + .type = FB_TYPE_VGA_PLANES, + .type_aux = FB_AUX_VGA_PLANES_VGA4, + .visual = FB_VISUAL_PSEUDOCOLOR, + .xpanstep = 8, + .ypanstep = 1, + .line_length = 640/8, + .accel = FB_ACCEL_NONE }; -static struct display disp; -static struct { u_short blue, green, red, pad; } palette[256]; +/* The VGA's weird architecture often requires that we read a byte and + write a byte to the same location. It doesn't matter *what* byte + we write, however. This is because all the action goes on behind + the scenes in the VGA's 32-bit latch register, and reading and writing + video memory just invokes latch behavior. + + To avoid race conditions (is this necessary?), reading and writing + the memory byte should be done with a single instruction. One + suitable instruction is the x86 bitwise OR. The following + read-modify-write routine should optimize to one such bitwise + OR. */ +static inline void rmw(volatile char *p) +{ + readb(p); + writeb(1, p); +} -/* --------------------------------------------------------------------- */ +/* Set the Graphics Mode Register, and return its previous value. + Bits 0-1 are write mode, bit 3 is read mode. */ +static inline int setmode(int mode) +{ + int oldmode; + + vga_io_w(GRAPHICS_ADDR_REG, GRAPHICS_MODE_INDEX); + oldmode = vga_io_r(GRAPHICS_DATA_REG); + vga_io_w(GRAPHICS_DATA_REG, mode); + return oldmode; +} -static void vga16fb_pan_var(struct fb_info *info, struct fb_var_screeninfo *var) -{ - u32 pos = (var->xres_virtual * var->yoffset + var->xoffset) >> 3; - outb(VGA_CRTC_START_HI, VGA_CRT_IC); - outb(pos >> 8, VGA_CRT_DC); - outb(VGA_CRTC_START_LO, VGA_CRT_IC); - outb(pos & 0xFF, VGA_CRT_DC); -#if 0 - /* if someone supports xoffset in bit resolution */ - inb(VGA_IS1_RC); /* reset flip-flop */ - outb(VGA_ATC_PEL, VGA_ATT_IW); - outb(xoffset & 7, VGA_ATT_IW); - inb(VGA_IS1_RC); - outb(0x20, VGA_ATT_IW); -#endif +/* Select the Bit Mask Register and return its value. */ +static inline int selectmask(void) +{ + return vga_io_rgfx(BIT_MASK_INDEX); } -static void vga16fb_set_disp(int con, struct vga16fb_info *info) +/* Set the value of the Bit Mask Register. It must already have been + selected with selectmask(). */ +static inline void setmask(int mask) { - struct display *display = (con < 0) ? info->fb_info.disp : (fb_display + con); + vga_io_w(GRAPHICS_DATA_REG, mask); +} - display->can_soft_blank = 1; - display->dispsw_data = NULL; - display->var = info->fb_info.var; - display->inverse = 0; +/* Set the Data Rotate Register and return its old value. + Bits 0-2 are rotate count, bits 3-4 are logical operation + (0=NOP, 1=AND, 2=OR, 3=XOR). */ +static inline int setop(int op) +{ + int oldop; + + vga_io_w(GRAPHICS_ADDR_REG, DATA_ROTATE_INDEX); + oldop = vga_io_r(GRAPHICS_DATA_REG); + vga_io_w(GRAPHICS_DATA_REG, op); + return oldop; +} + +/* Set the Enable Set/Reset Register and return its old value. + The code here always uses value 0xf for thsi register. */ +static inline int setsr(int sr) +{ + int oldsr; + + vga_io_w(GRAPHICS_ADDR_REG, ENABLE_SET_RESET_INDEX); + oldsr = vga_io_r(GRAPHICS_DATA_REG); + vga_io_w(GRAPHICS_DATA_REG, sr); + return oldsr; +} - /* - * If we are setting all the virtual consoles, also set - * the defaults used to create new consoles. - */ - if (con < 0 || info->fb_info.var.activate & FB_ACTIVATE_ALL) - info->fb_info.disp->var = info->fb_info.var; +/* Set the Set/Reset Register and return its old value. */ +static inline int setcolor(int color) +{ + int oldcolor; + + vga_io_w(GRAPHICS_ADDR_REG, SET_RESET_INDEX); + oldcolor = vga_io_r(GRAPHICS_DATA_REG); + vga_io_w(GRAPHICS_DATA_REG, color); + return oldcolor; +} + +/* Return the value in the Graphics Address Register. */ +static inline int getindex(void) +{ + return vga_io_r(GRAPHICS_ADDR_REG); +} - if (info->isVGA) - display->dispsw = &fbcon_vga_planes; +/* Set the value in the Graphics Address Register. */ +static inline void setindex(int index) +{ + vga_io_w(GRAPHICS_ADDR_REG, index); +} + +static void vga16fb_pan_var(struct fb_info *info, + struct fb_var_screeninfo *var) +{ + struct vga16fb_par *par = (struct vga16fb_par *) info->par; + u32 xoffset, pos; + + xoffset = var->xoffset; + if (info->var.bits_per_pixel == 8) { + pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 2; + } else if (par->mode & MODE_TEXT) { + int fh = 16; // FIXME !!! font height. Fugde for now. + pos = (info->var.xres_virtual * (var->yoffset / fh) + xoffset) >> 3; + } else { + if (info->var.nonstd) + xoffset--; + pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 3; + } + vga_io_wcrt(VGA_CRTC_START_HI, pos >> 8); + vga_io_wcrt(VGA_CRTC_START_LO, pos & 0xFF); + /* if we support CFB4, then we must! support xoffset with pixel + * granularity if someone supports xoffset in bit resolution */ + vga_io_r(VGA_IS1_RC); /* reset flip-flop */ + vga_io_w(VGA_ATT_IW, VGA_ATC_PEL); + if (var->bits_per_pixel == 8) + vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1); else - display->dispsw = &fbcon_ega_planes; - display->scrollmode = SCROLL_YREDRAW; + vga_io_w(VGA_ATT_IW, xoffset & 7); + vga_io_r(VGA_IS1_RC); + vga_io_w(VGA_ATT_IW, 0x20); } -static void vga16fb_encode_var(struct fb_var_screeninfo *var, - const struct vga16fb_par *par, - const struct vga16fb_info *info) +static void vga16fb_update_fix(struct fb_info *info) { - *var = par->var; + if (info->var.bits_per_pixel == 4) { + if (info->var.nonstd) { + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.line_length = info->var.xres_virtual / 2; + } else { + info->fix.type = FB_TYPE_VGA_PLANES; + info->fix.type_aux = FB_AUX_VGA_PLANES_VGA4; + info->fix.line_length = info->var.xres_virtual / 8; + } + } else if (info->var.bits_per_pixel == 0) { + info->fix.type = FB_TYPE_TEXT; + info->fix.type_aux = FB_AUX_TEXT_CGA; + info->fix.line_length = info->var.xres_virtual / 4; + } else { /* 8bpp */ + if (info->var.nonstd) { + info->fix.type = FB_TYPE_VGA_PLANES; + info->fix.type_aux = FB_AUX_VGA_PLANES_CFB8; + info->fix.line_length = info->var.xres_virtual / 4; + } else { + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.line_length = info->var.xres_virtual; + } + } } static void vga16fb_clock_chip(struct vga16fb_par *par, unsigned int pixclock, - const struct vga16fb_info *info) + const struct fb_info *info, + int mul, int div) { static struct { u32 pixclock; @@ -179,6 +277,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, { 0 /* bad */, 0x00, 0x00}}; int err; + pixclock = (pixclock * mul) / div; best = vgaclocks; err = pixclock - best->pixclock; if (err < 0) err = -err; @@ -193,25 +292,98 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, } } par->misc |= best->misc; - par->seq[VGA_SEQ_CLOCK_MODE] |= best->seq_clock_mode; - par->var.pixclock = best->pixclock; + par->clkdiv = best->seq_clock_mode; + pixclock = (best->pixclock * div) / mul; } #define FAIL(X) return -EINVAL -static int vga16fb_decode_var(const struct fb_var_screeninfo *var, - struct vga16fb_par *par, - const struct vga16fb_info *info) +static int vga16fb_open(struct fb_info *info, int user) +{ + struct vga16fb_par *par = (struct vga16fb_par *) info->par; + int cnt = atomic_read(&par->ref_count); + + if (!cnt) { + memset(&par->state, 0, sizeof(struct fb_vgastate)); + par->state.flags = 8; + fb_save_vga(&par->state); + } + atomic_inc(&par->ref_count); + return 0; +} + +static int vga16fb_release(struct fb_info *info, int user) +{ + struct vga16fb_par *par = (struct vga16fb_par *) info->par; + int cnt = atomic_read(&par->ref_count); + + if (!cnt) + return -EINVAL; + if (cnt == 1) + fb_restore_vga(&par->state); + atomic_dec(&par->ref_count); + + return 0; +} + +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; u32 vxres, xoffset, vyres, yoffset; u32 pos; u8 r7, rMode; - int i; - - if (var->bits_per_pixel != 4) + int shift; + int mode; + u32 maxmem; + + par->pel_msk = 0xFF; + + if (var->bits_per_pixel == 4) { + if (var->nonstd) { + if (!par->isVGA) + return -EINVAL; + shift = 3; + mode = MODE_SKIP4 | MODE_CFB; + maxmem = 16384; + par->pel_msk = 0x0F; + } else { + shift = 3; + mode = 0; + maxmem = 65536; + } + } else if (var->bits_per_pixel == 8) { + if (!par->isVGA) + return -EINVAL; /* no support on EGA */ + shift = 2; + if (var->nonstd) { + mode = MODE_8BPP | MODE_CFB; + maxmem = 65536; + } else { + 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 return -EINVAL; + xres = (var->xres + 7) & ~7; vxres = (var->xres_virtual + 0xF) & ~0xF; xoffset = (var->xoffset + 7) & ~7; @@ -224,18 +396,18 @@ static int vga16fb_decode_var(const struct fb_var_screeninfo *var, if (xres + xoffset > vxres) xoffset = vxres - xres; - par->var.xres = xres; - par->var.right_margin = right; - par->var.hsync_len = hslen; - par->var.left_margin = left; - par->var.xres_virtual = vxres; - par->var.xoffset = xoffset; - - xres >>= 3; - right >>= 3; - hslen >>= 3; - left >>= 3; - vxres >>= 3; + var->xres = xres; + var->right_margin = right; + var->hsync_len = hslen; + var->left_margin = left; + var->xres_virtual = vxres; + var->xoffset = xoffset; + + xres >>= shift; + right >>= shift; + hslen >>= shift; + left >>= shift; + vxres >>= shift; xtotal = xres + right + hslen + left; if (xtotal >= 256) FAIL("xtotal too big"); @@ -264,19 +436,19 @@ static int vga16fb_decode_var(const struct fb_var_screeninfo *var, if (yres > vyres) vyres = yres; - if (vxres * vyres > 65536) { - vyres = 65536 / vxres; + if (vxres * vyres > maxmem) { + vyres = maxmem / vxres; if (vyres < yres) return -ENOMEM; } if (yoffset + yres > vyres) yoffset = vyres - yres; - par->var.yres = yres; - par->var.lower_margin = lower; - par->var.vsync_len = vslen; - par->var.upper_margin = upper; - par->var.yres_virtual = vyres; - par->var.yoffset = yoffset; + var->yres = yres; + var->lower_margin = lower; + var->vsync_len = vslen; + var->upper_margin = upper; + var->yres_virtual = vyres; + var->yoffset = yoffset; if (var->vmode & FB_VMODE_DOUBLE) { yres <<= 1; @@ -304,12 +476,13 @@ static int vga16fb_decode_var(const struct fb_var_screeninfo *var, if (ytotal & 0x200) r7 |= 0x20; par->crtc[VGA_CRTC_PRESET_ROW] = 0; par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */ - par->var.vmode = var->vmode; if (var->vmode & FB_VMODE_DOUBLE) par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80; par->crtc[VGA_CRTC_CURSOR_START] = 0x20; par->crtc[VGA_CRTC_CURSOR_END] = 0x00; - pos = yoffset * vxres + (xoffset >> 3); + if ((mode & (MODE_CFB | MODE_8BPP)) == MODE_CFB) + xoffset--; + pos = yoffset * vxres + (xoffset >> shift); par->crtc[VGA_CRTC_START_HI] = pos >> 8; par->crtc[VGA_CRTC_START_LO] = pos & 0xFF; par->crtc[VGA_CRTC_CURSOR_HI] = 0x00; @@ -337,166 +510,199 @@ static int vga16fb_decode_var(const struct fb_var_screeninfo *var, if (vxres >= 512) FAIL("vxres too long"); par->crtc[VGA_CRTC_OFFSET] = vxres >> 1; - par->crtc[VGA_CRTC_UNDERLINE] = 0x1F; - par->crtc[VGA_CRTC_MODE] = rMode | 0xE3; + if (mode & MODE_SKIP4) + par->crtc[VGA_CRTC_UNDERLINE] = 0x5F; /* 256, cfb8 */ + else + par->crtc[VGA_CRTC_UNDERLINE] = 0x1F; /* 16, vgap */ + par->crtc[VGA_CRTC_MODE] = rMode | ((mode & MODE_TEXT) ? 0xA3 : 0xE3); par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF; par->crtc[VGA_CRTC_OVERFLOW] = r7; par->vss = 0x00; /* 3DA */ - for (i = 0x00; i < 0x10; i++) - par->atc[i] = i; - par->atc[VGA_ATC_MODE] = 0x81; - par->atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */ - par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F; - par->atc[VGA_ATC_PEL] = xoffset & 7; - par->atc[VGA_ATC_COLOR_PAGE] = 0x00; - - par->misc = 0xC3; /* enable CPU, ports 0x3Dx, positive sync */ - par->var.sync = var->sync; + par->misc = 0xE3; /* enable CPU, ports 0x3Dx, positive sync */ if (var->sync & FB_SYNC_HOR_HIGH_ACT) par->misc &= ~0x40; if (var->sync & FB_SYNC_VERT_HIGH_ACT) par->misc &= ~0x80; - par->seq[VGA_SEQ_CLOCK_MODE] = 0x01; - par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F; - par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00; - par->seq[VGA_SEQ_MEMORY_MODE] = 0x06; - - par->gdc[VGA_GFX_SR_VALUE] = 0x00; - par->gdc[VGA_GFX_SR_ENABLE] = 0x0F; - par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00; - par->gdc[VGA_GFX_DATA_ROTATE] = 0x20; - par->gdc[VGA_GFX_PLANE_READ] = 0; - par->gdc[VGA_GFX_MODE] = 0x00; - par->gdc[VGA_GFX_MISC] = 0x05; - par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F; - par->gdc[VGA_GFX_BIT_MASK] = 0xFF; - - vga16fb_clock_chip(par, var->pixclock, info); - - par->var.bits_per_pixel = 4; - par->var.grayscale = var->grayscale; - par->var.red.offset = par->var.green.offset = par->var.blue.offset = - par->var.transp.offset = 0; - par->var.red.length = par->var.green.length = par->var.blue.length = - (info->isVGA) ? 6 : 2; - par->var.transp.length = 0; - par->var.nonstd = 0; - par->var.activate = FB_ACTIVATE_NOW; - par->var.height = -1; - par->var.width = -1; - par->var.accel_flags = 0; + par->mode = mode; + + if (mode & MODE_8BPP) + /* pixel clock == vga clock / 2 */ + vga16fb_clock_chip(par, var->pixclock, info, 1, 2); + else + /* pixel clock == vga clock */ + vga16fb_clock_chip(par, var->pixclock, info, 1, 1); + var->red.offset = var->green.offset = var->blue.offset = + var->transp.offset = 0; + var->red.length = var->green.length = var->blue.length = + (par->isVGA) ? 6 : 2; + var->transp.length = 0; + var->activate = FB_ACTIVATE_NOW; + var->height = -1; + var->width = -1; + var->accel_flags = 0; return 0; } #undef FAIL -static int vga16fb_set_par(const struct vga16fb_par *par, - struct vga16fb_info *info) +#ifdef FBCON_HAS_VGA +static void vga16fb_load_font(struct display* p) { - int i; + 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 - outb(inb(VGA_MIS_R) | 0x01, VGA_MIS_W); +static int vga16fb_set_par(struct fb_info *info) +{ + struct vga16fb_par *par = (struct vga16fb_par *) info->par; + u8 gdc[VGA_GFX_C]; + u8 seq[VGA_SEQ_C]; + u8 atc[VGA_ATT_C]; + int fh, i; + + seq[VGA_SEQ_CLOCK_MODE] = 0x01 | par->clkdiv; + if (par->mode & MODE_TEXT) + seq[VGA_SEQ_PLANE_WRITE] = 0x03; + else + seq[VGA_SEQ_PLANE_WRITE] = 0x0F; + seq[VGA_SEQ_CHARACTER_MAP] = 0x00; + if (par->mode & MODE_TEXT) + seq[VGA_SEQ_MEMORY_MODE] = 0x03; + else if (par->mode & MODE_SKIP4) + seq[VGA_SEQ_MEMORY_MODE] = 0x0E; + else + seq[VGA_SEQ_MEMORY_MODE] = 0x06; + + gdc[VGA_GFX_SR_VALUE] = 0x00; + gdc[VGA_GFX_SR_ENABLE] = 0x00; + gdc[VGA_GFX_COMPARE_VALUE] = 0x00; + gdc[VGA_GFX_DATA_ROTATE] = 0x00; + gdc[VGA_GFX_PLANE_READ] = 0; + if (par->mode & MODE_TEXT) { + gdc[VGA_GFX_MODE] = 0x10; + gdc[VGA_GFX_MISC] = 0x06; + } else { + if (par->mode & MODE_CFB) + gdc[VGA_GFX_MODE] = 0x40; + else + gdc[VGA_GFX_MODE] = 0x00; + gdc[VGA_GFX_MISC] = 0x05; + } + gdc[VGA_GFX_COMPARE_MASK] = 0x0F; + gdc[VGA_GFX_BIT_MASK] = 0xFF; + + for (i = 0x00; i < 0x10; i++) + atc[i] = i; + if (par->mode & MODE_TEXT) + atc[VGA_ATC_MODE] = 0x04; + else if (par->mode & MODE_8BPP) + atc[VGA_ATC_MODE] = 0x41; + else + atc[VGA_ATC_MODE] = 0x81; + atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */ + atc[VGA_ATC_PLANE_ENABLE] = 0x0F; + if (par->mode & MODE_8BPP) + atc[VGA_ATC_PEL] = (info->var.xoffset & 3) << 1; + else + atc[VGA_ATC_PEL] = info->var.xoffset & 7; + atc[VGA_ATC_COLOR_PAGE] = 0x00; + + if (par->mode & MODE_TEXT) { + fh = 16; // FIXME !!! Fudge font height. + par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] + & ~0x1F) | (fh - 1); + } + + vga_io_w(VGA_MIS_W, vga_io_r(VGA_MIS_R) | 0x01); /* Enable graphics register modification */ - if (!info->isVGA) { - outb(0x00, EGA_GFX_E0); - outb(0x01, EGA_GFX_E1); + if (!par->isVGA) { + vga_io_w(EGA_GFX_E0, 0x00); + vga_io_w(EGA_GFX_E1, 0x01); } /* update misc output register */ - outb(par->misc, VGA_MIS_W); + vga_io_w(VGA_MIS_W, par->misc); /* synchronous reset on */ - outb(0x00, VGA_SEQ_I); - outb(0x01, VGA_SEQ_D); - + vga_io_wseq(0x00, 0x01); + + if (par->isVGA) + vga_io_w(VGA_PEL_MSK, par->pel_msk); + /* write sequencer registers */ - outb(1, VGA_SEQ_I); - outb(par->seq[1] | 0x20, VGA_SEQ_D); + vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE] | 0x20); for (i = 2; i < VGA_SEQ_C; i++) { - outb(i, VGA_SEQ_I); - outb(par->seq[i], VGA_SEQ_D); + vga_io_wseq(i, seq[i]); } /* synchronous reset off */ - outb(0x00, VGA_SEQ_I); - outb(0x03, VGA_SEQ_D); - + vga_io_wseq(0x00, 0x03); + /* deprotect CRT registers 0-7 */ - outb(0x11, VGA_CRT_IC); - outb(par->crtc[0x11], VGA_CRT_DC); + vga_io_wcrt(VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]); /* write CRT registers */ - for (i = 0; i < VGA_CRT_C; i++) { - outb(i, VGA_CRT_IC); - outb(par->crtc[i], VGA_CRT_DC); + for (i = 0; i < VGA_CRTC_REGS; i++) { + vga_io_wcrt(i, par->crtc[i]); } /* write graphics controller registers */ for (i = 0; i < VGA_GFX_C; i++) { - outb(i, VGA_GFX_I); - outb(par->gdc[i], VGA_GFX_D); + vga_io_wgfx(i, gdc[i]); } /* write attribute controller registers */ for (i = 0; i < VGA_ATT_C; i++) { - inb_p(VGA_IS1_RC); /* reset flip-flop */ - outb_p(i, VGA_ATT_IW); - outb_p(par->atc[i], VGA_ATT_IW); + vga_io_r(VGA_IS1_RC); /* reset flip-flop */ + 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); - outb(0x01, VGA_SEQ_I); - outb(par->seq[1], VGA_SEQ_D); - - inb(VGA_IS1_RC); - outb(0x20, VGA_ATT_IW); - - return 0; -} - -static int vga16fb_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *fb) -{ - struct vga16fb_info *info = (struct vga16fb_info*)fb; - struct vga16fb_par par; - struct display *display = (con < 0) ? fb->disp : (fb_display + con); - int err; - - if ((err = vga16fb_decode_var(var, &par, info)) != 0) - return err; - vga16fb_encode_var(var, &par, info); - - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) - return 0; - - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { - u32 oldxres, oldyres, oldvxres, oldvyres, oldbpp; - - oldxres = display->var.xres; - oldyres = display->var.yres; - oldvxres = display->var.xres_virtual; - oldvyres = display->var.yres_virtual; - oldbpp = display->var.bits_per_pixel; + vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE]); - display->var = *var; - - if (oldxres != var->xres || oldyres != var->yres || - oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || - oldbpp != var->bits_per_pixel) { - vga16fb_set_disp(con, info); - if (info->fb_info.changevar) - info->fb_info.changevar(con); - } - if (con == info->fb_info.currcon) - vga16fb_set_par(&par, info); - } + vga_io_r(VGA_IS1_RC); + vga_io_w(VGA_ATT_IW, 0x20); + vga16fb_update_fix(info); return 0; } @@ -505,12 +711,13 @@ static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned b static unsigned char map[] = { 000, 001, 010, 011 }; int val; + if (regno >= 16) + return; val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2); - inb_p(0x3DA); /* ! 0x3BA */ - outb_p(regno, 0x3C0); - outb_p(val, 0x3C0); - inb_p(0x3DA); /* some clones need it */ - outb_p(0x20, 0x3C0); /* unblank screen */ + vga_io_r(VGA_IS1_RC); /* ! 0x3BA */ + vga_io_wattr(regno, val); + vga_io_r(VGA_IS1_RC); /* some clones need it */ + vga_io_w(VGA_ATT_IW, 0x20); /* unblank screen */ } static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) @@ -523,8 +730,9 @@ static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned b static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, - struct fb_info *fb_info) + struct fb_info *info) { + struct vga16fb_par *par = (struct vga16fb_par *) info->par; int gray; /* @@ -534,40 +742,34 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, * != 0 for invalid regno. */ - if (regno >= 16) + if (regno >= 256) return 1; - palette[regno].red = red; - palette[regno].green = green; - palette[regno].blue = blue; + gray = info->var.grayscale; - if (fb_info->currcon < 0) - gray = disp.var.grayscale; - else - gray = fb_display[fb_info->currcon].var.grayscale; if (gray) { /* gray = 0.30*R + 0.59*G + 0.11*B */ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; } - if (((struct vga16fb_info *) fb_info)->isVGA) + if (par->isVGA) vga16_setpalette(regno,red,green,blue); else ega16_setpalette(regno,red,green,blue); - return 0; } -static int vga16fb_pan_display(struct fb_var_screeninfo *var, int con, +static int vga16fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - if (var->xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual || - var->yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual) + if (var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; - if (con == info->currcon) - vga16fb_pan_var(info, var); - fb_display[con].var.xoffset = var->xoffset; - fb_display[con].var.yoffset = var->yoffset; - fb_display[con].var.vmode &= ~FB_VMODE_YWRAP; + + vga16fb_pan_var(info, var); + + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + info->var.vmode &= ~FB_VMODE_YWRAP; return 0; } @@ -575,59 +777,49 @@ static int vga16fb_pan_display(struct fb_var_screeninfo *var, int con, blanking code was originally by Huang shi chao, and modified by Christoph Rimek (chrimek@toppoint.de) and todd j. derr (tjd@barefoot.org) for Linux. */ -#define attrib_port 0x3c0 -#define seq_port_reg 0x3c4 -#define seq_port_val 0x3c5 -#define gr_port_reg 0x3ce -#define gr_port_val 0x3cf -#define video_misc_rd 0x3cc -#define video_misc_wr 0x3c2 -#define vga_video_port_reg 0x3d4 -#define vga_video_port_val 0x3d5 - -static void vga_vesa_blank(struct vga16fb_info *info, int mode) +#define attrib_port VGA_ATC_IW +#define seq_port_reg VGA_SEQ_I +#define seq_port_val VGA_SEQ_D +#define gr_port_reg VGA_GFX_I +#define gr_port_val VGA_GFX_D +#define video_misc_rd VGA_MIS_R +#define video_misc_wr VGA_MIS_W +#define vga_video_port_reg VGA_CRT_IC +#define vga_video_port_val VGA_CRT_DC + +static void vga_vesa_blank(struct vga16fb_par *par, int mode) { unsigned char SeqCtrlIndex; unsigned char CrtCtrlIndex; - cli(); - SeqCtrlIndex = inb_p(seq_port_reg); - CrtCtrlIndex = inb_p(vga_video_port_reg); + //cli(); + SeqCtrlIndex = vga_io_r(seq_port_reg); + CrtCtrlIndex = vga_io_r(vga_video_port_reg); /* save original values of VGA controller registers */ - if(!info->vesa_blanked) { - info->vga_state.CrtMiscIO = inb_p(video_misc_rd); - sti(); - - outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */ - info->vga_state.HorizontalTotal = inb_p(vga_video_port_val); - outb_p(0x01,vga_video_port_reg); /* HorizDisplayEnd */ - info->vga_state.HorizDisplayEnd = inb_p(vga_video_port_val); - outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ - info->vga_state.StartHorizRetrace = inb_p(vga_video_port_val); - outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ - info->vga_state.EndHorizRetrace = inb_p(vga_video_port_val); - outb_p(0x07,vga_video_port_reg); /* Overflow */ - info->vga_state.Overflow = inb_p(vga_video_port_val); - outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ - info->vga_state.StartVertRetrace = inb_p(vga_video_port_val); - outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ - info->vga_state.EndVertRetrace = inb_p(vga_video_port_val); - outb_p(0x17,vga_video_port_reg); /* ModeControl */ - info->vga_state.ModeControl = inb_p(vga_video_port_val); - outb_p(0x01,seq_port_reg); /* ClockingMode */ - info->vga_state.ClockingMode = inb_p(seq_port_val); + if(!par->vesa_blanked) { + par->vga_state.CrtMiscIO = vga_io_r(video_misc_rd); + //sti(); + + par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */ + par->vga_state.HorizDisplayEnd = vga_io_rcrt(0x01); /* HorizDisplayEnd */ + par->vga_state.StartHorizRetrace = vga_io_rcrt(0x04); /* StartHorizRetrace */ + par->vga_state.EndHorizRetrace = vga_io_rcrt(0x05); /* EndHorizRetrace */ + par->vga_state.Overflow = vga_io_rcrt(0x07); /* Overflow */ + par->vga_state.StartVertRetrace = vga_io_rcrt(0x10); /* StartVertRetrace */ + par->vga_state.EndVertRetrace = vga_io_rcrt(0x11); /* EndVertRetrace */ + par->vga_state.ModeControl = vga_io_rcrt(0x17); /* ModeControl */ + par->vga_state.ClockingMode = vga_io_rseq(0x01); /* ClockingMode */ } /* assure that video is enabled */ /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ - cli(); - outb_p(0x01,seq_port_reg); - outb_p(info->vga_state.ClockingMode | 0x20,seq_port_val); + //cli(); + vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20); /* test for vertical retrace in process.... */ - if ((info->vga_state.CrtMiscIO & 0x80) == 0x80) - outb_p(info->vga_state.CrtMiscIO & 0xef,video_misc_wr); + if ((par->vga_state.CrtMiscIO & 0x80) == 0x80) + vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO & 0xef); /* * Set <End of vertical retrace> to minimum (0) and @@ -640,7 +832,7 @@ static void vga_vesa_blank(struct vga16fb_info *info, int mode) outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ outb_p(0x40,vga_video_port_val); /* minimum (bits 0..3) */ outb_p(0x07,vga_video_port_reg); /* Overflow */ - outb_p(info->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */ + outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */ } if (mode & VESA_HSYNC_SUSPEND) { @@ -658,44 +850,44 @@ static void vga_vesa_blank(struct vga16fb_info *info, int mode) /* restore both index registers */ outb_p(SeqCtrlIndex,seq_port_reg); outb_p(CrtCtrlIndex,vga_video_port_reg); - sti(); + //sti(); } -static void vga_vesa_unblank(struct vga16fb_info *info) +static void vga_vesa_unblank(struct vga16fb_par *par) { unsigned char SeqCtrlIndex; unsigned char CrtCtrlIndex; - cli(); - SeqCtrlIndex = inb_p(seq_port_reg); - CrtCtrlIndex = inb_p(vga_video_port_reg); + //cli(); + SeqCtrlIndex = vga_io_r(seq_port_reg); + CrtCtrlIndex = vga_io_r(vga_video_port_reg); /* restore original values of VGA controller registers */ - outb_p(info->vga_state.CrtMiscIO,video_misc_wr); - - outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */ - outb_p(info->vga_state.HorizontalTotal,vga_video_port_val); - outb_p(0x01,vga_video_port_reg); /* HorizDisplayEnd */ - outb_p(info->vga_state.HorizDisplayEnd,vga_video_port_val); - outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ - outb_p(info->vga_state.StartHorizRetrace,vga_video_port_val); - outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ - outb_p(info->vga_state.EndHorizRetrace,vga_video_port_val); - outb_p(0x07,vga_video_port_reg); /* Overflow */ - outb_p(info->vga_state.Overflow,vga_video_port_val); - outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ - outb_p(info->vga_state.StartVertRetrace,vga_video_port_val); - outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ - outb_p(info->vga_state.EndVertRetrace,vga_video_port_val); - outb_p(0x17,vga_video_port_reg); /* ModeControl */ - outb_p(info->vga_state.ModeControl,vga_video_port_val); - outb_p(0x01,seq_port_reg); /* ClockingMode */ - outb_p(info->vga_state.ClockingMode,seq_port_val); + vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO); + + /* HorizontalTotal */ + vga_io_wcrt(0x00, par->vga_state.HorizontalTotal); + /* HorizDisplayEnd */ + vga_io_wcrt(0x01, par->vga_state.HorizDisplayEnd); + /* StartHorizRetrace */ + vga_io_wcrt(0x04, par->vga_state.StartHorizRetrace); + /* EndHorizRetrace */ + vga_io_wcrt(0x05, par->vga_state.EndHorizRetrace); + /* Overflow */ + vga_io_wcrt(0x07, par->vga_state.Overflow); + /* StartVertRetrace */ + vga_io_wcrt(0x10, par->vga_state.StartVertRetrace); + /* EndVertRetrace */ + vga_io_wcrt(0x11, par->vga_state.EndVertRetrace); + /* ModeControl */ + vga_io_wcrt(0x17, par->vga_state.ModeControl); + /* ClockingMode */ + vga_io_wseq(0x01, par->vga_state.ClockingMode); /* restore index/control registers */ - outb_p(SeqCtrlIndex,seq_port_reg); - outb_p(CrtCtrlIndex,vga_video_port_reg); - sti(); + vga_io_w(seq_port_reg, SeqCtrlIndex); + vga_io_w(vga_video_port_reg, CrtCtrlIndex); + //sti(); } static void vga_pal_blank(void) @@ -711,127 +903,562 @@ static void vga_pal_blank(void) } /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ -static int vga16fb_blank(int blank, struct fb_info *fb_info) +static int vga16fb_blank(int blank, struct fb_info *info) { - struct vga16fb_info *info = (struct vga16fb_info*)fb_info; + struct vga16fb_par *par = (struct vga16fb_par *) info->par; switch (blank) { case 0: /* Unblank */ - if (info->vesa_blanked) { - vga_vesa_unblank(info); - info->vesa_blanked = 0; + if (par->vesa_blanked) { + vga_vesa_unblank(par); + par->vesa_blanked = 0; } - if (info->palette_blanked) { - do_install_cmap(fb_info->currcon, fb_info); - info->palette_blanked = 0; + if (par->palette_blanked) { + //do_install_cmap(info->currcon, info); + par->palette_blanked = 0; } break; case 1: /* blank */ vga_pal_blank(); - info->palette_blanked = 1; + par->palette_blanked = 1; break; default: /* VESA blanking */ - vga_vesa_blank(info, blank-1); - info->vesa_blanked = 1; + vga_vesa_blank(par, blank-1); + par->vesa_blanked = 1; break; } return 0; } +void vga_8planes_fillrect(struct fb_info *info, struct fb_fillrect *rect) +{ + char oldindex = getindex(); + char oldmode = setmode(0x40); + char oldmask = selectmask(); + int line_ofs, height; + char oldop, oldsr; + char *where; + + rect->dx /= 4; + where = info->screen_base + rect->dx + rect->dy * info->fix.line_length; + + if (rect->rop == ROP_COPY) { + oldop = setop(0); + oldsr = setsr(0); + + rect->width /= 4; + line_ofs = info->fix.line_length - rect->width; + setmask(0xff); + + height = rect->height; + + while (height--) { + int x; + + /* we can do memset... */ + for (x = rect->width; x > 0; --x) { + writeb(rect->color, where); + where++; + } + where += line_ofs; + } + } else { + char oldcolor = setcolor(0xf); + int y; + + oldop = setop(0x18); + oldsr = setsr(0xf); + setmask(0x0F); + for (y = 0; y < rect->height; y++) { + rmw(where); + rmw(where+1); + where += info->fix.line_length; + } + setcolor(oldcolor); + } + setmask(oldmask); + setsr(oldsr); + setop(oldop); + setmode(oldmode); + setindex(oldindex); +} + +void vga16fb_fillrect(struct fb_info *info, struct fb_fillrect *rect) +{ + int x, x2, y2, vxres, vyres, width, height, line_ofs; + char *dst; + + vxres = info->var.xres_virtual; + vyres = info->var.yres_virtual; + + if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres) + return; + + /* We could use hardware clipping but on many cards you get around + * hardware clipping by writing to framebuffer directly. */ + + x2 = rect->dx + rect->width; + y2 = rect->dy + rect->height; + x2 = x2 < vxres ? x2 : vxres; + y2 = y2 < vyres ? y2 : vyres; + rect->width = x2 - rect->dx; + + switch (info->fix.type) { + case FB_TYPE_VGA_PLANES: + if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { + + height = y2 - rect->dy; + width = rect->width/8; + + line_ofs = info->fix.line_length - width; + dst = info->screen_base + (rect->dx/8) + rect->dy * info->fix.line_length; + + switch (rect->rop) { + case ROP_COPY: + setmode(0); + setop(0); + setsr(0xf); + setcolor(rect->color); + selectmask(); + + setmask(0xff); + + while (height--) { + for (x = 0; x < width; x++) { + writeb(0, dst); + dst++; + } + dst += line_ofs; + } + break; + case ROP_XOR: + setmode(0); + setop(0x18); + setsr(0xf); + setcolor(0xf); + selectmask(); + + setmask(0xff); + while (height--) { + for (x = 0; x < width; x++) { + rmw(dst); + dst++; + } + dst += line_ofs; + } + break; + } + } 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); + break; + } +} + +void vga_8planes_copyarea(struct fb_info *info, struct fb_copyarea *area) +{ + int height, line_ofs, x; + char oldindex = getindex(); + char oldmode = setmode(0x41); + char oldop = setop(0); + char oldsr = setsr(0xf); + char *dest, *src; + + height = area->height; + + area->sx = area->sx / 4; + area->dx = area->dx / 4; + area->width = area->width / 4; + + if (area->dy < area->sy || (area->dy == area->sy && area->dx < area->sx)) { + line_ofs = info->fix.line_length - area->width; + dest = info->screen_base + area->dx + area->dy * info->fix.line_length; + src = info->screen_base + area->sx + area->sy * info->fix.line_length; + while (height--) { + for (x = 0; x < area->width; x++) { + readb(src); + writeb(0, dest); + src++; + dest++; + } + src += line_ofs; + dest += line_ofs; + } + } else { + line_ofs = info->fix.line_length - area->width; + dest = info->screen_base + area->dx + area->width + + (area->dy + height - 1) * info->fix.line_length; + src = info->screen_base + area->sx + area->width + + (area->sy + height - 1) * info->fix.line_length; + while (height--) { + for (x = 0; x < area->width; x++) { + --src; + --dest; + readb(src); + writeb(0, dest); + } + src -= line_ofs; + dest -= line_ofs; + } + } + + setsr(oldsr); + setop(oldop); + setmode(oldmode); + setindex(oldindex); +} + +void vga16fb_copyarea(struct fb_info *info, struct fb_copyarea *area) +{ + int x, x2, y2, old_dx, old_dy, vxres, vyres; + int height, width, line_ofs; + char *dst = NULL, *src = NULL; + + vxres = info->var.xres_virtual; + vyres = info->var.yres_virtual; + + if (area->dx > vxres || area->sx > vxres || area->dy > vyres || + area->sy > vyres) + return; + + /* clip the destination */ + old_dx = area->dx; + old_dy = area->dy; + + /* + * We could use hardware clipping but on many cards you get around + * hardware clipping by writing to framebuffer directly. + */ + x2 = area->dx + area->width; + y2 = area->dy + area->height; + area->dx = area->dx > 0 ? area->dx : 0; + area->dy = area->dy > 0 ? area->dy : 0; + x2 = x2 < vxres ? x2 : vxres; + y2 = y2 < vyres ? y2 : vyres; + area->width = x2 - area->dx; + area->height = y2 - area->dy; + + /* update sx1,sy1 */ + area->sx += (area->dx - old_dx); + area->sy += (area->dy - old_dy); + + /* the source must be completely inside the virtual screen */ + if (area->sx < 0 || area->sy < 0 || + (area->sx + area->width) > vxres || + (area->sy + area->height) > vyres) + return; + + switch (info->fix.type) { + case FB_TYPE_VGA_PLANES: + if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { + width = area->width/8; + height = area->height; + line_ofs = info->fix.line_length - width; + + setmode(1); + setop(0); + setsr(0xf); + + if (area->dy < area->sy || (area->dy == area->sy && area->dx < area->sx)) { + dst = info->screen_base + (area->dx/8) + area->dy * info->fix.line_length; + src = info->screen_base + (area->sx/8) + area->sy * info->fix.line_length; + while (height--) { + for (x = 0; x < width; x++) { + readb(src); + writeb(0, dst); + dst++; + src++; + } + src += line_ofs; + dst += line_ofs; + } + } else { + dst = info->screen_base + (area->dx/8) + width + + (area->dy + height - 1) * info->fix.line_length; + src = info->screen_base + (area->sx/8) + width + + (area->sy + height - 1) * info->fix.line_length; + while (height--) { + for (x = 0; x < width; x++) { + dst--; + src--; + readb(src); + writeb(0, dst); + } + src -= line_ofs; + dst -= line_ofs; + } + } + } 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); + break; + } +} + +#ifdef __LITTLE_ENDIAN +static unsigned int transl_l[] = +{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}; +static unsigned int transl_h[] = +{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, + 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}; +#else +#ifdef __BIG_ENDIAN +static unsigned int transl_h[] = +{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}; +static unsigned int transl_l[] = +{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, + 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}; +#else +#error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes" +#endif +#endif + +void vga_8planes_imageblit(struct fb_info *info, struct fb_image *image) +{ + char oldindex = getindex(); + char oldmode = setmode(0x40); + char oldop = setop(0); + char oldsr = setsr(0); + char oldmask = selectmask(); + u8 *cdat = image->data; + char *where; + int y; + + image->dx /= 4; + where = info->screen_base + image->dx + image->dy * info->fix.line_length; + + setmask(0xff); + writeb(image->bg_color, where); + readb(where); + selectmask(); + setmask(image->fg_color ^ image->bg_color); + setmode(0x42); + setop(0x18); + for (y = 0; y < image->height; y++, where += info->fix.line_length) + writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where); + setmask(oldmask); + setsr(oldsr); + setop(oldop); + setmode(oldmode); + setindex(oldindex); +} + +void vga_imageblit_expand(struct fb_info *info, struct fb_image *image) +{ + char *where = info->screen_base + (image->dx/8) + + image->dy * info->fix.line_length; + struct vga16fb_par *par = (struct vga16fb_par *) info->par; + u8 *cdat = image->data, *dst; + int x, y; + + switch (info->fix.type) { + case FB_TYPE_VGA_PLANES: + if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { + if (par->isVGA) { + setmode(2); + setop(0); + setsr(0xf); + setcolor(image->fg_color); + selectmask(); + + setmask(0xff); + writeb(image->bg_color, where); + rmb(); + readb(where); /* fill latches */ + setmode(3); + wmb(); + for (y = 0; y < image->height; y++) { + dst = where; + for (x = image->width/8; x--;) + writeb(*cdat++, dst++); + where += info->fix.line_length; + } + wmb(); + } else { + setmode(0); + setop(0); + setsr(0xf); + setcolor(image->bg_color); + selectmask(); + + setmask(0xff); + for (y = 0; y < image->height; y++) { + dst = where; + for (x=image->width/8; x--;){ + rmw(dst); + setcolor(image->fg_color); + selectmask(); + if (*cdat) { + setmask(*cdat++); + rmw(dst++); + } + } + where += info->fix.line_length; + } + } + } 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); + break; + } +} + +void vga_imageblit_color(struct fb_info *info, struct fb_image *image) +{ + /* + * Draw logo + */ + struct vga16fb_par *par = (struct vga16fb_par *) info->par; + char *where = info->screen_base + image->dy * info->fix.line_length + + image->dx/8; + char *cdat = image->data, *dst; + int x, y; + + switch (info->fix.type) { + case FB_TYPE_VGA_PLANES: + if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 && + par->isVGA) { + setsr(0xf); + setop(0); + setmode(0); + + for (y = 0; y < image->height; y++) { + for (x = 0; x < image->width; x++) { + dst = where + x/8; + + setcolor(*cdat); + selectmask(); + setmask(1 << (7 - (x % 8))); + fb_readb(dst); + fb_writeb(0, dst); + + cdat++; + } + where += info->fix.line_length; + } + } + break; + case FB_TYPE_PACKED_PIXELS: + cfb_imageblit(info, image); + break; + default: + break; + } +} + +void vga16fb_imageblit(struct fb_info *info, struct fb_image *image) +{ + if (image->depth == 1) + vga_imageblit_expand(info, image); + else if (image->depth == info->var.bits_per_pixel) + vga_imageblit_color(info, image); +} + static struct fb_ops vga16fb_ops = { - .owner = THIS_MODULE, - .fb_set_var = vga16fb_set_var, - .fb_get_cmap = gen_get_cmap, - .fb_set_cmap = gen_set_cmap, - .fb_setcolreg = vga16fb_setcolreg, - .fb_pan_display =vga16fb_pan_display, - .fb_blank = vga16fb_blank, + .owner = THIS_MODULE, + .fb_open = vga16fb_open, + .fb_release = vga16fb_release, + .fb_check_var = vga16fb_check_var, + .fb_set_par = vga16fb_set_par, + .fb_setcolreg = vga16fb_setcolreg, + .fb_pan_display = vga16fb_pan_display, + .fb_blank = vga16fb_blank, + .fb_fillrect = vga16fb_fillrect, + .fb_copyarea = vga16fb_copyarea, + .fb_imageblit = vga16fb_imageblit, + .fb_cursor = soft_cursor, }; int vga16fb_setup(char *options) { char *this_opt; - vga16fb.fb_info.fontname[0] = '\0'; - if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; - - if (!strncmp(this_opt, "font:", 5)) - strcpy(vga16fb.fb_info.fontname, this_opt+5); } return 0; } int __init vga16fb_init(void) { - int i,j; + int i; printk(KERN_DEBUG "vga16fb: initializing\n"); - /* XXX share VGA_FB_PHYS region with vgacon */ + /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ - vga16fb.video_vbase = ioremap(VGA_FB_PHYS, VGA_FB_PHYS_LEN); - if (!vga16fb.video_vbase) { + vga16fb.screen_base = ioremap(VGA_FB_PHYS, VGA_FB_PHYS_LEN); + if (!vga16fb.screen_base) { printk(KERN_ERR "vga16fb: unable to map device\n"); return -ENOMEM; } - printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.video_vbase); + printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.screen_base); - vga16fb.isVGA = ORIG_VIDEO_ISVGA; - vga16fb.palette_blanked = 0; - vga16fb.vesa_blanked = 0; + vga16_par.isVGA = ORIG_VIDEO_ISVGA; + vga16_par.palette_blanked = 0; + vga16_par.vesa_blanked = 0; - i = vga16fb.isVGA? 6 : 2; + i = vga16_par.isVGA? 6 : 2; vga16fb_defined.red.length = i; vga16fb_defined.green.length = i; vga16fb_defined.blue.length = i; - for(i = 0; i < 16; i++) { - j = color_table[i]; - palette[i].red = default_red[j]; - palette[i].green = default_grn[j]; - palette[i].blue = default_blu[j]; - } - /* XXX share VGA I/O region with vgacon and others */ + /* name should not depend on EGA/VGA */ + vga16fb.node = NODEV; + vga16fb.fbops = &vga16fb_ops; + vga16fb.var = vga16fb_defined; + vga16fb.fix = vga16fb_fix; + vga16fb.par = &vga16_par; + vga16fb.flags = FBINFO_FLAG_DEFAULT; - disp.var = vga16fb_defined; + i = (vga16fb_defined.bits_per_pixel == 8) ? 256 : 16; + fb_alloc_cmap(&vga16fb.cmap, i, 0); - strcpy(vga16fb.fb_info.modename, vga16fb_fix.id); - vga16fb.fb_info.changevar = NULL; - vga16fb.fb_info.node = NODEV; - vga16fb.fb_info.var = vga16fb_defined; - vga16fb.fb_info.fix = vga16fb_fix; - vga16fb.fb_info.fbops = &vga16fb_ops; - vga16fb.fb_info.screen_base = vga16fb.video_vbase; - vga16fb.fb_info.disp=&disp; - vga16fb.fb_info.currcon = -1; - vga16fb.fb_info.switch_con=&gen_switch; - vga16fb.fb_info.updatevar=&gen_update_var; - vga16fb.fb_info.flags=FBINFO_FLAG_DEFAULT; - vga16fb_set_disp(-1, &vga16fb); + if (vga16fb_check_var(&vga16fb.var, &vga16fb)) + return -EINVAL; - fb_alloc_cmap(&vga16fb.fb_info.cmap, 16, 0); + vga16fb_update_fix(&vga16fb); - if (register_framebuffer(&vga16fb.fb_info)<0) { - iounmap(vga16fb.video_vbase); + if (register_framebuffer(&vga16fb) < 0) { + iounmap(vga16fb.screen_base); return -EINVAL; } printk(KERN_INFO "fb%d: %s frame buffer device\n", - GET_FB_IDX(vga16fb.fb_info.node), vga16fb.fb_info.modename); + minor(vga16fb.node), vga16fb.fix.id); return 0; } static void __exit vga16fb_exit(void) { - unregister_framebuffer(&vga16fb.fb_info); - iounmap(vga16fb.video_vbase); + unregister_framebuffer(&vga16fb); + iounmap(vga16fb.screen_base); /* XXX unshare VGA regions */ } diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c new file mode 100644 index 000000000000..2b6fc7dea40e --- /dev/null +++ b/drivers/video/vgastate.c @@ -0,0 +1,438 @@ +/* + * linux/include/video/vgastate.c -- VGA state save/restore + * + * Copyright 2002 James Simmons + * + * Copyright history from vga16fb.c: + * Copyright 1999 Ben Pfaff and Petr Vandrovec + * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm + * Based on VESA framebuffer (c) 1998 Gerd Knorr + * + * 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/config.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/fb.h> + +#include "vga.h" + +static inline unsigned char vga_rcrtcs(caddr_t regbase, unsigned short iobase, + unsigned char reg) +{ + vga_w(regbase, iobase + 0x4, reg); + return vga_r(regbase, iobase + 0x5); +} + +static inline void vga_wcrtcs(caddr_t regbase, unsigned short iobase, + unsigned char reg, unsigned char val) +{ + vga_w(regbase, iobase + 0x4, reg); + vga_w(regbase, iobase + 0x5, val); +} + +static void save_vga_text(struct fb_vgastate *state) +{ + int i; + u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4; + + /* if in graphics mode, no need to save */ + attr10 = vga_rattr(state->vgabase, 0x10); + if (attr10 & 1) + return; + + /* save regs */ + misc = vga_r(state->vgabase, VGA_MIS_R); + gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ); + gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE); + gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC); + seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE); + seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE); + + /* force graphics mode */ + vga_w(state->vgabase, VGA_MIS_W, misc | 1); + + /* blank screen */ + seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE); + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); + vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5); + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); + + /* save font 0 */ + if (state->flags & VGA_SAVE_FONT0) { + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); + vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2); + vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); + vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); + for (i = 0; i < 8 * 8192; i++) + state->vga_font0[i] = vga_r(state->fbbase, i); + } + /* save font 1 */ + if (state->flags & VGA_SAVE_FONT1) { + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); + 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 < 8 * 8192; i++) + state->vga_font1[i] = vga_r(state->fbbase, i); + } + /* save font 2 */ + if (state->flags & VGA_SAVE_TEXT) { + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); + vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0); + vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); + vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); + for (i = 0; i < 2 * 8192; i++) + state->vga_text[i] = vga_r(state->fbbase, i); + + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); + vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1); + vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); + vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); + for (i = 0; i < 2 * 8192; i++) + state->vga_text[i] = vga_r(state->fbbase + + 2 * 8192, i); + } + + /* restore regs */ + vga_wattr(state->vgabase, 0x10, attr10); + + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4); + + vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4); + vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5); + vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6); + vga_w(state->vgabase, VGA_MIS_W, misc); + + /* unblank screen */ + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); + vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5)); + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); + + vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1); +} + +static void restore_vga_text(struct fb_vgastate *state) +{ + int i; + u8 misc, gr1, gr3, gr4, gr5, gr6, gr8; + u8 seq1, seq2, seq4; + + /* save regs */ + misc = vga_r(state->vgabase, VGA_MIS_R); + gr1 = vga_rgfx(state->vgabase, VGA_GFX_SR_ENABLE); + gr3 = vga_rgfx(state->vgabase, VGA_GFX_DATA_ROTATE); + gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ); + gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE); + gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC); + gr8 = vga_rgfx(state->vgabase, VGA_GFX_BIT_MASK); + seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE); + seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE); + + /* force graphics mode */ + vga_w(state->vgabase, VGA_MIS_W, misc | 1); + + /* blank screen */ + seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE); + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); + vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5); + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); + + if (state->depth == 4) { + vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, 0x0); + vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, 0xff); + vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, 0x00); + } + /* restore font 0 */ + if (state->flags & VGA_SAVE_FONT0) { + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); + vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2); + vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); + vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); + for (i = 0; i < 8 * 8192; i++) + vga_w(state->fbbase, i, state->vga_font0[i]); + } + /* restore font 1 */ + if (state->flags & VGA_SAVE_FONT1) { + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); + 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 < 8 * 8192; i++) + vga_w(state->fbbase, i, state->vga_font1[i]); + } + /* restore font 2 */ + if (state->flags & VGA_SAVE_TEXT) { + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); + vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0); + vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); + vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); + for (i = 0; i < 2 * 8192; i++) + vga_w(state->fbbase, i, state->vga_text[i]); + + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); + vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1); + vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); + vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); + for (i = 0; i < 2 * 8192; i++) + vga_w(state->fbbase + 2 * 8192, i, + state->vga_text[i]); + } + /* unblank screen */ + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); + vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5)); + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); + + /* restore regs */ + vga_w(state->vgabase, VGA_MIS_W, misc); + + vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, gr1); + vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, gr3); + vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4); + vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5); + vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6); + vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, gr8); + + vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1); + vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2); + vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4); +} + +static void save_vga_mode(struct fb_vgastate *state) +{ + unsigned short iobase; + int i; + + state->misc = vga_r(state->vgabase, VGA_MIS_R); + if (state->misc & 1) + iobase = 0x3d0; + else + iobase = 0x3b0; + + for (i = 0; i < state->num_crtc; i++) + state->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i); + + vga_r(state->vgabase, iobase + 0xa); + vga_w(state->vgabase, VGA_ATT_W, 0x00); + for (i = 0; i < state->num_attr; i++) { + vga_r(state->vgabase, iobase + 0xa); + state->attr[i] = vga_rattr(state->vgabase, i); + } + vga_r(state->vgabase, iobase + 0xa); + vga_w(state->vgabase, VGA_ATT_W, 0x20); + + for (i = 0; i < state->num_gfx; i++) + state->gfx[i] = vga_rgfx(state->vgabase, i); + + for (i = 0; i < state->num_seq; i++) + state->seq[i] = vga_rseq(state->vgabase, i); +} + +static void restore_vga_mode(struct fb_vgastate *state) +{ + unsigned short iobase; + int i; + + vga_w(state->vgabase, VGA_MIS_W, state->misc); + + if (state->misc & 1) + iobase = 0x3d0; + else + iobase = 0x3b0; + + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01); + vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, + state->seq[VGA_SEQ_CLOCK_MODE] | 0x20); + + for (i = 2; i < state->num_seq; i++) + vga_wseq(state->vgabase, i, state->seq[i]); + + vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03); + + /* unprotect vga regs */ + vga_wcrtcs(state->vgabase, iobase, 17, state->crtc[17] & ~0x80); + for (i = 0; i < state->num_crtc; i++) + vga_wcrtcs(state->vgabase, iobase, i, state->crtc[i]); + + for (i = 0; i < state->num_gfx; i++) + vga_wgfx(state->vgabase, i, state->gfx[i]); + + vga_r(state->vgabase, iobase + 0xa); + vga_w(state->vgabase, VGA_ATT_W, 0x00); + for (i = 0; i < state->num_attr; i++) { + vga_r(state->vgabase, iobase + 0xa); + vga_wattr(state->vgabase, i, state->attr[i]); + } + + vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, + state->seq[VGA_SEQ_CLOCK_MODE]); + + vga_r(state->vgabase, iobase + 0xa); + vga_w(state->vgabase, VGA_ATT_W, 0x20); +} + +static void save_vga_cmap(struct fb_vgastate *state) +{ + int i; + + vga_w(state->vgabase, VGA_PEL_MSK, 0xff); + + /* assumes DAC is readable and writable */ + vga_w(state->vgabase, VGA_PEL_IR, 0x00); + for (i = 0; i < 768; i++) + state->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D); +} + +static void restore_vga_cmap(struct fb_vgastate *state) +{ + int i; + + vga_w(state->vgabase, VGA_PEL_MSK, 0xff); + + vga_w(state->vgabase, VGA_PEL_IW, 0x00); + for (i = 0; i < 768; i++) + vga_w(state->vgabase, VGA_PEL_D, state->vga_cmap[i]); +} + +static void vga_cleanup(struct fb_vgastate *state) +{ + if (state->vga_font0) + kfree(state->vga_font0); + if (state->vga_font1) + kfree(state->vga_font1); + if (state->vga_text) + kfree(state->vga_text); + if (state->fbbase) + iounmap(state->fbbase); + if (state->vga_cmap) + kfree(state->vga_cmap); + if (state->attr) + kfree(state->attr); + if (state->crtc) + kfree(state->crtc); + if (state->gfx) + kfree(state->gfx); + if (state->seq) + kfree(state->seq); +} + +int fb_save_vga(struct fb_vgastate *state) +{ + state->vga_font0 = NULL; + state->vga_font1 = NULL; + state->vga_text = NULL; + state->vga_cmap = NULL; + state->attr = NULL; + state->crtc = NULL; + state->gfx = NULL; + state->seq = NULL; + + if (state->flags & VGA_SAVE_CMAP) { + state->vga_cmap = kmalloc(768, GFP_KERNEL); + if (!state->vga_cmap) { + vga_cleanup(state); + return 1; + } + save_vga_cmap(state); + } + + if (state->flags & VGA_SAVE_MODE) { + if (state->num_attr < 21) + state->num_attr = 21; + if (state->num_crtc < 25) + state->num_crtc = 25; + if (state->num_gfx < 9) + state->num_gfx = 9; + if (state->num_seq < 5) + state->num_seq = 5; + state->attr = kmalloc(state->num_attr, GFP_KERNEL); + state->crtc = kmalloc(state->num_crtc, GFP_KERNEL); + state->gfx = kmalloc(state->num_gfx, GFP_KERNEL); + state->seq = kmalloc(state->num_seq, GFP_KERNEL); + if (!state->attr || !state->crtc || !state->gfx || + !state->seq) { + vga_cleanup(state); + return 1; + } + save_vga_mode(state); + } + + if (state->flags & VGA_SAVE_FONT0) { + state->vga_font0 = kmalloc(8192 * 8, GFP_KERNEL); + if (!state->vga_font0) { + vga_cleanup(state); + return 1; + } + } + if (state->flags & VGA_SAVE_FONT1) { + state->vga_font1 = kmalloc(8192 * 8, GFP_KERNEL); + if (!state->vga_font1) { + vga_cleanup(state); + return 1; + } + } + if (state->flags & VGA_SAVE_TEXT) { + state->vga_text = kmalloc(8192 * 4, GFP_KERNEL); + if (!state->vga_text) { + vga_cleanup(state); + return 1; + } + } + if (state->flags & VGA_SAVE_FONTS) { + state->fbbase = ioremap(0xA0000, 8 * 8192); + if (!state->fbbase) { + vga_cleanup(state); + return 1; + } + save_vga_text(state); + iounmap(state->fbbase); + state->fbbase = NULL; + } + return 0; +} + +int fb_restore_vga (struct fb_vgastate *state) +{ + if (state->flags & VGA_SAVE_MODE) + restore_vga_mode(state); + + if (state->flags & VGA_SAVE_FONTS) { + state->fbbase = ioremap(0xA0000, 8 * 8192); + if (!state->fbbase) { + vga_cleanup(state); + return 1; + } + restore_vga_text(state); + } + + if (state->flags & VGA_SAVE_CMAP) + restore_vga_cmap(state); + + vga_cleanup(state); + return 0; +} + +#ifdef MODULE +int init_module(void) { return 0; }; +void cleanup_module(void) {}; +#endif + +EXPORT_SYMBOL(fb_save_vga); +EXPORT_SYMBOL(fb_restore_vga); + +MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); +MODULE_DESCRIPTION("VGA State Save/Restore"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c index 72039504e9e7..e9a54e973e04 100644 --- a/drivers/video/virgefb.c +++ b/drivers/video/virgefb.c @@ -1806,7 +1806,7 @@ int __init virgefb_init(void) } printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n", - GET_FB_IDX(fb_info.node), fb_info.modename, v_ram_size>>10); + minor(fb_info.node), fb_info.modename, v_ram_size>>10); /* TODO: This driver cannot be unloaded yet */ diff --git a/include/linux/console.h b/include/linux/console.h index 646e0eaa9fb3..37b441e6dfd8 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -40,6 +40,7 @@ struct consw { int (*con_switch)(struct vc_data *); int (*con_blank)(struct vc_data *, int); int (*con_font_op)(struct vc_data *, struct console_font_op *); + int (*con_resize)(struct vc_data *, unsigned int, unsigned int); int (*con_set_palette)(struct vc_data *, unsigned char *); int (*con_scrolldelta)(struct vc_data *, int); int (*con_set_origin)(struct vc_data *); diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index d86c16e96d11..153f71db1f38 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -27,6 +27,7 @@ struct vc_data { unsigned char vc_halfcolor; /* Color for half intensity mode */ unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */ unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */ + struct console_font_op vc_font; /* Current VC font set */ unsigned short vc_video_erase_char; /* Background erase character */ unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */ unsigned int vc_x, vc_y; /* Cursor position */ diff --git a/include/linux/fb.h b/include/linux/fb.h index cda1c818f68c..a3031b2a13c4 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -3,6 +3,7 @@ #include <linux/tty.h> #include <asm/types.h> +#include <asm/io.h> /* Definitions of frame buffers */ @@ -17,6 +18,7 @@ #define FBIOGETCMAP 0x4604 #define FBIOPUTCMAP 0x4605 #define FBIOPAN_DISPLAY 0x4606 +#define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor) /* 0x4607-0x460B are defined below */ /* #define FBIOGET_MONITORSPEC 0x460C */ /* #define FBIOPUT_MONITORSPEC 0x460D */ @@ -208,7 +210,8 @@ struct fb_var_screeninfo { __u32 vsync_len; /* length of vertical sync */ __u32 sync; /* see FB_SYNC_* */ __u32 vmode; /* see FB_VMODE_* */ - __u32 reserved[6]; /* Reserved for future compatibility */ + __u32 rotate; /* angle we rotate counter clockwise */ + __u32 reserved[5]; /* Reserved for future compatibility */ }; struct fb_cmap { @@ -262,12 +265,12 @@ struct fb_vblank { #define ROP_XOR 1 struct fb_copyarea { - __u32 sx; /* screen-relative */ - __u32 sy; - __u32 width; - __u32 height; __u32 dx; __u32 dy; + __u32 width; + __u32 height; + __u32 sx; + __u32 sy; }; struct fb_fillrect { @@ -280,23 +283,76 @@ struct fb_fillrect { }; struct fb_image { - __u32 width; /* Size of image */ + __u32 dx; /* Where to place image */ + __u32 dy; + __u32 width; /* Size of image */ __u32 height; - __u16 dx; /* Where to place image */ - __u16 dy; - __u32 fg_color; /* Only used when a mono bitmap */ + __u32 fg_color; /* Only used when a mono bitmap */ __u32 bg_color; - __u8 depth; /* Dpeth of the image */ - char *data; /* Pointer to image data */ + __u8 depth; /* Depth of the image */ + char *data; /* Pointer to image data */ + struct fb_cmap cmap; /* color map info */ }; -#ifdef __KERNEL__ +/* + * hardware cursor control + */ -#if 1 /* to go away in 2.5.0 */ -extern int GET_FB_IDX(kdev_t rdev); -#else -#define GET_FB_IDX(node) (minor(node)) -#endif +#define FB_CUR_SETCUR 0x01 +#define FB_CUR_SETPOS 0x02 +#define FB_CUR_SETHOT 0x04 +#define FB_CUR_SETCMAP 0x08 +#define FB_CUR_SETSHAPE 0x10 +#define FB_CUR_SETDEST 0x20 +#define FB_CUR_SETSIZE 0x40 +#define FB_CUR_SETALL 0xFF + +struct fbcurpos { + __u16 x, y; +}; + +struct fb_cursor { + __u16 set; /* what to set */ + __u16 enable; /* cursor on/off */ + __u16 rop; /* bitop operation */ + char *mask; /* cursor mask bits */ + char *dest; /* destination */ + struct fbcurpos hot; /* cursor hot spot */ + struct fb_image image; /* Cursor image */ +}; + +/* VGA State Save and Restore */ +#define VGA_SAVE_FONT0 1 /* save/restore plane 2 fonts */ +#define VGA_SAVE_FONT1 2 /* save/restore plane 3 fonts */ +#define VGA_SAVE_TEXT 4 /* save/restore plane 0/1 fonts */ +#define VGA_SAVE_FONTS 7 /* save/restore all fonts */ +#define VGA_SAVE_MODE 8 /* save/restore video mode */ +#define VGA_SAVE_CMAP 16 /* save/restore color map/DAC */ + +struct fb_vgastate { + caddr_t vgabase; /* mmio base, if supported */ + __u32 flags; /* what state/s to save (see VGA_SAVE_*) */ + __u32 depth; /* current fb depth, not important */ + __u32 num_attr; /* number of att registers, 0 for default */ + __u32 num_crtc; /* number of crt registers, 0 for default */ + __u32 num_gfx; /* number of gfx registers, 0 for default */ + __u32 num_seq; /* number of seq registers, 0 for default */ + caddr_t fbbase; /* -- DO NOT ALTER STARTING HERE -- */ + __u8 *vga_font0; + __u8 *vga_font1; + __u8 *vga_text; + __u8 *vga_cmap; + __u8 *attr; + __u8 *crtc; + __u8 *gfx; + __u8 *seq; + __u8 misc; +}; + +extern int fb_save_vga(struct fb_vgastate *state); +extern int fb_restore_vga(struct fb_vgastate *state); + +#ifdef __KERNEL__ #include <linux/fs.h> #include <linux/poll.h> @@ -316,15 +372,9 @@ struct fb_ops { struct module *owner; int (*fb_open)(struct fb_info *info, int user); int (*fb_release)(struct fb_info *info, int user); - /* set settable parameters */ - int (*fb_set_var)(struct fb_var_screeninfo *var, int con, - struct fb_info *info); - /* get colormap */ - int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info); - /* set colormap */ - int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info); + /* For framebuffers with strange non linear layouts */ + ssize_t (*fb_read)(struct file *file, char *buf, size_t count, loff_t *ppos); + ssize_t (*fb_write)(struct file *file, const char *buf, size_t count, loff_t *ppos); /* checks var and creates a par based on it */ int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info); /* set the video mode according to par */ @@ -335,26 +385,29 @@ struct fb_ops { /* blank display */ int (*fb_blank)(int blank, struct fb_info *info); /* pan display */ - int (*fb_pan_display)(struct fb_var_screeninfo *var, int con, struct fb_info *info); + int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); /* draws a rectangle */ void (*fb_fillrect)(struct fb_info *info, struct fb_fillrect *rect); /* Copy data from area to another */ void (*fb_copyarea)(struct fb_info *info, struct fb_copyarea *region); /* Draws a image to the display */ void (*fb_imageblit)(struct fb_info *info, struct fb_image *image); + /* Draws cursor */ + int (*fb_cursor)(struct fb_info *info, struct fb_cursor *cursor); + /* Rotates the display */ + void (*fb_rotate)(struct fb_info *info, int angle); /* perform polling on fb device */ int (*fb_poll)(struct fb_info *info, poll_table *wait); + /* wait for blit idle, optional */ + int (*fb_sync)(struct fb_info *info); /* perform fb specific ioctl (optional) */ int (*fb_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); /* perform fb specific mmap */ int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); - /* switch to/from raster image mode */ - int (*fb_rasterimg)(struct fb_info *info, int start); }; struct fb_info { - char modename[40]; /* default video mode */ kdev_t node; int flags; int open; /* Has this been open already ? */ @@ -362,18 +415,12 @@ struct fb_info { struct fb_var_screeninfo var; /* Current var */ struct fb_fix_screeninfo fix; /* Current fix */ struct fb_monspecs monspecs; /* Current Monitor specs */ + struct fb_cursor cursor; /* Current cursor */ struct fb_cmap cmap; /* Current cmap */ struct fb_ops *fbops; char *screen_base; /* Virtual address */ - struct display *disp; /* initial display variable */ struct vc_data *display_fg; /* Console visible on this display */ int currcon; /* Current VC. */ - char fontname[40]; /* default font name */ - int (*changevar)(int); /* tell console var has changed */ - int (*switch_con)(int, struct fb_info*); - /* tell fb to switch consoles */ - int (*updatevar)(int, struct fb_info*); - /* tell fb to update the vars */ void *pseudo_palette; /* Fake palette of 16 colors and the cursor's color for non palette mode */ @@ -387,31 +434,53 @@ struct fb_info { #define FBINFO_FLAG_DEFAULT 0 #endif - /* - * `Generic' versions of the frame buffer device operations - */ +#if defined(__sparc__) -extern int gen_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info); -extern int gen_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info); -extern int gen_set_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info); -extern int fb_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *info); -extern void cfb_fillrect(struct fb_info *info, struct fb_fillrect *rect); -extern void cfb_copyarea(struct fb_info *info, struct fb_copyarea *region); -extern void cfb_imageblit(struct fb_info *info, struct fb_image *image); +/* We map all of our framebuffers such that big-endian accesses + * are what we want, so the following is sufficient. + */ + +#define fb_readb sbus_readb +#define fb_readw sbus_readw +#define fb_readl sbus_readl +#define fb_writeb sbus_writeb +#define fb_writew sbus_writew +#define fb_writel sbus_writel +#define fb_memset sbus_memset_io + +#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) + +#define fb_readb __raw_readb +#define fb_readw __raw_readw +#define fb_readl __raw_readl +#define fb_writeb __raw_writeb +#define fb_writew __raw_writew +#define fb_writel __raw_writel +#define fb_memset memset_io + +#else + +#define fb_readb(addr) (*(volatile u8 *) (addr)) +#define fb_readw(addr) (*(volatile u16 *) (addr)) +#define fb_readl(addr) (*(volatile u32 *) (addr)) +#define fb_writeb(b,addr) (*(volatile u8 *) (addr) = (b)) +#define fb_writew(b,addr) (*(volatile u16 *) (addr) = (b)) +#define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b)) +#define fb_memset memset + +#endif /* - * Helper functions + * `Generic' versions of the frame buffer device operations */ -extern void do_install_cmap(int con, struct fb_info *info); -extern int gen_update_var(int con, struct fb_info *info); +extern int fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info); +extern int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); extern int fb_blank(int blank, struct fb_info *info); -extern int gen_switch(int con, struct fb_info *info); -extern void gen_set_disp(int con, struct fb_info *info); +extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); +extern void cfb_fillrect(struct fb_info *info, struct fb_fillrect *rect); +extern void cfb_copyarea(struct fb_info *info, struct fb_copyarea *area); +extern void cfb_imageblit(struct fb_info *info, struct fb_image *image); /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); @@ -427,12 +496,9 @@ extern int fbmon_dpms(const struct fb_info *fb_info); /* drivers/video/fbcmap.c */ extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); +extern void fb_dealloc_cmap(struct fb_cmap *cmap); extern void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto); -extern int fb_get_cmap(struct fb_cmap *cmap, int kspc, - int (*getcolreg)(u_int, u_int *, u_int *, u_int *, - u_int *, struct fb_info *), - struct fb_info *fb_info); extern int fb_set_cmap(struct fb_cmap *cmap, int kspc, struct fb_info *fb_info); extern struct fb_cmap *fb_default_cmap(int len); extern void fb_invert_cmaps(void); @@ -491,54 +557,4 @@ extern int __init fb_find_mode(struct fb_var_screeninfo *var, #endif /* __KERNEL__ */ -#if 1 - -#define FBCMD_GET_CURRENTPAR 0xDEAD0005 -#define FBCMD_SET_CURRENTPAR 0xDEAD8005 - -#endif - - -#if 1 /* Preliminary */ - - /* - * Hardware Cursor - */ - -#define FBIOGET_FCURSORINFO 0x4607 -#define FBIOGET_VCURSORINFO 0x4608 -#define FBIOPUT_VCURSORINFO 0x4609 -#define FBIOGET_CURSORSTATE 0x460A -#define FBIOPUT_CURSORSTATE 0x460B - - -struct fb_fix_cursorinfo { - __u16 crsr_width; /* width and height of the cursor in */ - __u16 crsr_height; /* pixels (zero if no cursor) */ - __u16 crsr_xsize; /* cursor size in display pixels */ - __u16 crsr_ysize; - __u16 crsr_color1; /* colormap entry for cursor color1 */ - __u16 crsr_color2; /* colormap entry for cursor color2 */ -}; - -struct fb_var_cursorinfo { - __u16 width; - __u16 height; - __u16 xspot; - __u16 yspot; - __u8 data[1]; /* field with [height][width] */ -}; - -struct fb_cursorstate { - __s16 xoffset; - __s16 yoffset; - __u16 mode; -}; - -#define FB_CURSOR_OFF 0 -#define FB_CURSOR_ON 1 -#define FB_CURSOR_FLASH 2 - -#endif /* Preliminary */ - #endif /* _LINUX_FB_H */ diff --git a/include/linux/radeonfb.h b/include/linux/radeonfb.h new file mode 100644 index 000000000000..99bdf91bbc5d --- /dev/null +++ b/include/linux/radeonfb.h @@ -0,0 +1,15 @@ +#ifndef __LINUX_RADEONFB_H__ +#define __LINUX_RADEONFB_H__ + +#include <asm/ioctl.h> +#include <asm/types.h> + +#define ATY_RADEON_LCD_ON 0x00000001 +#define ATY_RADEON_CRT_ON 0x00000002 + + +#define FBIO_RADEON_GET_MIRROR _IOR('@', 3, sizeof(__u32*)) +#define FBIO_RADEON_SET_MIRROR _IOW('@', 4, sizeof(__u32*)) + +#endif + diff --git a/include/linux/sisfb.h b/include/linux/sisfb.h index 4d12567013ba..f45257643986 100644 --- a/include/linux/sisfb.h +++ b/include/linux/sisfb.h @@ -1,6 +1,11 @@ #ifndef _LINUX_SISFB #define _LINUX_SISFB +#include <linux/spinlock.h> + +#include <asm/ioctl.h> +#include <asm/types.h> + #define DISPTYPE_CRT1 0x00000008L #define DISPTYPE_CRT2 0x00000004L #define DISPTYPE_LCD 0x00000002L @@ -20,6 +25,7 @@ #define HASVB_303 0x40 #define HASVB_CHRONTEL 0x80 +/* TW: *Never* change the order of the following enum */ typedef enum _SIS_CHIP_TYPE { SIS_VGALegacy = 0, SIS_300, @@ -32,10 +38,17 @@ typedef enum _SIS_CHIP_TYPE { SIS_315PRO, SIS_640, SIS_740, - SIS_330, + SIS_650, + SIS_330, MAX_SIS_CHIP } SIS_CHIP_TYPE; +typedef enum _VGA_ENGINE { + UNKNOWN_VGA = 0, + SIS_300_VGA, + SIS_315_VGA, +} VGA_ENGINE; + typedef enum _TVTYPE { TVMODE_NTSC = 0, TVMODE_PAL, @@ -81,21 +94,25 @@ struct ap_data { }; struct video_info { - int chip_id; + int chip_id; unsigned int video_size; unsigned long video_base; - char *video_vbase; + char * video_vbase; unsigned long mmio_base; - char *mmio_vbase; + char * mmio_vbase; unsigned long vga_base; + unsigned long mtrr; + unsigned long heapstart; int video_bpp; + int video_cmap_len; int video_width; int video_height; int video_vwidth; int video_vheight; int org_x; int org_y; + int video_linelength; unsigned int refresh_rate; unsigned long disp_state; @@ -106,9 +123,42 @@ struct video_info { SIS_CHIP_TYPE chip; unsigned char revision_id; + unsigned short DstColor; /* TW: For 2d acceleration */ + unsigned long SiS310_AccelDepth; + unsigned long CommandReg; + + spinlock_t lockaccel; + char reserved[256]; }; + +/* TW: Addtional IOCTL for communication sisfb <> X driver */ +/* If changing this, vgatypes.h must also be changed (for X driver) */ + +/* TW: ioctl for identifying and giving some info (esp. memory heap start) */ +#define SISFB_GET_INFO _IOR('n',0xF8,sizeof(__u32)) + +/* TW: Structure argument for SISFB_GET_INFO ioctl */ +typedef struct _SISFB_INFO sisfb_info, *psisfb_info; + +struct _SISFB_INFO { + unsigned long sisfb_id; /* for identifying sisfb */ +#ifndef SISFB_ID +#define SISFB_ID 0x53495346 /* Identify myself with 'SISF' */ +#endif + int chip_id; /* PCI ID of detected chip */ + int memory; /* video memory in KB which sisfb manages */ + int heapstart; /* heap start (= sisfb "mem" argument) in KB */ + unsigned char fbvidmode; /* current sisfb mode */ + + unsigned char sisfb_version; + unsigned char sisfb_revision; + unsigned char sisfb_patchlevel; + + char reserved[253]; /* for future use */ +}; + #ifdef __KERNEL__ extern struct video_info ivideo; diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 6d0b234f5a61..d611200c749d 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -10,6 +10,7 @@ #include <linux/vt.h> #include <linux/kd.h> #include <linux/tty.h> +#include <linux/console_struct.h> /* * Presently, a lot of graphics programs do not restore the contents of @@ -37,14 +38,9 @@ extern int kbd_rate(struct kbd_repeat *rep); /* console.c */ -struct console_font_op; - int vc_allocate(unsigned int console); int vc_cons_allocated(unsigned int console); -int vc_resize(unsigned int lines, unsigned int cols, - unsigned int first, unsigned int last); -#define vc_resize_all(l, c) vc_resize(l, c, 0, MAX_NR_CONSOLES-1) -#define vc_resize_con(l, c, x) vc_resize(l, c, x, x) +int vc_resize(int currcons, unsigned int cols, unsigned int lines); void vc_disallocate(unsigned int console); void reset_palette(int currcons); void set_palette(int currcons); diff --git a/include/video/fbcon-afb.h b/include/video/fbcon-afb.h deleted file mode 100644 index cbbcf0019ad9..000000000000 --- a/include/video/fbcon-afb.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for Amiga bitplanes (afb) - */ - -#ifndef _VIDEO_FBCON_AFB_H -#define _VIDEO_FBCON_AFB_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_AFB_MODULE) -#define FBCON_HAS_AFB -#endif -#else -#if defined(CONFIG_FBCON_AFB) -#define FBCON_HAS_AFB -#endif -#endif - -extern struct display_switch fbcon_afb; -extern void fbcon_afb_setup(struct display *p); -extern void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_afb_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_afb_revc(struct display *p, int xx, int yy); - -#endif diff --git a/include/video/fbcon-cfb16.h b/include/video/fbcon-cfb16.h deleted file mode 100644 index 3ccc7d7cd535..000000000000 --- a/include/video/fbcon-cfb16.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * FBcon low-level driver for 16 bpp packed pixel (cfb16) - */ - -#ifndef _VIDEO_FBCON_CFB16_H -#define _VIDEO_FBCON_CFB16_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB16_MODULE) -#define FBCON_HAS_CFB16 -#endif -#else -#if defined(CONFIG_FBCON_CFB16) -#define FBCON_HAS_CFB16 -#endif -#endif - -extern struct display_switch fbcon_cfb16; -extern void fbcon_cfb16_setup(struct display *p); -extern void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, - int dx, int height, int width); -extern void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_cfb16_revc(struct display *p, int xx, int yy); -extern void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only); - -#endif /* _VIDEO_FBCON_CFB16_H */ diff --git a/include/video/fbcon-cfb2.h b/include/video/fbcon-cfb2.h deleted file mode 100644 index 5ba68a5f0a4f..000000000000 --- a/include/video/fbcon-cfb2.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for 2 bpp packed pixel (cfb2) - */ - -#ifndef _VIDEO_FBCON_CFB2_H -#define _VIDEO_FBCON_CFB2_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_CFB2) || defined(CONFIG_FBCON_CFB2_MODULE) -#define FBCON_HAS_CFB2 -#endif -#else -#if defined(CONFIG_FBCON_CFB2) -#define FBCON_HAS_CFB2 -#endif -#endif - -extern struct display_switch fbcon_cfb2; -extern void fbcon_cfb2_setup(struct display *p); -extern void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_cfb2_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_cfb2_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_CFB2_H */ diff --git a/include/video/fbcon-cfb24.h b/include/video/fbcon-cfb24.h deleted file mode 100644 index 77442e22d2af..000000000000 --- a/include/video/fbcon-cfb24.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * FBcon low-level driver for 24 bpp packed pixel (cfb24) - */ - -#ifndef _VIDEO_FBCON_CFB24_H -#define _VIDEO_FBCON_CFB24_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_CFB24) || defined(CONFIG_FBCON_CFB24_MODULE) -#define FBCON_HAS_CFB24 -#endif -#else -#if defined(CONFIG_FBCON_CFB24) -#define FBCON_HAS_CFB24 -#endif -#endif - -extern struct display_switch fbcon_cfb24; -extern void fbcon_cfb24_setup(struct display *p); -extern void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy, - int dx, int height, int width); -extern void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_cfb24_revc(struct display *p, int xx, int yy); -extern void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only); - -#endif /* _VIDEO_FBCON_CFB24_H */ diff --git a/include/video/fbcon-cfb32.h b/include/video/fbcon-cfb32.h deleted file mode 100644 index abac3baa2f37..000000000000 --- a/include/video/fbcon-cfb32.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * FBcon low-level driver for 32 bpp packed pixel (cfb32) - */ - -#ifndef _VIDEO_FBCON_CFB32_H -#define _VIDEO_FBCON_CFB32_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FBCON_CFB32_MODULE) -#define FBCON_HAS_CFB32 -#endif -#else -#if defined(CONFIG_FBCON_CFB32) -#define FBCON_HAS_CFB32 -#endif -#endif - -extern struct display_switch fbcon_cfb32; -extern void fbcon_cfb32_setup(struct display *p); -extern void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy, - int dx, int height, int width); -extern void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_cfb32_revc(struct display *p, int xx, int yy); -extern void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only); - -#endif /* _VIDEO_FBCON_CFB32_H */ diff --git a/include/video/fbcon-cfb4.h b/include/video/fbcon-cfb4.h deleted file mode 100644 index 963befe5ca1e..000000000000 --- a/include/video/fbcon-cfb4.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for 4 bpp packed pixel (cfb4) - */ - -#ifndef _VIDEO_FBCON_CFB4_H -#define _VIDEO_FBCON_CFB4_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_CFB4) || defined(CONFIG_FBCON_CFB4_MODULE) -#define FBCON_HAS_CFB4 -#endif -#else -#if defined(CONFIG_FBCON_CFB4) -#define FBCON_HAS_CFB4 -#endif -#endif - -extern struct display_switch fbcon_cfb4; -extern void fbcon_cfb4_setup(struct display *p); -extern void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_cfb4_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_CFB4_H */ diff --git a/include/video/fbcon-cfb8.h b/include/video/fbcon-cfb8.h deleted file mode 100644 index 96189d0acd27..000000000000 --- a/include/video/fbcon-cfb8.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * FBcon low-level driver for 8 bpp packed pixel (cfb8) - */ - -#ifndef _VIDEO_FBCON_CFB8_H -#define _VIDEO_FBCON_CFB8_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FBCON_CFB8_MODULE) -#define FBCON_HAS_CFB8 -#endif -#else -#if defined(CONFIG_FBCON_CFB8) -#define FBCON_HAS_CFB8 -#endif -#endif - -extern struct display_switch fbcon_cfb8; -extern void fbcon_cfb8_setup(struct display *p); -extern void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_cfb8_revc(struct display *p, int xx, int yy); -extern void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p, - int bottom_only); - -#endif /* _VIDEO_FBCON_CFB8_H */ diff --git a/include/video/fbcon-hga.h b/include/video/fbcon-hga.h deleted file mode 100644 index 695ab443f2a4..000000000000 --- a/include/video/fbcon-hga.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for Hercules Graphics Adaptor (hga) - */ - -#ifndef _VIDEO_FBCON_HGA_H -#define _VIDEO_FBCON_HGA_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_HGA) || defined(CONFIG_FBCON_HGA_MODULE) -#define FBCON_HAS_HGA -#endif -#else -#if defined(CONFIG_FBCON_HGA) -#define FBCON_HAS_HGA -#endif -#endif - -extern struct display_switch fbcon_hga; -extern void fbcon_hga_setup(struct display *p); -extern void fbcon_hga_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_hga_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_hga_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_hga_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_hga_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_HGA_H */ diff --git a/include/video/fbcon-ilbm.h b/include/video/fbcon-ilbm.h deleted file mode 100644 index 80f9707f679d..000000000000 --- a/include/video/fbcon-ilbm.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for Amiga interleaved bitplanes (ilbm) - */ - -#ifndef _VIDEO_FBCON_ILBM_H -#define _VIDEO_FBCON_ILBM_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_ILBM) || defined(CONFIG_FBCON_ILBM_MODULE) -#define FBCON_HAS_ILBM -#endif -#else -#if defined(CONFIG_FBCON_ILBM) -#define FBCON_HAS_ILBM -#endif -#endif - -extern struct display_switch fbcon_ilbm; -extern void fbcon_ilbm_setup(struct display *p); -extern void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_ilbm_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_ILBM_H */ diff --git a/include/video/fbcon-iplan2p2.h b/include/video/fbcon-iplan2p2.h deleted file mode 100644 index b72868035317..000000000000 --- a/include/video/fbcon-iplan2p2.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for Atari interleaved bitplanes (2 planes) (iplan2p2) - */ - -#ifndef _VIDEO_FBCON_IPLAN2P2_H -#define _VIDEO_FBCON_IPLAN2P2_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P2_MODULE) -#define FBCON_HAS_IPLAN2P2 -#endif -#else -#if defined(CONFIG_FBCON_IPLAN2P2) -#define FBCON_HAS_IPLAN2P2 -#endif -#endif - -extern struct display_switch fbcon_iplan2p2; -extern void fbcon_iplan2p2_setup(struct display *p); -extern void fbcon_iplan2p2_bmove(struct display *p, int sy, int sx, int dy, - int dx, int height, int width); -extern void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p, - int sy, int sx, int height, int width); -extern void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_iplan2p2_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_IPLAN2P2_H */ diff --git a/include/video/fbcon-iplan2p4.h b/include/video/fbcon-iplan2p4.h deleted file mode 100644 index a7012020421c..000000000000 --- a/include/video/fbcon-iplan2p4.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for Atari interleaved bitplanes (4 planes) (iplan2p4) - */ - -#ifndef _VIDEO_FBCON_IPLAN2P4_H -#define _VIDEO_FBCON_IPLAN2P4_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_IPLAN2P4) || defined(CONFIG_FBCON_IPLAN2P4_MODULE) -#define FBCON_HAS_IPLAN2P4 -#endif -#else -#if defined(CONFIG_FBCON_IPLAN2P4) -#define FBCON_HAS_IPLAN2P4 -#endif -#endif - -extern struct display_switch fbcon_iplan2p4; -extern void fbcon_iplan2p4_setup(struct display *p); -extern void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy, - int dx, int height, int width); -extern void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p, - int sy, int sx, int height, int width); -extern void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_iplan2p4_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_IPLAN2P4_H */ diff --git a/include/video/fbcon-iplan2p8.h b/include/video/fbcon-iplan2p8.h deleted file mode 100644 index 6691e18d6e26..000000000000 --- a/include/video/fbcon-iplan2p8.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for Atari interleaved bitplanes (8 planes) (iplan2p8) - */ - -#ifndef _VIDEO_FBCON_IPLAN2P8_H -#define _VIDEO_FBCON_IPLAN2P8_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_IPLAN2P8) || defined(CONFIG_FBCON_IPLAN2P8_MODULE) -#define FBCON_HAS_IPLAN2P8 -#endif -#else -#if defined(CONFIG_FBCON_IPLAN2P8) -#define FBCON_HAS_IPLAN2P8 -#endif -#endif - -extern struct display_switch fbcon_iplan2p8; -extern void fbcon_iplan2p8_setup(struct display *p); -extern void fbcon_iplan2p8_bmove(struct display *p, int sy, int sx, int dy, - int dx, int height, int width); -extern void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p, - int sy, int sx, int height, int width); -extern void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_iplan2p8_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_IPLAN2P8_H */ diff --git a/include/video/fbcon-mac.h b/include/video/fbcon-mac.h deleted file mode 100644 index b275ff91b824..000000000000 --- a/include/video/fbcon-mac.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for Mac variable bpp packed pixels (mac) - */ - -#ifndef _VIDEO_FBCON_MAC_H -#define _VIDEO_FBCON_MAC_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_MAC) || defined(CONFIG_FBCON_MAC_MODULE) -#define FBCON_HAS_MAC -#endif -#else -#if defined(CONFIG_FBCON_MAC) -#define FBCON_HAS_MAC -#endif -#endif - -extern struct display_switch fbcon_mac; -extern void fbcon_mac_setup(struct display *p); -extern void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_mac_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_mac_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_MAC_H */ diff --git a/include/video/fbcon-mfb.h b/include/video/fbcon-mfb.h deleted file mode 100644 index f74e63da22a9..000000000000 --- a/include/video/fbcon-mfb.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for Monochrome (mfb) - */ - -#ifndef _VIDEO_FBCON_MFB_H -#define _VIDEO_FBCON_MFB_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_MFB) || defined(CONFIG_FBCON_MFB_MODULE) -#define FBCON_HAS_MFB -#endif -#else -#if defined(CONFIG_FBCON_MFB) -#define FBCON_HAS_MFB -#endif -#endif - -extern struct display_switch fbcon_mfb; -extern void fbcon_mfb_setup(struct display *p); -extern void fbcon_mfb_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_mfb_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_mfb_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_mfb_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_mfb_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_MFB_H */ diff --git a/include/video/fbcon-vga-planes.h b/include/video/fbcon-vga-planes.h deleted file mode 100644 index 31578d41c58f..000000000000 --- a/include/video/fbcon-vga-planes.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * FBcon low-level driver for VGA 4-plane modes - */ - -#ifndef _VIDEO_FBCON_VGA_PLANES_H -#define _VIDEO_FBCON_VGA_PLANES_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_VGA_PLANES) || defined(CONFIG_FBCON_VGA_PLANES_MODULE) -#define FBCON_HAS_VGA_PLANES -#endif -#else -#if defined(CONFIG_FBCON_VGA_PLANES) -#define FBCON_HAS_VGA_PLANES -#endif -#endif - -extern struct display_switch fbcon_vga_planes; -extern struct display_switch fbcon_ega_planes; -extern void fbcon_vga_planes_setup(struct display *p); -extern void fbcon_vga_planes_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_vga_planes_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_vga_planes_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_ega_planes_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_vga_planes_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_VGA_PLANES_H */ diff --git a/include/video/fbcon-vga.h b/include/video/fbcon-vga.h deleted file mode 100644 index e7c7b2db0ce7..000000000000 --- a/include/video/fbcon-vga.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FBcon low-level driver for VGA characters/attributes - */ - -#ifndef _VIDEO_FBCON_VGA_H -#define _VIDEO_FBCON_VGA_H - -#include <linux/config.h> - -#ifdef MODULE -#if defined(CONFIG_FBCON_VGA) || defined(CONFIG_FBCON_VGA_MODULE) -#define FBCON_HAS_VGA -#endif -#else -#if defined(CONFIG_FBCON_VGA) -#define FBCON_HAS_VGA -#endif -#endif - -extern struct display_switch fbcon_vga; -extern void fbcon_vga_setup(struct display *p); -extern void fbcon_vga_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -extern void fbcon_vga_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -extern void fbcon_vga_putc(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -extern void fbcon_vga_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx); -extern void fbcon_vga_revc(struct display *p, int xx, int yy); - -#endif /* _VIDEO_FBCON_VGA_H */ diff --git a/include/video/fbcon.h b/include/video/fbcon.h deleted file mode 100644 index c28fea0c10c3..000000000000 --- a/include/video/fbcon.h +++ /dev/null @@ -1,795 +0,0 @@ -/* - * linux/drivers/video/fbcon.h -- Low level frame buffer based console driver - * - * Copyright (C) 1997 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_FBCON_H -#define _VIDEO_FBCON_H - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/console_struct.h> -#include <linux/vt_buffer.h> - -#include <asm/io.h> - - - /* - * `switch' for the Low Level Operations - */ - -struct display_switch { - void (*setup)(struct display *p); - void (*bmove)(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); - /* for clear, conp may be NULL, which means use a blanking (black) color */ - void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width); - void (*putc)(struct vc_data *conp, struct display *p, int c, int yy, - int xx); - void (*putcs)(struct vc_data *conp, struct display *p, const unsigned short *s, - int count, int yy, int xx); - void (*revc)(struct display *p, int xx, int yy); - void (*cursor)(struct display *p, int mode, int xx, int yy); - int (*set_font)(struct display *p, int width, int height); - void (*clear_margins)(struct vc_data *conp, struct display *p, - int bottom_only); - unsigned int fontwidthmask; /* 1 at (1 << (width - 1)) if width is supported */ -}; - -extern struct display_switch fbcon_dummy; - - /* - * This is the interface between the low-level console driver and the - * low-level frame buffer device - */ - -struct display { - /* Filled in by the frame buffer device */ - - struct fb_var_screeninfo var; /* variable infos. yoffset and vmode */ - /* are updated by fbcon.c */ - struct fb_cmap cmap; /* colormap */ - u_short can_soft_blank; /* zero if no hardware blanking */ - u_short inverse; /* != 0 text black on white as default */ - struct display_switch *dispsw; /* low level operations */ - void *dispsw_data; /* optional dispsw helper data */ - -#if 0 - struct fb_fix_cursorinfo fcrsr; - struct fb_var_cursorinfo *vcrsr; - struct fb_cursorstate crsrstate; -#endif - - /* Filled in by the low-level console driver */ - struct vc_data *conp; /* pointer to console data */ - struct fb_info *fb_info; /* frame buffer for this console */ - int vrows; /* number of virtual rows */ - unsigned short cursor_x; /* current cursor position */ - unsigned short cursor_y; - int fgcol; /* text colors */ - int bgcol; - u_long next_line; /* offset to one line below */ - u_long next_plane; /* offset to next plane */ - u_char *fontdata; /* Font associated to this display */ - unsigned short _fontheightlog; - unsigned short _fontwidthlog; - unsigned short _fontheight; - unsigned short _fontwidth; - int userfont; /* != 0 if fontdata kmalloc()ed */ - u_short scrollmode; /* Scroll Method */ - short yscroll; /* Hardware scrolling */ - unsigned char fgshift, bgshift; - unsigned short charmask; /* 0xff or 0x1ff */ -}; - -/* drivers/video/fbcon.c */ -extern struct display fb_display[MAX_NR_CONSOLES]; -extern char con2fb_map[MAX_NR_CONSOLES]; -extern int PROC_CONSOLE(const struct fb_info *info); -extern void set_con2fb_map(int unit, int newidx); -extern int set_all_vcs(int fbidx, struct fb_ops *fb, - struct fb_var_screeninfo *var, struct fb_info *info); - -#define fontheight(p) ((p)->_fontheight) -#define fontheightlog(p) ((p)->_fontheightlog) - -#ifdef CONFIG_FBCON_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) -#define fontwidthlog(p) (0) - -#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) -#define fontwidthlog(p) ((p)->_fontwidthlog) - -#endif - - /* - * Attribute Decoding - */ - -/* Color */ -#define attr_fgcol(p,s) \ - (((s) >> ((p)->fgshift)) & 0x0f) -#define attr_bgcol(p,s) \ - (((s) >> ((p)->bgshift)) & 0x0f) -#define attr_bgcol_ec(p,conp) \ - ((conp) ? (((conp)->vc_video_erase_char >> ((p)->bgshift)) & 0x0f) : 0) -#define attr_fgcol_ec(p,vc) \ - ((vc) ? (((vc)->vc_video_erase_char >> ((p)->fgshift)) & 0x0f) : 0) - -/* Monochrome */ -#define attr_bold(p,s) \ - ((s) & 0x200) -#define attr_reverse(p,s) \ - (((s) & 0x800) ^ ((p)->inverse ? 0x800 : 0)) -#define attr_underline(p,s) \ - ((s) & 0x400) -#define attr_blink(p,s) \ - ((s) & 0x8000) - - /* - * Scroll Method - */ - -/* Internal flags */ -#define __SCROLL_YPAN 0x001 -#define __SCROLL_YWRAP 0x002 -#define __SCROLL_YMOVE 0x003 -#define __SCROLL_YREDRAW 0x004 -#define __SCROLL_YMASK 0x00f -#define __SCROLL_YFIXED 0x010 -#define __SCROLL_YNOMOVE 0x020 -#define __SCROLL_YPANREDRAW 0x040 -#define __SCROLL_YNOPARTIAL 0x080 - -/* Only these should be used by the drivers */ -/* Which one should you use? If you have a fast card and slow bus, - then probably just 0 to indicate fbcon should choose between - YWRAP/YPAN+MOVE/YMOVE. On the other side, if you have a fast bus - and even better if your card can do fonting (1->8/32bit painting), - you should consider either SCROLL_YREDRAW (if your card is - able to do neither YPAN/YWRAP), or SCROLL_YNOMOVE. - The best is to test it with some real life scrolling (usually, not - all lines on the screen are filled completely with non-space characters, - and REDRAW performs much better on such lines, so don't cat a file - with every line covering all screen columns, it would not be the right - benchmark). - */ -#define SCROLL_YREDRAW (__SCROLL_YFIXED|__SCROLL_YREDRAW) -#define SCROLL_YNOMOVE (__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW) - -/* SCROLL_YNOPARTIAL, used in combination with the above, is for video - cards which can not handle using panning to scroll a portion of the - screen without excessive flicker. Panning will only be used for - whole screens. - */ -/* Namespace consistency */ -#define SCROLL_YNOPARTIAL __SCROLL_YNOPARTIAL - - -#if defined(__sparc__) - -/* We map all of our framebuffers such that big-endian accesses - * are what we want, so the following is sufficient. - */ - -#define fb_readb sbus_readb -#define fb_readw sbus_readw -#define fb_readl sbus_readl -#define fb_writeb sbus_writeb -#define fb_writew sbus_writew -#define fb_writel sbus_writel -#define fb_memset sbus_memset_io - -#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) - -#define fb_readb __raw_readb -#define fb_readw __raw_readw -#define fb_readl __raw_readl -#define fb_writeb __raw_writeb -#define fb_writew __raw_writew -#define fb_writel __raw_writel -#define fb_memset memset_io - -#else - -#define fb_readb(addr) (*(volatile u8 *) (addr)) -#define fb_readw(addr) (*(volatile u16 *) (addr)) -#define fb_readl(addr) (*(volatile u32 *) (addr)) -#define fb_writeb(b,addr) (*(volatile u8 *) (addr) = (b)) -#define fb_writew(b,addr) (*(volatile u16 *) (addr) = (b)) -#define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b)) -#define fb_memset memset - -#endif - - -extern void fbcon_redraw_clear(struct vc_data *, struct display *, int, int, int, int); -extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int); - - -/* ================================================================= */ -/* Utility Assembler Functions */ -/* ================================================================= */ - - -#if defined(__mc68000__) - -/* ====================================================================== */ - -/* Those of a delicate disposition might like to skip the next couple of - * pages. - * - * These functions are drop in replacements for memmove and - * memset(_, 0, _). However their five instances add at least a kilobyte - * to the object file. You have been warned. - * - * Not a great fan of assembler for the sake of it, but I think - * that these routines are at least 10 times faster than their C - * equivalents for large blits, and that's important to the lowest level of - * a graphics driver. Question is whether some scheme with the blitter - * would be faster. I suspect not for simple text system - not much - * asynchrony. - * - * Code is very simple, just gruesome expansion. Basic strategy is to - * increase data moved/cleared at each step to 16 bytes to reduce - * instruction per data move overhead. movem might be faster still - * For more than 15 bytes, we try to align the write direction on a - * longword boundary to get maximum speed. This is even more gruesome. - * Unaligned read/write used requires 68020+ - think this is a problem? - * - * Sorry! - */ - - -/* ++roman: I've optimized Robert's original versions in some minor - * aspects, e.g. moveq instead of movel, let gcc choose the registers, - * use movem in some places... - * For other modes than 1 plane, lots of more such assembler functions - * were needed (e.g. the ones using movep or expanding color values). - */ - -/* ++andreas: more optimizations: - subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc - addal is faster than addaw - movep is rather expensive compared to ordinary move's - some functions rewritten in C for clarity, no speed loss */ - -static __inline__ void *fb_memclear_small(void *s, size_t count) -{ - if (!count) - return(0); - - __asm__ __volatile__( - "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t" - "1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t" - "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t" - "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t" - "1:" - : "=a" (s), "=d" (count) - : "d" (0), "0" ((char *)s+count), "1" (count) - ); - __asm__ __volatile__( - "subql #1,%1 ; jcs 3f\n\t" - "movel %2,%%d4; movel %2,%%d5; movel %2,%%d6\n\t" - "2: moveml %2/%%d4/%%d5/%%d6,%0@-\n\t" - "dbra %1,2b\n\t" - "3:" - : "=a" (s), "=d" (count) - : "d" (0), "0" (s), "1" (count) - : "d4", "d5", "d6" - ); - - return(0); -} - - -static __inline__ void *fb_memclear(void *s, size_t count) -{ - if (!count) - return(0); - - if (count < 16) { - __asm__ __volatile__( - "lsrl #1,%1 ; jcc 1f ; clrb %0@+\n\t" - "1: lsrl #1,%1 ; jcc 1f ; clrw %0@+\n\t" - "1: lsrl #1,%1 ; jcc 1f ; clrl %0@+\n\t" - "1: lsrl #1,%1 ; jcc 1f ; clrl %0@+ ; clrl %0@+\n\t" - "1:" - : "=a" (s), "=d" (count) - : "0" (s), "1" (count) - ); - } else { - long tmp; - __asm__ __volatile__( - "movel %1,%2\n\t" - "lsrl #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t" - "lsrl #1,%2 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/ - "clrw %0@+ ; subqw #2,%1 ; jra 2f\n\t" - "1: lsrl #1,%2 ; jcc 2f\n\t" - "clrw %0@+ ; subqw #2,%1\n\t" - "2: movew %1,%2; lsrl #2,%1 ; jeq 6f\n\t" - "lsrl #1,%1 ; jcc 3f ; clrl %0@+\n\t" - "3: lsrl #1,%1 ; jcc 4f ; clrl %0@+ ; clrl %0@+\n\t" - "4: subql #1,%1 ; jcs 6f\n\t" - "5: clrl %0@+; clrl %0@+ ; clrl %0@+ ; clrl %0@+\n\t" - "dbra %1,5b ; clrw %1; subql #1,%1; jcc 5b\n\t" - "6: movew %2,%1; btst #1,%1 ; jeq 7f ; clrw %0@+\n\t" - "7: ; btst #0,%1 ; jeq 8f ; clrb %0@+\n\t" - "8:" - : "=a" (s), "=d" (count), "=d" (tmp) - : "0" (s), "1" (count) - ); - } - - return(0); -} - - -static __inline__ void *fb_memset255(void *s, size_t count) -{ - if (!count) - return(0); - - __asm__ __volatile__( - "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t" - "1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t" - "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t" - "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t" - "1:" - : "=a" (s), "=d" (count) - : "d" (-1), "0" ((char *)s+count), "1" (count) - ); - __asm__ __volatile__( - "subql #1,%1 ; jcs 3f\n\t" - "movel %2,%%d4; movel %2,%%d5; movel %2,%%d6\n\t" - "2: moveml %2/%%d4/%%d5/%%d6,%0@-\n\t" - "dbra %1,2b\n\t" - "3:" - : "=a" (s), "=d" (count) - : "d" (-1), "0" (s), "1" (count) - : "d4", "d5", "d6" - ); - - return(0); -} - - -static __inline__ void *fb_memmove(void *d, const void *s, size_t count) -{ - if (d < s) { - if (count < 16) { - __asm__ __volatile__( - "lsrl #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t" - "1: lsrl #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t" - "1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t" - "1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t" - "1:" - : "=a" (d), "=a" (s), "=d" (count) - : "0" (d), "1" (s), "2" (count) - ); - } else { - long tmp; - __asm__ __volatile__( - "movel %0,%3\n\t" - "lsrl #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t" - "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/ - "movew %1@+,%0@+ ; subqw #2,%2 ; jra 2f\n\t" - "1: lsrl #1,%3 ; jcc 2f\n\t" - "movew %1@+,%0@+ ; subqw #2,%2\n\t" - "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t" - "lsrl #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t" - "3: lsrl #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t" - "4: subql #1,%2 ; jcs 6f\n\t" - "5: movel %1@+,%0@+;movel %1@+,%0@+\n\t" - "movel %1@+,%0@+;movel %1@+,%0@+\n\t" - "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t" - "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t" - "7: ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t" - "8:" - : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp) - : "0" (d), "1" (s), "2" (count) - ); - } - } else { - if (count < 16) { - __asm__ __volatile__( - "lsrl #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t" - "1: lsrl #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t" - "1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t" - "1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t" - "1:" - : "=a" (d), "=a" (s), "=d" (count) - : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count) - ); - } else { - long tmp; - __asm__ __volatile__( - "movel %0,%3\n\t" - "lsrl #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t" - "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/ - "movew %1@-,%0@- ; subqw #2,%2 ; jra 2f\n\t" - "1: lsrl #1,%3 ; jcc 2f\n\t" - "movew %1@-,%0@- ; subqw #2,%2\n\t" - "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t" - "lsrl #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t" - "3: lsrl #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t" - "4: subql #1,%2 ; jcs 6f\n\t" - "5: movel %1@-,%0@-;movel %1@-,%0@-\n\t" - "movel %1@-,%0@-;movel %1@-,%0@-\n\t" - "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t" - "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t" - "7: ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t" - "8:" - : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp) - : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count) - ); - } - } - - return(0); -} - - -/* ++andreas: Simple and fast version of memmove, assumes size is - divisible by 16, suitable for moving the whole screen bitplane */ -static __inline__ void fast_memmove(char *dst, const char *src, size_t size) -{ - if (!size) - return; - if (dst < src) - __asm__ __volatile__ - ("1:" - " moveml %0@+,%/d0/%/d1/%/a0/%/a1\n" - " moveml %/d0/%/d1/%/a0/%/a1,%1@\n" - " addql #8,%1; addql #8,%1\n" - " dbra %2,1b\n" - " clrw %2; subql #1,%2\n" - " jcc 1b" - : "=a" (src), "=a" (dst), "=d" (size) - : "0" (src), "1" (dst), "2" (size / 16 - 1) - : "d0", "d1", "a0", "a1", "memory"); - else - __asm__ __volatile__ - ("1:" - " subql #8,%0; subql #8,%0\n" - " moveml %0@,%/d0/%/d1/%/a0/%/a1\n" - " moveml %/d0/%/d1/%/a0/%/a1,%1@-\n" - " dbra %2,1b\n" - " clrw %2; subql #1,%2\n" - " jcc 1b" - : "=a" (src), "=a" (dst), "=d" (size) - : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1) - : "d0", "d1", "a0", "a1", "memory"); -} - -#elif defined(CONFIG_SUN4) - -/* You may think that I'm crazy and that I should use generic - routines. No, I'm not: sun4's framebuffer crashes if we std - into it, so we cannot use memset. */ - -static __inline__ void *sun4_memset(void *s, char val, size_t count) -{ - int i; - for(i=0; i<count;i++) - ((char *) s) [i] = val; - return s; -} - -static __inline__ void *fb_memset255(void *s, size_t count) -{ - return sun4_memset(s, 255, count); -} - -static __inline__ void *fb_memclear(void *s, size_t count) -{ - return sun4_memset(s, 0, count); -} - -static __inline__ void *fb_memclear_small(void *s, size_t count) -{ - return sun4_memset(s, 0, count); -} - -/* To be honest, this is slow_memmove :). But sun4 is crappy, so what we can do. */ -static __inline__ void fast_memmove(void *d, const void *s, size_t count) -{ - int i; - if (d<s) { - for (i=0; i<count; i++) - ((char *) d)[i] = ((char *) s)[i]; - } else - for (i=0; i<count; i++) - ((char *) d)[count-i-1] = ((char *) s)[count-i-1]; -} - -static __inline__ void *fb_memmove(char *dst, const char *src, size_t size) -{ - fast_memmove(dst, src, size); - return dst; -} - -#else - -static __inline__ void *fb_memclear_small(void *s, size_t count) -{ - char *xs = (char *) s; - - while (count--) - fb_writeb(0, xs++); - - return s; -} - -static __inline__ void *fb_memclear(void *s, size_t count) -{ - unsigned long xs = (unsigned long) s; - - if (count < 8) - goto rest; - - if (xs & 1) { - fb_writeb(0, xs++); - count--; - } - if (xs & 2) { - fb_writew(0, xs); - xs += 2; - count -= 2; - } - while (count > 3) { - fb_writel(0, xs); - xs += 4; - count -= 4; - } -rest: - while (count--) - fb_writeb(0, xs++); - - return s; -} - -static __inline__ void *fb_memset255(void *s, size_t count) -{ - unsigned long xs = (unsigned long) s; - - if (count < 8) - goto rest; - - if (xs & 1) { - fb_writeb(0xff, xs++); - count--; - } - if (xs & 2) { - fb_writew(0xffff, xs); - xs += 2; - count -= 2; - } - while (count > 3) { - fb_writel(0xffffffff, xs); - xs += 4; - count -= 4; - } -rest: - while (count--) - fb_writeb(0xff, xs++); - - return s; -} - -#if defined(__i386__) - -static __inline__ void fast_memmove(void *d, const void *s, size_t count) -{ - int d0, d1, d2, d3; - if (d < s) { -__asm__ __volatile__ ( - "cld\n\t" - "shrl $1,%%ecx\n\t" - "jnc 1f\n\t" - "movsb\n" - "1:\tshrl $1,%%ecx\n\t" - "jnc 2f\n\t" - "movsw\n" - "2:\trep\n\t" - "movsl" - : "=&c" (d0), "=&D" (d1), "=&S" (d2) - :"0"(count),"1"((long)d),"2"((long)s) - :"memory"); - } else { -__asm__ __volatile__ ( - "std\n\t" - "shrl $1,%%ecx\n\t" - "jnc 1f\n\t" - "movb 3(%%esi),%%al\n\t" - "movb %%al,3(%%edi)\n\t" - "decl %%esi\n\t" - "decl %%edi\n" - "1:\tshrl $1,%%ecx\n\t" - "jnc 2f\n\t" - "movw 2(%%esi),%%ax\n\t" - "movw %%ax,2(%%edi)\n\t" - "decl %%esi\n\t" - "decl %%edi\n\t" - "decl %%esi\n\t" - "decl %%edi\n" - "2:\trep\n\t" - "movsl\n\t" - "cld" - : "=&c" (d0), "=&D" (d1), "=&S" (d2), "=&a" (d3) - :"0"(count),"1"(count-4+(long)d),"2"(count-4+(long)s) - :"memory"); - } -} - -static __inline__ void *fb_memmove(char *dst, const char *src, size_t size) -{ - fast_memmove(dst, src, size); - return dst; -} - -#else /* !__i386__ */ - - /* - * Anyone who'd like to write asm functions for other CPUs? - * (Why are these functions better than those from include/asm/string.h?) - */ - -static __inline__ void *fb_memmove(void *d, const void *s, size_t count) -{ - unsigned long dst, src; - - if (d < s) { - dst = (unsigned long) d; - src = (unsigned long) s; - - if ((count < 8) || ((dst ^ src) & 3)) - goto restup; - - if (dst & 1) { - fb_writeb(fb_readb(src++), dst++); - count--; - } - if (dst & 2) { - fb_writew(fb_readw(src), dst); - src += 2; - dst += 2; - count -= 2; - } - while (count > 3) { - fb_writel(fb_readl(src), dst); - src += 4; - dst += 4; - count -= 4; - } - - restup: - while (count--) - fb_writeb(fb_readb(src++), dst++); - } else { - dst = (unsigned long) d + count; - src = (unsigned long) s + count; - - if ((count < 8) || ((dst ^ src) & 3)) - goto restdown; - - if (dst & 1) { - src--; - dst--; - count--; - fb_writeb(fb_readb(src), dst); - } - if (dst & 2) { - src -= 2; - dst -= 2; - count -= 2; - fb_writew(fb_readw(src), dst); - } - while (count > 3) { - src -= 4; - dst -= 4; - count -= 4; - fb_writel(fb_readl(src), dst); - } - - restdown: - while (count--) { - src--; - dst--; - fb_writeb(fb_readb(src), dst); - } - } - - return d; -} - -static __inline__ void fast_memmove(char *d, const char *s, size_t count) -{ - unsigned long dst, src; - - if (d < s) { - dst = (unsigned long) d; - src = (unsigned long) s; - - if ((count < 8) || ((dst ^ src) & 3)) - goto restup; - - if (dst & 1) { - fb_writeb(fb_readb(src++), dst++); - count--; - } - if (dst & 2) { - fb_writew(fb_readw(src), dst); - src += 2; - dst += 2; - count -= 2; - } - while (count > 3) { - fb_writel(fb_readl(src), dst); - src += 4; - dst += 4; - count -= 4; - } - - restup: - while (count--) - fb_writeb(fb_readb(src++), dst++); - } else { - dst = (unsigned long) d + count; - src = (unsigned long) s + count; - - if ((count < 8) || ((dst ^ src) & 3)) - goto restdown; - - if (dst & 1) { - src--; - dst--; - count--; - fb_writeb(fb_readb(src), dst); - } - if (dst & 2) { - src -= 2; - dst -= 2; - count -= 2; - fb_writew(fb_readw(src), dst); - } - while (count > 3) { - src -= 4; - dst -= 4; - count -= 4; - fb_writel(fb_readl(src), dst); - } - - restdown: - while (count--) { - src--; - dst--; - fb_writeb(fb_readb(src), dst); - } - } -} - -#endif /* !__i386__ */ - -#endif /* !__mc68000__ */ - -#endif /* _VIDEO_FBCON_H */ diff --git a/drivers/video/iga.h b/include/video/iga.h index de9685c58f1a..5a48f16578f8 100644 --- a/drivers/video/iga.h +++ b/include/video/iga.h @@ -7,11 +7,6 @@ #ifndef _IGA1682_H #define _IGA1682_H 1 -struct iga1682_info -{ - unsigned int total_vram; -}; - #define IGA_ATTR_CTL 0x3C0 #define IGA_IDX_VGA_OVERSCAN 0x11 #define DAC_W_INDEX 0x03C8 diff --git a/include/video/neomagic.h b/include/video/neomagic.h index e0b73849bf0a..eec28b762178 100644 --- a/include/video/neomagic.h +++ b/include/video/neomagic.h @@ -176,6 +176,7 @@ struct neofb_par { int lcd_stretch; int internal_display; int external_display; + int libretto; }; typedef struct { diff --git a/drivers/video/radeon.h b/include/video/radeon.h index 64a023033ca0..64a023033ca0 100644 --- a/drivers/video/radeon.h +++ b/include/video/radeon.h diff --git a/kernel/printk.c b/kernel/printk.c index d7c4d22bf347..6a9ad3289cb1 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -560,6 +560,7 @@ void console_conditional_schedule(void) schedule(); } } +EXPORT_SYMBOL(console_conditional_schedule); void console_print(const char *s) { |
