diff options
| author | James Simmons <jsimmons@maxwell.earthlink.net> | 2002-10-15 20:46:14 -0700 |
|---|---|---|
| committer | James Simmons <jsimmons@maxwell.earthlink.net> | 2002-10-15 20:46:14 -0700 |
| commit | 143b8e9d04987f7d776646280cd47b94aa8e4a16 (patch) | |
| tree | 47ca083421db1f680d44605df071a9378e57a6ca | |
| parent | 007376bde07f4ee495941eb32d9509cb413889fd (diff) | |
Cleaned up and moved all the graphics related code inf drivers/video and move the console display related stuff into lower directory called console.
| -rw-r--r-- | Documentation/DocBook/kernel-api.tmpl | 4 | ||||
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | arch/alpha/config.in | 17 | ||||
| -rw-r--r-- | arch/arm/config.in | 10 | ||||
| -rw-r--r-- | arch/i386/config.in | 12 | ||||
| -rw-r--r-- | arch/ia64/config.in | 11 | ||||
| -rw-r--r-- | arch/m68k/config.in | 7 | ||||
| -rw-r--r-- | arch/mips/config.in | 11 | ||||
| -rw-r--r-- | arch/mips64/config.in | 15 | ||||
| -rw-r--r-- | arch/parisc/config.in | 19 | ||||
| -rw-r--r-- | arch/ppc/config.in | 7 | ||||
| -rw-r--r-- | arch/ppc64/config.in | 7 | ||||
| -rw-r--r-- | arch/sh/config.in | 13 | ||||
| -rw-r--r-- | arch/sparc/config.in | 7 | ||||
| -rw-r--r-- | arch/sparc64/config.in | 4 | ||||
| -rw-r--r-- | arch/x86_64/config.in | 12 | ||||
| -rw-r--r-- | drivers/Makefile | 3 | ||||
| -rw-r--r-- | drivers/video/Config.help | 123 | ||||
| -rw-r--r-- | drivers/video/Config.in | 145 | ||||
| -rw-r--r-- | drivers/video/Makefile | 41 | ||||
| -rw-r--r-- | drivers/video/aty128fb.c | 3165 | ||||
| -rw-r--r-- | drivers/video/cfbcopyarea.c | 104 | ||||
| -rw-r--r-- | drivers/video/cfbfillrect.c | 110 | ||||
| -rw-r--r-- | drivers/video/cfbimgblt.c | 331 | ||||
| -rw-r--r-- | drivers/video/console/Config.help | 149 | ||||
| -rw-r--r-- | drivers/video/console/Config.in | 162 | ||||
| -rw-r--r-- | drivers/video/console/Makefile | 49 | ||||
| -rw-r--r-- | drivers/video/console/dummycon.c (renamed from drivers/video/dummycon.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-accel.c (renamed from drivers/video/fbcon-accel.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-accel.h (renamed from drivers/video/fbcon-accel.h) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-afb.c (renamed from drivers/video/fbcon-afb.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-hga.c (renamed from drivers/video/fbcon-hga.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-ilbm.c (renamed from drivers/video/fbcon-ilbm.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-iplan2p2.c (renamed from drivers/video/fbcon-iplan2p2.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-iplan2p4.c (renamed from drivers/video/fbcon-iplan2p4.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-iplan2p8.c (renamed from drivers/video/fbcon-iplan2p8.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-sti.c (renamed from drivers/video/fbcon-sti.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon-vga-planes.c (renamed from drivers/video/fbcon-vga-planes.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fbcon.c (renamed from drivers/video/fbcon.c) | 28 | ||||
| -rw-r--r-- | drivers/video/console/font_6x11.c (renamed from drivers/video/font_6x11.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/font_8x16.c (renamed from drivers/video/font_8x16.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/font_8x8.c (renamed from drivers/video/font_8x8.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/font_acorn_8x8.c (renamed from drivers/video/font_acorn_8x8.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/font_mini_4x6.c (renamed from drivers/video/font_mini_4x6.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/font_pearl_8x8.c (renamed from drivers/video/font_pearl_8x8.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/font_sun12x22.c (renamed from drivers/video/font_sun12x22.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/font_sun8x16.c (renamed from drivers/video/font_sun8x16.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/fonts.c (renamed from drivers/video/fonts.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/mdacon.c (renamed from drivers/video/mdacon.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/newport_con.c (renamed from drivers/video/newport_con.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/prom.uni (renamed from drivers/video/prom.uni) | 0 | ||||
| -rw-r--r-- | drivers/video/console/promcon.c (renamed from drivers/video/promcon.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/sti-bmode.h (renamed from drivers/video/sti-bmode.h) | 0 | ||||
| -rw-r--r-- | drivers/video/console/sticon-bmode.c (renamed from drivers/video/sticon-bmode.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/sticon.c (renamed from drivers/video/sticon.c) | 0 | ||||
| -rw-r--r-- | drivers/video/console/vgacon.c (renamed from drivers/video/vgacon.c) | 0 | ||||
| -rw-r--r-- | drivers/video/fbcmap.c | 57 | ||||
| -rw-r--r-- | drivers/video/fbgen.c | 45 | ||||
| -rw-r--r-- | drivers/video/fbmem.c | 7 | ||||
| -rw-r--r-- | drivers/video/neofb.c | 2 | ||||
| -rw-r--r-- | drivers/video/sgivwfb.c | 1 | ||||
| -rw-r--r-- | drivers/video/sis/sis_accel.c | 495 | ||||
| -rw-r--r-- | include/linux/fb.h | 25 | ||||
| -rw-r--r-- | include/linux/sisfb.h | 58 |
64 files changed, 2883 insertions, 2375 deletions
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. @@ -668,7 +668,7 @@ defconfig: CLEAN_FILES += \ include/linux/compile.h \ vmlinux System.map \ - drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \ + drivers/char/consolemap_deftbl.c drivers/video/console/promcon_tbl.c \ drivers/char/conmakehash \ drivers/char/drm/*-mod.c \ drivers/char/defkeymap.c drivers/char/qtronixmap.c \ diff --git a/arch/alpha/config.in b/arch/alpha/config.in index dc851ada6963..c4f6d381d15e 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -348,22 +348,7 @@ source drivers/media/Config.in source fs/Config.in -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - bool 'VGA text console' CONFIG_VGA_CONSOLE -# 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/Config.in - if [ "$CONFIG_FB" = "y" ]; then - define_bool CONFIG_PCI_CONSOLE y - fi - endmenu -fi +source drivers/video/Config.in mainmenu_option next_comment comment 'Sound' diff --git a/arch/arm/config.in b/arch/arm/config.in index 9e6605c5a4e4..e9f7e1c2f39b 100644 --- a/arch/arm/config.in +++ b/arch/arm/config.in @@ -498,15 +498,7 @@ source drivers/media/Config.in source fs/Config.in -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then - bool 'VGA text console' CONFIG_VGA_CONSOLE - fi - source drivers/video/Config.in - endmenu -fi +source drivers/video/Config.in if [ "$CONFIG_ARCH_ACORN" = "y" -o \ "$CONFIG_ARCH_CLPS7500" = "y" -o \ diff --git a/arch/i386/config.in b/arch/i386/config.in index 784e35d23bce..941d04a0da6b 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -417,17 +417,7 @@ source drivers/media/Config.in source fs/Config.in -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - bool 'VGA text console' CONFIG_VGA_CONSOLE - bool 'Video mode selection support' CONFIG_VIDEO_SELECT - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE - source drivers/video/Config.in - fi - endmenu -fi +source drivers/video/Config.in mainmenu_option next_comment comment 'Sound' diff --git a/arch/ia64/config.in b/arch/ia64/config.in index c2e6fdf686fd..9147f72fbf74 100644 --- a/arch/ia64/config.in +++ b/arch/ia64/config.in @@ -229,16 +229,7 @@ fi # HP_SIM source fs/Config.in if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then - if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - bool 'VGA text console' CONFIG_VGA_CONSOLE - source drivers/video/Config.in - if [ "$CONFIG_FB" = "y" ]; then - define_bool CONFIG_PCI_CONSOLE y - fi - endmenu - fi + source drivers/video/Config.in mainmenu_option next_comment comment 'Sound' diff --git a/arch/m68k/config.in b/arch/m68k/config.in index 436e3a3986a9..9dc1eec61bac 100644 --- a/arch/m68k/config.in +++ b/arch/m68k/config.in @@ -527,12 +527,7 @@ endmenu source fs/Config.in -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - source drivers/video/Config.in - endmenu -fi +source drivers/video/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff --git a/arch/mips/config.in b/arch/mips/config.in index f48cfd6ae206..f7319fdfdbd5 100644 --- a/arch/mips/config.in +++ b/arch/mips/config.in @@ -449,16 +449,7 @@ fi source fs/Config.in -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - bool 'VGA text console' CONFIG_VGA_CONSOLE - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE - source drivers/video/Config.in - fi - endmenu -fi +source drivers/video/Config.in if [ "$CONFIG_DECSTATION" != "y" ]; then mainmenu_option next_comment diff --git a/arch/mips64/config.in b/arch/mips64/config.in index f60cccdea4be..9851d55ee8c0 100644 --- a/arch/mips64/config.in +++ b/arch/mips64/config.in @@ -199,20 +199,7 @@ source drivers/media/Config.in source fs/Config.in -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - source drivers/video/Config.in - if [ "$CONFIG_SGI_IP22" = "y" ]; then - tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE - if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then - define_bool CONFIG_DUMMY_CONSOLE y - else - define_bool CONFIG_FONT_8x16 y - fi - fi - endmenu -fi +source drivers/video/Config.in if [ "$CONFIG_PROC_FS" = "y" ]; then define_bool CONFIG_KCORE_ELF y diff --git a/arch/parisc/config.in b/arch/parisc/config.in index 990b739f6d80..2ec98ccce0af 100644 --- a/arch/parisc/config.in +++ b/arch/parisc/config.in @@ -168,24 +168,7 @@ if [ "$CONFIG_SOUND" != "n" ]; then fi endmenu -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - source drivers/video/Config.in - -# bool 'IODC console' CONFIG_IODC_CONSOLE - bool 'STI console' CONFIG_STI_CONSOLE - if [ "$CONFIG_IODC_CONSOLE" = "n" ]; then - if [ "$CONFIG_GSC_PS2" = "y" ]; then - define_bool CONFIG_DUMMY_CONSOLE y - fi - fi - if [ "$CONFIG_STI_CONSOLE" = "y" ]; then - define_bool CONFIG_DUMMY_CONSOLE y - fi - endmenu -fi -# endmenu +source drivers/video/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff --git a/arch/ppc/config.in b/arch/ppc/config.in index 84f098ad2753..bb2c92f7b17e 100644 --- a/arch/ppc/config.in +++ b/arch/ppc/config.in @@ -459,14 +459,7 @@ source net/irda/Config.in source drivers/isdn/Config.in -mainmenu_option next_comment -comment 'Console drivers' -if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then - bool 'VGA text console' CONFIG_VGA_CONSOLE -fi source drivers/video/Config.in -endmenu - if [ "$CONFIG_PPC_ISERIES" = "y" ]; then mainmenu_option next_comment diff --git a/arch/ppc64/config.in b/arch/ppc64/config.in index ec1e5539b0ff..bd8c78c88421 100644 --- a/arch/ppc64/config.in +++ b/arch/ppc64/config.in @@ -151,12 +151,7 @@ source drivers/media/Config.in source fs/Config.in -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - source drivers/video/Config.in - endmenu -fi +source drivers/video/Config.in mainmenu_option next_comment comment 'Sound' diff --git a/arch/sh/config.in b/arch/sh/config.in index 54640eb6172c..0603186fbc39 100644 --- a/arch/sh/config.in +++ b/arch/sh/config.in @@ -336,18 +336,7 @@ source fs/Config.in source drivers/media/Config.in -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - bool 'VGA text console' CONFIG_VGA_CONSOLE - bool 'Video mode selection support' CONFIG_VIDEO_SELECT - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE - source drivers/video/Config.in - fi - endmenu -fi - +source drivers/video/Config.in mainmenu_option next_comment comment 'Sound' diff --git a/arch/sparc/config.in b/arch/sparc/config.in index e93547ad28f3..83c207b989e8 100644 --- a/arch/sparc/config.in +++ b/arch/sparc/config.in @@ -60,14 +60,7 @@ source drivers/parport/Config.in dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT endmenu -mainmenu_option next_comment -comment 'Console drivers' -bool 'PROM console' CONFIG_PROM_CONSOLE -if [ "$CONFIG_PROM_CONSOLE" != "y" ]; then - define_bool CONFIG_DUMMY_CONSOLE y -fi source drivers/video/Config.in -endmenu source drivers/mtd/Config.in diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in index 537b7d099c94..848e2f7eb6a8 100644 --- a/arch/sparc64/config.in +++ b/arch/sparc64/config.in @@ -74,11 +74,7 @@ if [ "$CONFIG_PCI" = "y" ]; then fi endmenu -mainmenu_option next_comment -comment 'Console drivers' -bool 'PROM console' CONFIG_PROM_CONSOLE source drivers/video/Config.in -endmenu source drivers/serial/Config.in source drivers/sbus/char/Config.in diff --git a/arch/x86_64/config.in b/arch/x86_64/config.in index 6c41e4e22b1d..04395edd04ca 100644 --- a/arch/x86_64/config.in +++ b/arch/x86_64/config.in @@ -188,17 +188,7 @@ source drivers/media/Config.in source fs/Config.in -if [ "$CONFIG_VT" = "y" ]; then - mainmenu_option next_comment - comment 'Console drivers' - bool 'VGA text console' CONFIG_VGA_CONSOLE - bool 'Video mode selection support' CONFIG_VIDEO_SELECT - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE - source drivers/video/Config.in - fi - endmenu -fi +source drivers/video/Config.in mainmenu_option next_comment comment 'Sound' diff --git a/drivers/Makefile b/drivers/Makefile index 958ecc4df984..560d819124a8 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -17,7 +17,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/ @@ -27,7 +27,6 @@ obj-$(CONFIG_ALL_PPC) += macintosh/ obj-$(CONFIG_MAC) += macintosh/ obj-$(CONFIG_PNP) += pnp/ 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/video/Config.help b/drivers/video/Config.help index ee952117f677..d508d1f1c7d3 100644 --- a/drivers/video/Config.help +++ b/drivers/video/Config.help @@ -1,19 +1,6 @@ CONFIG_FB_SGIVW SGI Visual Workstation support for framebuffer graphics. -CONFIG_VIDEO_SELECT - 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_FB The frame buffer device provides an abstraction for the graphics hardware. It represents the frame buffer of some video hardware and @@ -242,14 +229,6 @@ CONFIG_FB_VESA You will get a boot time penguin logo at no additional cost. Please read <file:Documentation/fb/vesafb.txt>. If unsure, say Y. -CONFIG_FBCON_VGA_PLANES - 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_FB_VGA16 This is the frame buffer device driver for VGA 16 color graphic cards. Say Y if you have such a card. @@ -280,58 +259,6 @@ CONFIG_FB_STI Really old HP boxes may not have STI, and must use the PDC BIOS console or the IODC BIOS. -CONFIG_FBCON_FONTS - 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_FONT_8x16 - 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_FBCON_FONTWIDTH8_ONLY - Answer Y here will make the kernel provide only the 8x8 fonts (these - are the less readable). - - If unsure, say N. - -CONFIG_FONT_SUN8x16 - This is the high resolution console font for Sun machines. Say Y. - -CONFIG_FONT_SUN12x22 - 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_FONT_8x8 - 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_6x11 - Small console font with Macintosh-style high-half glyphs. Some Mac - framebuffer drivers don't support this one at all. - -CONFIG_FONT_PEARL_8x8 - Small console font with PC-style control-character and high-half - glyphs. - -CONFIG_FONT_ACORN_8x8 - Small console font with PC-style control characters and high-half - glyphs. - CONFIG_FB_HGA Say Y here if you have a Hercules mono graphics card. @@ -646,53 +573,3 @@ CONFIG_FB_SA1100 If you plan to use the LCD display with your SA-1100 system, say Y here. -CONFIG_FBCON_ADVANCED - 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 - This is the low level frame buffer console driver for monochrome - (2 colors) packed pixels. - -CONFIG_FBCON_AFB - This is the low level frame buffer console driver for 1 to 8 - bitplanes (2 to 256 colors) on Amiga. - -CONFIG_FBCON_ILBM - This is the low level frame buffer console driver for 1 to 8 - interleaved bitplanes (2 to 256 colors) on Amiga. - -CONFIG_FBCON_IPLAN2P2 - This is the low level frame buffer console driver for 2 interleaved - bitplanes (4 colors) on Atari. - -CONFIG_FBCON_IPLAN2P4 - This is the low level frame buffer console driver for 4 interleaved - bitplanes (16 colors) on Atari. - -CONFIG_FBCON_IPLAN2P8 - This is the low level frame buffer console driver for 8 interleaved - bitplanes (256 colors) on Atari. - -CONFIG_FBCON_HGA - This is the low level frame buffer console driver for Hercules mono - graphics cards. - diff --git a/drivers/video/Config.in b/drivers/video/Config.in index 534f8c9ef4e5..0e1c8808c985 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -3,12 +3,11 @@ # mainmenu_option next_comment -comment 'Frame-buffer support' +comment 'Graphics support' bool 'Support for frame buffer devices ' CONFIG_FB if [ "$CONFIG_FB" = "y" ]; then - define_bool CONFIG_DUMMY_CONSOLE y if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_PCI" = "y" ]; then tristate ' Cirrus Logic support (EXPERIMENTAL)' CONFIG_FB_CLGEN @@ -78,7 +77,7 @@ if [ "$CONFIG_FB" = "y" ]; then bool ' Chips 65550 display support' CONFIG_FB_CT65550 bool ' IMS Twin Turbo display support' CONFIG_FB_IMSTT bool ' S3 Trio display support' CONFIG_FB_S3TRIO - tristate ' VGA 16-color graphics console' CONFIG_FB_VGA16 + tristate ' VGA 16-color graphics support' CONFIG_FB_VGA16 fi if [ "$CONFIG_PARISC" = "y" ]; then bool ' Generic STI frame buffer device support' CONFIG_FB_STI @@ -95,9 +94,9 @@ if [ "$CONFIG_FB" = "y" ]; then tristate ' TGA framebuffer support' CONFIG_FB_TGA fi if [ "$CONFIG_X86" = "y" ]; then - bool ' VESA VGA graphics console' CONFIG_FB_VESA - tristate ' VGA 16-color graphics console' CONFIG_FB_VGA16 - tristate ' Hercules mono graphics console ' CONFIG_FB_HGA + bool ' VESA VGA graphics support' CONFIG_FB_VESA + tristate ' VGA 16-color graphics support' CONFIG_FB_VGA16 + tristate ' Hercules mono graphics support ' CONFIG_FB_HGA define_bool CONFIG_VIDEO_SELECT y fi if [ "$CONFIG_VISWS" = "y" ]; then @@ -214,138 +213,8 @@ if [ "$CONFIG_FB" = "y" ]; then if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate ' Virtual Frame Buffer support (ONLY FOR TESTING!) (EXPERIMENTAL)' CONFIG_FB_VIRTUAL fi - - bool ' Advanced low level driver options' CONFIG_FBCON_ADVANCED - if [ "$CONFIG_FBCON_ADVANCED" = "y" ]; then - tristate ' Monochrome support' CONFIG_FBCON_MFB - tristate ' 24 bpp packed pixels support' CONFIG_FBCON_CFB24 - tristate ' Hardware acceleration support' CONFIG_FBCON_ACCEL - tristate ' Amiga bitplanes support' CONFIG_FBCON_AFB - tristate ' Amiga interleaved bitplanes support' CONFIG_FBCON_ILBM - tristate ' Atari interleaved bitplanes (2 planes) support' CONFIG_FBCON_IPLAN2P2 - tristate ' Atari interleaved bitplanes (4 planes) support' CONFIG_FBCON_IPLAN2P4 - tristate ' Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8 -# tristate ' Atari interleaved bitplanes (16 planes) support' CONFIG_FBCON_IPLAN2P16 - tristate ' VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES - tristate ' HGA monochrome support ' CONFIG_FBCON_HGA - else - if [ "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \ - "$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \ - "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ - "$CONFIG_FB_ATY128" = "y" -o "$CONFIG_FB_RADEON" = "y" ]; then - define_tristate CONFIG_FBCON_CFB24 y - else - if [ "$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VOODOO1" = "m" -o \ - "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ - "$CONFIG_FB_ATY128" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ - "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_PVR2" = "m" ]; then - define_tristate CONFIG_FBCON_CFB24 m - fi - fi - if [ "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \ - "$CONFIG_FB_FM2" = "y" -o "$CONFIG_FB_HIT" = "y" -o \ - "$CONFIG_FB_HP300" = "y" -o "$CONFIG_FB_Q40" = "y" -o \ - "$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_G364" = "y" -o \ - "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \ - "$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \ - "$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \ - "$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_APOLLO" = "y" -o \ - "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ - "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_OF" = "y" -o \ - "$CONFIG_FB_SGIVW" = "y" ]; then - define_tristate CONFIG_FBCON_ACCEL y - else - if [ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_HIT" = "m" -o \ - "$CONFIG_FB_G364" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ - "$CONFIG_FB_CLPS711X" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \ - "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \ - "$CONFIG_FB_ATY" = "m" ]; then - define_tristate CONFIG_FBCON_ACCEL m - fi - fi - if [ "$CONFIG_FB_AMIGA" = "y" ]; then - define_tristate CONFIG_FBCON_AFB y - define_tristate CONFIG_FBCON_ILBM y - else - if [ "$CONFIG_FB_AMIGA" = "m" ]; then - define_tristate CONFIG_FBCON_AFB m - define_tristate CONFIG_FBCON_ILBM m - fi - fi - if [ "$CONFIG_FB_ATARI" = "y" ]; then - define_tristate CONFIG_FBCON_IPLAN2P2 y - define_tristate CONFIG_FBCON_IPLAN2P4 y - define_tristate CONFIG_FBCON_IPLAN2P8 y - else - if [ "$CONFIG_FB_ATARI" = "m" ]; then - define_tristate CONFIG_FBCON_IPLAN2P2 m - define_tristate CONFIG_FBCON_IPLAN2P4 m - define_tristate CONFIG_FBCON_IPLAN2P8 m - fi - fi - if [ "$CONFIG_FB_VGA16" = "y" ]; then - define_tristate CONFIG_FBCON_VGA_PLANES y - else - if [ "$CONFIG_FB_VGA16" = "m" ]; then - define_tristate CONFIG_FBCON_VGA_PLANES m - fi - fi - if [ "$CONFIG_FB_HGA" = "y" ]; then - define_tristate CONFIG_FBCON_HGA y - else - if [ "$CONFIG_FB_HGA" = "m" ]; then - define_tristate CONFIG_FBCON_HGA m - fi - fi - if [ "$CONFIG_FB_STI" = "y" ]; then - define_tristate CONFIG_FBCON_STI y - fi - fi - bool ' Support only 8 pixels wide fonts' CONFIG_FBCON_FONTWIDTH8_ONLY - if [ "$CONFIG_SPARC32" = "y" -o "$CONFIG_SPARC64" = "y" ]; then - bool ' Sparc console 8x16 font' CONFIG_FONT_SUN8x16 - if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then - bool ' Sparc console 12x22 font (not supported by all drivers)' CONFIG_FONT_SUN12x22 - fi - bool ' Select other fonts' CONFIG_FBCON_FONTS - if [ "$CONFIG_FBCON_FONTS" = "y" ]; then - bool ' VGA 8x8 font' CONFIG_FONT_8x8 - bool ' VGA 8x16 font' CONFIG_FONT_8x16 - if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then - bool ' Mac console 6x11 font (not supported by all drivers)' CONFIG_FONT_6x11 - fi - bool ' Pearl (old m68k) console 8x8 font' CONFIG_FONT_PEARL_8x8 - bool ' Acorn console 8x8 font' CONFIG_FONT_ACORN_8x8 - fi - else - bool ' Select compiled-in fonts' CONFIG_FBCON_FONTS - if [ "$CONFIG_FBCON_FONTS" = "y" ]; then - bool ' VGA 8x8 font' CONFIG_FONT_8x8 - bool ' VGA 8x16 font' CONFIG_FONT_8x16 - bool ' Sparc console 8x16 font' CONFIG_FONT_SUN8x16 - if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then - bool ' Sparc console 12x22 font (not supported by all drivers)' CONFIG_FONT_SUN12x22 - bool ' Mac console 6x11 font (not supported by all drivers)' CONFIG_FONT_6x11 - fi - bool ' Pearl (old m68k) console 8x8 font' CONFIG_FONT_PEARL_8x8 - bool ' Acorn console 8x8 font' CONFIG_FONT_ACORN_8x8 - bool ' Mini 4x6 font' CONFIG_FONT_MINI_4x6 - else - define_bool CONFIG_FONT_8x8 y - define_bool CONFIG_FONT_8x16 y - if [ "$CONFIG_MAC" = "y" ]; then - if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then - define_bool CONFIG_FONT_6x11 y - fi - fi - if [ "$CONFIG_AMIGA" = "y" ]; then - define_bool CONFIG_FONT_PEARL_8x8 y - fi - if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_ACORN" = "y" ]; then - define_bool CONFIG_FONT_ACORN_8x8 y - fi - fi - fi fi +source drivers/video/console/Config.in + endmenu diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 3cddbde0ff50..0f8739db41f4 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -5,31 +5,12 @@ # 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 fbgen.o \ - fbcon-afb.o fbcon-ilbm.o fbcon-accel.o cyber2000fb.o \ - fbcon-iplan2p2.o fbcon-iplan2p4.o fbcon-iplan2p8.o \ - fbcon-vga-planes.o fbcon-vga8-planes.o fbcon-hga.o +export-objs := fbmem.o fbcmap.o fbmon.o modedb.o fbgen.o cyber2000fb.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 - # 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 fbgen.o # Only include macmodes.o if we have FB support and are PPC ifeq ($(CONFIG_FB),y) obj-$(CONFIG_PPC) += macmodes.o @@ -86,7 +67,7 @@ obj-$(CONFIG_FB_TX3912) += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbi obj-$(CONFIG_FB_MATROX) += matrox/ obj-$(CONFIG_FB_RIVA) += riva/ -obj-$(CONFIG_FB_SIS) += sis/ +obj-$(CONFIG_FB_SIS) += sis/ cfbimgblt.o obj-$(CONFIG_FB_ATY) += aty/ cfbimgblt.o obj-$(CONFIG_FB_SUN3) += sun3fb.o @@ -99,21 +80,7 @@ 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_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_HGA) += fbcon-hga.o -obj-$(CONFIG_FBCON_STI) += fbcon-sti.o -obj-$(CONFIG_FBCON_ACCEL) += fbcon-accel.o +obj-$(CONFIG_VT) += console/ 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/aty128fb.c b/drivers/video/aty128fb.c index ae43cc8ea62e..921adccb4c6f 100644 --- a/drivers/video/aty128fb.c +++ b/drivers/video/aty128fb.c @@ -7,13 +7,23 @@ * 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) + * * 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 +59,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> @@ -92,27 +102,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) */ @@ -133,9 +143,9 @@ static struct fb_videomode defaultmode __initdata = { /* struct to hold chip description information */ struct aty128_chip_info { - const char *name; - unsigned short device; - int chip_gen; + const char *name; + unsigned short device; + int chip_gen; }; /* Chip generations */ @@ -148,16 +158,17 @@ enum { /* 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} + {"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}, + {"Rage128 Pro TF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U1, 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} }; /* packed BIOS settings */ @@ -190,28 +201,38 @@ 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" }; + { 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 const char *aty128fb_name = "ATY Rage128"; static char fontname[40] __initdata = { 0 }; @@ -222,99 +243,105 @@ 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; + 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_PCI - struct pci_dev *pdev; + struct pci_dev *pdev; #endif #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) */ + 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 + unsigned char red[64]; /* see comments in aty128fb_setcolreg */ + unsigned char green[64]; + unsigned char blue[64]; +}; + +struct fb_info_aty128 { + struct fb_info fb_info; + struct display disp; + struct aty128fb_par par; + u32 pseudo_palette[17]; + struct fb_info_aty128 *next; }; 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) /* @@ -323,19 +350,16 @@ static struct fb_info_aty128 *board_list = NULL; 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, struct fb_info *fb); static int aty128fb_blank(int blank, struct fb_info *fb); +static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); static int aty128fb_rasterimg(struct fb_info *info, int start); /* @@ -343,88 +367,52 @@ static int aty128fb_rasterimg(struct fb_info *info, int start); */ int aty128fb_init(void); -static int aty128fbcon_switch(int con, struct fb_info *fb); /* * 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); + struct aty128fb_par *par); 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); #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_set_var = gen_set_var, + .fb_check_var = aty128fb_check_var, + .fb_set_par = aty128fb_set_par, + .fb_get_cmap = gen_get_cmap, + .fb_set_cmap = gen_set_cmap, + .fb_setcolreg = aty128fb_setcolreg, + .fb_pan_display = aty128fb_pan_display, + .fb_blank = aty128fb_blank, + .fb_ioctl = aty128fb_ioctl, +#if 0 + .fb_fillrect = aty128fb_fillrect, + .fb_copyarea = aty128fb_copyarea, + .fb_imageblit = aty128fb_imageblit, + .fb_rasterimg = aty128fb_rasterimg, +#else + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +#endif }; #ifdef CONFIG_PMAC_BACKLIGHT @@ -443,1345 +431,1194 @@ 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; - - wait_for_idle(info); - - /* 3D scaler not spoken here */ - wait_for_fifo(1, info); - aty_st_le32(SCALE_3D_CNTL, 0x00000000); + u32 pitch_value; - aty128_reset_engine(info); + wait_for_idle(par); - pitch_value = par->crtc.pitch; - if (par->crtc.bpp == 24) { - pitch_value = pitch_value * 3; - } + /* 3D scaler not spoken here */ + wait_for_fifo(1, par); + aty_st_le32(SCALE_3D_CNTL, 0x00000000); - 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_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info) +aty128_set_lcd_enable(struct aty128fb_par *par, int on) { - u32 div3; + u32 reg; - unsigned char post_conv[] = /* register values for post dividers */ + 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 aty128fb_par *par) +{ + u32 div3; + + 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) +aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - 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) -{ - 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 - */ -static int -aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb) -{ - const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; - struct aty128fb_par par; - - if (con == -1) - par = info->default_par; - else - aty128_decode_var(&fb_display[con].var, &par, info); - - aty128_encode_fix(fix, &par, info); - - return 0; -} - - - /* - * Pan or Wrap the Display - * - * Not supported (yet!) - */ +/* + * Pan or Wrap the Display + */ static int aty128fb_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *fb) + 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; + struct aty128fb_par *par = fb->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; + 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; + xoffset = (var->xoffset +7) & ~7; + yoffset = var->yoffset; - if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) - return -EINVAL; + if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) + return -EINVAL; - par->crtc.xoffset = xoffset; - par->crtc.yoffset = yoffset; + par->crtc.xoffset = xoffset; + par->crtc.yoffset = yoffset; - offset = ((yoffset * par->crtc.vxres + xoffset) * par->crtc.bpp) >> 6; + offset = ((yoffset * par->crtc.vxres + xoffset)*(par->crtc.bpp >> 3)) & ~7; - aty_st_le32(CRTC_OFFSET, offset); + if (par->crtc.bpp == 24) + offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */ - return 0; + aty_st_le32(CRTC_OFFSET, offset); + + 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) { - struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info; + struct aty128fb_par *par = info->par; - if (fb->blitter_may_be_busy) - wait_for_idle(fb); + if (par->blitter_may_be_busy) + wait_for_idle(par); - return 0; + 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; + 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; - } + 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; +#ifdef CONFIG_PMAC_PBOOK + } else 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; - } + else 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 */ + 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_ALL_PPC */ + else + mode_option = this_opt; + } + return 0; } - /* - * Initialisation - */ +/* + * Initialisation + */ static int __init -aty128_init(struct fb_info_aty128 *info, const char *name) +aty128_init(struct fb_info *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; - } + struct aty128fb_par *par = info->par; + struct fb_var_screeninfo var; + u32 dac; + u8 chip_rev; + const struct aty128_chip_info *aci = &aty128_pci_probe_list[0]; + const char *video_card; - if (noaccel) - var.accel_flags &= ~FB_ACCELF_TEXT; - else - var.accel_flags |= FB_ACCELF_TEXT; + if (!par->vram_size) /* may have already been probed */ + par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; - if (aty128_decode_var(&var, &info->default_par, info)) { - printk(KERN_ERR "aty128fb: Cannot set default mode.\n"); - return 0; - } + /* Get the chip revision */ + chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; - /* 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]; - } + /* put a name with the face */ + while (aci->name && par->pdev->device != aci->device) + aci++; + video_card = aci->name? aci->name: "Rage128"; + par->chip_gen = aci->chip_gen; - /* 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); + printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); - /* turn off bus mastering, just in case */ - aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS); + 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); + + /* fill in info */ + strcpy(info->modename, aty128fb_name); + info->node = NODEV; + info->fbops = &aty128fb_ops; + 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_PBOOK + par->lcd_on = default_lcd_on; + par->crt_on = default_crt_on; +#endif - aty128fb_set_var(&var, -1, &info->fb_info); - aty128_init_engine(&info->default_par, info); + 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; - board_list = aty128_board_list_add(board_list, info); + 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; + } - size = (var.bits_per_pixel <= 8) ? 256 : 32; - fb_alloc_cmap(&info->fb_info.cmap, size, 0); + if (noaccel) + var.accel_flags &= ~FB_ACCELF_TEXT; + else + var.accel_flags |= FB_ACCELF_TEXT; - if (register_framebuffer(&info->fb_info) < 0) - return 0; + if (aty128fb_check_var(&var, info)) { + printk(KERN_ERR "aty128fb: Cannot set default mode.\n"); + return 0; + } -#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 */ + /* 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); - printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", - GET_FB_IDX(info->fb_info.node), aty128fb_name, name); + /* turn off bus mastering, just in case */ + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS); - return 1; /* success! */ -} + info->var = var; + fb_alloc_cmap(&info->cmap, 256, 0); + gen_set_disp(-1, info); + var.activate = FB_ACTIVATE_NOW; + gen_set_var(&var, -1, info); -/* 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; + aty128_init_engine(par); - 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; + if (register_framebuffer(info) < 0) + return 0; - return board_list; +#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 + if (!par->pdev) + printk(KERN_WARNING "aty128fb: Not a PCI card, can't enable power management\n"); + else { + par->pm_reg = pci_find_capability(par->pdev, PCI_CAP_ID_PM); + pmu_register_sleep_notifier(&aty128_sleep_notifier); + } +#endif + + printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", + GET_FB_IDX(info->node), aty128fb_name, name); + + return 1; /* success! */ } @@ -1789,21 +1626,21 @@ 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++; - } + 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++; + } #endif - return 0; + return 0; } @@ -1813,7 +1650,9 @@ static int __init aty128_pci_register(struct pci_dev *pdev, const struct aty128_chip_info *aci) { - struct fb_info_aty128 *info = NULL; + struct fb_info_aty128 *lump = NULL; + struct fb_info *info; + struct aty128fb_par *par; unsigned long fb_addr, reg_addr; int err; #if !defined(CONFIG_PPC) && !defined(__sparc__) @@ -1824,7 +1663,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,38 +1682,46 @@ aty128_pci_register(struct pci_dev *pdev, } /* We have the resources. Now virtualize them */ - if (!(info = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC))) { + if (!(lump = kmalloc(sizeof(struct fb_info_aty128), 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(lump, 0, sizeof(struct fb_info_aty128)); + info = &lump->fb_info; + par = &lump->par; - /* Copy PCI device info into info->pdev */ - info->pdev = pdev; + info->par = par; + info->disp = &lump->disp; + info->fix = aty128fb_fix; + info->currcon = -1; + info->pseudo_palette = lump->pseudo_palette; - info->fb_info.currcon = -1; + par->pdev = pdev; /* Virtualize mmio region */ - info->regbase_phys = reg_addr; - info->regbase = ioremap(reg_addr, 0x1FFF); - - if (!info->regbase) + 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; } @@ -1889,14 +1736,17 @@ aty128_pci_register(struct pci_dev *pdev, aty128_get_pllinfo(info, bios_seg); } #endif - aty128_timings(info); + aty128_timings(par); if (!aty128_init(info, "PCI")) goto err_out; + lump->next = board_list; + board_list = lump; + #ifdef CONFIG_MTRR if (mtrr) { - info->mtrr.vram = mtrr_add(info->frame_buffer_phys, + info->mtrr.vram = mtrr_add(info->fix.smem_start, info->vram_size, MTRR_TYPE_WRCOMB, 1); info->mtrr.vram_valid = 1; /* let there be speed */ @@ -1906,10 +1756,10 @@ 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); + kfree(lump); err_unmap_out: release_mem_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); @@ -1926,8 +1776,7 @@ err_free_fb: /* 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; @@ -1985,7 +1834,7 @@ static char __init 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 +1854,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 +1871,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_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])); +#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 */ - 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; + if (!par->constants.dotclock) + par->constants.dotclock = 2950; - 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; - } -} - - -static int -aty128fbcon_switch(int con, struct fb_info *fb) -{ - struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; - struct aty128fb_par par; +#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; - /* 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); + par->constants.xclk = round_div((2 * Nx * par->constants.dotclock), + (M * PostDivSet[xclk_cntl])); - /* set the current console */ - fb->currcon = con; - - aty128_decode_var(&fb_display[con].var, &par, info); - aty128_set_par(&par, info); - - 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, int con, 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 +2085,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 +2148,7 @@ aty128_set_backlight_level(int level, void* data) } #endif /* CONFIG_PMAC_BACKLIGHT */ +#if 0 /* * Accelerated functions */ @@ -2301,39 +2156,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,200 +2212,128 @@ 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); -} - - -static void fbcon_aty24_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_cfb24_clear_margins(conp, p, bottom_only); -} - -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); - - if (fb->blitter_may_be_busy) - wait_for_idle(fb); - - fbcon_cfb32_putc(conp, p, c, yy, xx); -} - - -static void fbcon_aty32_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_cfb32_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); + } } +extern struct display_switch fbcon_dummy; -static void fbcon_aty32_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_cfb32_clear_margins(conp, p, 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 *board; + int result; + + result = PBOOK_SLEEP_OK; + + for (board = board_list; board != NULL; board = board->next) { + struct fb_info *info = &board->fb_info; + struct aty128fb_par *par = info->par; + int nb; + + nb = info->var.yres * info->fix.line_length; + + 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: + if (info->currcon >= 0) + fb_display[info->currcon].dispsw = &fbcon_dummy; + + 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); + + 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; + } + gen_set_disp(-1, info); + aty128fb_blank(0, info); + break; + } + } + return result; } - -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 +#endif /* CONFIG_PMAC_PBOOK */ #ifdef MODULE MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>"); @@ -2570,55 +2353,55 @@ MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); 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); - } + 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"); - } + if (nomtrr) { + mtrr = 0; + printk(KERN_INFO "aty128fb: Parameter NOMTRR set\n"); + } #endif - - aty128fb_init(); - return 0; + + aty128fb_init(); + return 0; } void __exit cleanup_module(void) { - struct fb_info_aty128 *info = board_list; + struct fb_info_aty128 *info = board_list; - while (board_list) { - info = board_list; - board_list = board_list->next; + while (board_list) { + info = board_list; + board_list = board_list->next; - unregister_framebuffer(&info->fb_info); + 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); + if (info->mtrr.vram_valid) + mtrr_del(info->mtrr.vram, info->fix.smem_start, + info->vram_size); #endif /* CONFIG_MTRR */ - iounmap(info->regbase); - iounmap(info->frame_buffer); + iounmap(info->par.regbase); + iounmap(info->fb_info.screen_base); - 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)); + release_mem_region(pci_resource_start(info->par.pdev, 0), + pci_resource_len(info->par.pdev, 0)); + release_mem_region(pci_resource_start(info->par.pdev, 1), + pci_resource_len(info->par.pdev, 1)); + release_mem_region(pci_resource_start(info->par.pdev, 2), + pci_resource_len(info->par.pdev, 2)); - kfree(info); - } + kfree(info); + } } #endif /* MODULE */ diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c index 07b47422410b..e3fcc679afb9 100644 --- a/drivers/video/cfbcopyarea.c +++ b/drivers/video/cfbcopyarea.c @@ -38,9 +38,11 @@ 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 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, tmp; + unsigned long start_index, end_index, start_mask, end_mask, last, + tmp; unsigned long *dst = NULL, *src = NULL; char *src1, *dst1; int height; @@ -84,10 +86,16 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) lineincr = linesize; } 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); + 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; } @@ -98,7 +106,7 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) 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)); + ((unsigned long) src1 & (bpl - 1)); start_mask = end_mask = 0; if (start_index) { @@ -111,7 +119,6 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) n -= end_index; } n /= bpl; - if (n <= 0) { if (start_mask) { if (end_mask) @@ -148,16 +155,25 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) last = (FB_READ(src) & start_mask); if (shift > 0) - FB_WRITE(FB_READ(dst) | (last >> shift_right), dst); + 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); + FB_WRITE((last << + shift_left) | + (tmp >> + shift_right), + dst); last = tmp; src++; } - FB_WRITE(FB_READ(dst) | (last << shift_left), dst); + FB_WRITE(FB_READ(dst) | + (last << shift_left), + dst); src1 += lineincr; dst1 += lineincr; } while (--height); @@ -172,16 +188,25 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) last = (FB_READ(src) & end_mask); if (shift < 0) - FB_WRITE(FB_READ(dst) | (last >> shift_right), dst); + 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); + FB_WRITE((tmp << + shift_left) | + (last >> + shift_right), + dst); last = tmp; src--; } - FB_WRITE(FB_READ(dst) | (last >> shift_right), dst); + FB_WRITE(FB_READ(dst) | + (last >> shift_right), + dst); src1 += lineincr; dst1 += lineincr; } while (--height); @@ -191,20 +216,27 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) if (lineincr > 0) { /* positive increment */ do { - dst = (unsigned long *) (dst1 - start_index); - src = (unsigned long *) (src1 - start_index); + dst = + (unsigned long *) (dst1 - + start_index); + src = + (unsigned long *) (src1 - + start_index); if (start_mask) - FB_WRITE(FB_READ(src) | start_mask, dst); + FB_WRITE(FB_READ(src) | + start_mask, dst); for (j = 0; j < n; j++) { - FB_WRITE(FB_READ(src), dst); + FB_WRITE(FB_READ(src), + dst); dst++; src++; } if (end_mask) - FB_WRITE(FB_READ(src) | end_mask, dst); + FB_WRITE(FB_READ(src) | + end_mask, dst); src1 += lineincr; dst1 += lineincr; } while (--height); @@ -215,9 +247,11 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) src = (unsigned long *) src1; if (start_mask) - FB_WRITE(FB_READ(src) | start_mask, dst); + FB_WRITE(FB_READ(src) | + start_mask, dst); for (j = 0; j < n; j++) { - FB_WRITE(FB_READ(src), dst); + FB_WRITE(FB_READ(src), + dst); dst--; src--; } @@ -226,5 +260,33 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) } while (--height); } } + } else { + int n = ((area->width * p->var.bits_per_pixel) >> 3); + int n16 = (n >> 4) << 4; + int n_fract = n - n16; + int rows; + + if (area->dy < area->sy + || (area->dy == area->sy && area->dx < area->sx)) { + for (rows = height; rows--;) { + if (n16) + fast_memmove(dst1, src1, n16); + if (n_fract) + fb_memmove(dst1 + n16, src1 + n16, + n_fract); + dst1 += linesize; + src1 += linesize; + } + } else { + for (rows = height; rows--;) { + if (n16) + fast_memmove(dst1, src1, n16); + if (n_fract) + fb_memmove(dst1 + n16, src1 + n16, + n_fract); + dst1 -= linesize; + src1 -= linesize; + } + } } } diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c index b3ad462b7a27..8f42a317a1c4 100644 --- a/drivers/video/cfbfillrect.c +++ b/drivers/video/cfbfillrect.c @@ -35,7 +35,7 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) unsigned long height, ppw, fg, fgcolor; int i, n, x2, y2, linesize = p->fix.line_length; int bpl = sizeof(unsigned long); - unsigned long *dst; + unsigned long *dst = NULL; char *dst1; if (!rect->width || !rect->height) @@ -55,7 +55,7 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) ppw = BITS_PER_LONG / p->var.bits_per_pixel; dst1 = p->screen_base + (rect->dy * linesize) + - (rect->dx * (p->var.bits_per_pixel >> 3)); + (rect->dx * (p->var.bits_per_pixel >> 3)); start_index = ((unsigned long) dst1 & (bpl - 1)); end_index = ((unsigned long) (dst1 + n) & (bpl - 1)); @@ -97,11 +97,12 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) case ROP_COPY: do { /* Word align to increases performace :-) */ - dst = (unsigned long *) (dst1 - start_index); + dst = + (unsigned long *) (dst1 - start_index); if (start_mask) { FB_WRITE(FB_READ(dst) | - start_mask, dst); + start_mask, dst); dst++; } @@ -112,17 +113,18 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) if (end_mask) FB_WRITE(FB_READ(dst) | end_mask, - dst); + dst); dst1 += linesize; } while (--height); break; case ROP_XOR: do { - dst = (unsigned long *) (dst1 - start_index); + dst = + (unsigned long *) (dst1 - start_index); if (start_mask) { FB_WRITE(FB_READ(dst) ^ - start_mask, dst); + start_mask, dst); dst++; } @@ -133,56 +135,92 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect) if (end_mask) { FB_WRITE(FB_READ(dst) ^ end_mask, - dst); + dst); } dst1 += linesize; } while (--height); break; } } 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; + /* + * Slow Method: The aim is to find the number of pixels to + * pack in order to write doubleword multiple data. + * For 24 bpp, 4 pixels are packed which are written as + * 3 dwords. + */ + char *dst2, *dst3; + int bytes = (p->var.bits_per_pixel + 7) >> 3; + int read, write, total, pack_size; + u32 pixarray[BITS_PER_LONG >> 3], m; + + fg = fgcolor; + read = (bytes + (bpl - 1)) & ~(bpl - 1); + write = bytes; + total = (rect->width * bytes); + + pack_size = bpl * write; + + dst3 = (char *) pixarray; + + for (n = read; n--;) { + *(u32 *) dst3 = fg; + dst3 += bytes; + } 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; + dst2 = dst1; + n = total; + + while (n >= pack_size) { + for (m = 0; m < write; m++) { + fb_writel(pixarray[m], + (u32 *) dst2); + dst2 += 4; + } + n -= pack_size; + } + if (n) { + m = 0; + while (n--) + fb_writeb(((u8 *) + pixarray)[m++], + dst2++); } - 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); */ + dst2 = dst1; + n = total; + + while (n >= pack_size) { + for (m = 0; m < write; m++) { + fb_writel(fb_readl + ((u32 *) dst2) ^ + pixarray[m], + (u32 *) dst2); + dst2 += 4; + } + n -= pack_size; + } + if (n) { + m = 0; + while (n--) { + fb_writeb(fb_readb(dst2) ^ + ((u8 *) + pixarray)[m++], + dst2); + dst2++; + } } - if (end_mask) - *dst ^= end_mask; dst1 += linesize; } while (--height); break; } + } return; } diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index f522f900d66f..96018596ca8e 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -22,6 +22,13 @@ * 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. @@ -39,16 +46,251 @@ #define DPRINTK(fmt, args...) #endif -void cfb_imageblit(struct fb_info *p, struct fb_image *image) +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 +}; + +static u32 cfb_pixarray[4]; +static u32 cfb_tabdef[2]; + + +static inline void fast_imageblit(struct fb_image *image, + struct fb_info *p, char *dst1, + int fgcolor, int bgcolor) +{ + int i, j, k, l = 8, n; + int bit_mask, end_mask, eorx; + unsigned long fgx = fgcolor, bgx = bgcolor, pad; + unsigned long tmp = ~0 << (BITS_PER_LONG - p->var.bits_per_pixel); + unsigned long ppw = BITS_PER_LONG / p->var.bits_per_pixel; + 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 <<= p->var.bits_per_pixel; + bgx <<= p->var.bits_per_pixel; + fgx |= fgcolor; + bgx |= bgcolor; + } + + n = ((image->width + 7) >> 3); + pad = (n << 3) - 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; + for (j = n; j > 0; j--) { + l--; + if (test_bit(l, (unsigned long *) src)) + end_mask |= + (tmp >> + (p->var.bits_per_pixel * + (j - 1))); + if (!l) { + l = 8; + src++; + } + } + fb_writel((end_mask & eorx) ^ bgx, dst++); + } + l -= pad; + dst1 += p->fix.line_length; + } +} + + +/* + * Slow method: The idea is to find the number of pixels necessary to form + * dword-sized multiples that will be written to the framebuffer. For BPP24, + * 4 pixels has to be read which are then packed into 3 double words that + * are then written to the framebuffer. + * + * With this method, processing is done 1 pixel at a time. + */ +static inline void slow_imageblit(struct fb_image *image, + struct fb_info *p, char *dst1, + int fgcolor, int bgcolor) +{ + int bytes = (p->var.bits_per_pixel + 7) >> 3; + int tmp = ~0UL >> (BITS_PER_LONG - p->var.bits_per_pixel); + int i, j, k, l = 8, m, end_mask, eorx; + int read, write, total, pack_size, bpl = sizeof(unsigned long); + unsigned long *dst; + char *dst2 = (char *) cfb_pixarray, *src = image->data; + + cfb_tabdef[0] = 0; + cfb_tabdef[1] = tmp; + + eorx = fgcolor ^ bgcolor; + read = (bytes + (bpl - 1)) & ~(bpl - 1); + write = bytes; + total = image->width * bytes; + pack_size = bpl * write; + + for (i = image->height; i--;) { + dst = (unsigned long *) dst1; + j = total; + m = read; + + while (j >= pack_size) { + l--; + m--; + end_mask = cfb_tabdef[(*src >> l) & 1]; + *(unsigned long *) dst2 = + (end_mask & eorx) ^ bgcolor; + dst2 += bytes; + if (!m) { + for (k = 0; k < write; k++) + fb_writel(cfb_pixarray[k], dst++); + dst2 = (char *) cfb_pixarray; + j -= pack_size; + m = read; + } + if (!l) { + l = 8; + src++; + } + } + /* write residual pixels */ + if (j) { + k = 0; + while (j--) + fb_writeb(((u8 *) cfb_pixarray)[k++], + dst++); + } + dst1 += p->fix.line_length; + } +} + +static inline void bitwise_blit(struct fb_image *image, struct fb_info *p, + char *dst1, int fgcolor, int bgcolor) { - int pad, ppw; - int x2, y2, n, i, j, k, l = 7; + int i, j, k, l = 8, n, pad, ppw; unsigned long tmp = ~0 << (BITS_PER_LONG - p->var.bits_per_pixel); - unsigned long fgx, bgx, fgcolor, bgcolor, eorx; + unsigned long fgx = fgcolor, bgx = bgcolor, eorx; unsigned long end_mask; unsigned long *dst = NULL; + char *src = image->data; + + ppw = BITS_PER_LONG / p->var.bits_per_pixel; + + 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--) { + l--; + if (test_bit(l, (unsigned long *) src)) + end_mask |= + (tmp >> + (p->var.bits_per_pixel * + (k - 1))); + if (!l) { + l = 8; + src++; + } + } + fb_writel((end_mask & eorx) ^ bgx, dst); + dst++; + } + + if (n) { + end_mask = 0; + for (j = n; j > 0; j--) { + l--; + if (test_bit(l, (unsigned long *) src)) + end_mask |= + (tmp >> + (p->var.bits_per_pixel * + (j - 1))); + if (!l) { + l = 8; + src++; + } + } + fb_writel((end_mask & eorx) ^ bgx, dst); + dst++; + } + l -= pad; + dst1 += p->fix.line_length; + } +} + +void cfb_imageblit(struct fb_info *p, struct fb_image *image) +{ + int x2, y2, n; + unsigned long fgcolor, bgcolor; + unsigned long end_mask; u8 *dst1; - u8 *src; /* * We could use hardware clipping but on many cards you get around hardware @@ -60,68 +302,37 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image) 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; - image->width = x2 - image->dx; + 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; + dst1 = p->screen_base + image->dy * p->fix.line_length + + ((image->dx * p->var.bits_per_pixel) >> 3); if (image->depth == 1) { - 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]; + 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; - } - - for (i = 0; i < ppw-1; i++) { - fgx <<= p->var.bits_per_pixel; - bgx <<= p->var.bits_per_pixel; - fgx |= fgcolor; - bgx |= bgcolor; + fgcolor = image->fg_color; + bgcolor = image->bg_color; } - 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 { + + if (p->var.bits_per_pixel >= 8) { + if (BITS_PER_LONG % p->var.bits_per_pixel == 0) + fast_imageblit(image, p, dst1, fgcolor, + bgcolor); + else + slow_imageblit(image, p, dst1, fgcolor, + bgcolor); + } else + /* Is there such a thing as 3 or 5 bits per pixel? */ + slow_imageblit(image, p, dst1, fgcolor, bgcolor); + + } + + else { /* Draw the penguin */ n = ((image->width * p->var.bits_per_pixel) >> 3); end_mask = 0; diff --git a/drivers/video/console/Config.help b/drivers/video/console/Config.help new file mode 100644 index 000000000000..1bd59ed8f72e --- /dev/null +++ b/drivers/video/console/Config.help @@ -0,0 +1,149 @@ +CONFIG_VIDEO_SELECT + 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_FBCON_VGA_PLANES + 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_FB_VGA16 + This is the frame buffer device driver for VGA 16 color graphic + cards. Say Y if you have such a card. + + This code is also available as a module. If you want to compile it + as a module ( = code which can be inserted in and removed from the + running kernel whenever you want), say M here and read + <file:Documentation/modules.txt>. The module will be called + vga16fb.o. + +CONFIG_FB_STI + STI refers to the HP "Standard Text Interface" which is a set of + BIOS routines contained in a ROM chip in HP PA-RISC based machines. + Enabling this option will implement the linux framebuffer device and + an fbcon color text console using calls to the STI BIOS routines. + The HP framebuffer device is usually planar, uses a strange memory + layout, and changing the plane mask to create colored pixels + requires a call to the STI routines, so do not expect /dev/fb to + actually be useful. However, it is the best we have as far as + graphics on the HP chipsets due to lack of hardware level + documentation for the various on-board HP chipsets used in these + systems. It is sufficient for basic text console functions, + including fonts. + + You should probably enable this option, unless you are having + trouble getting video when booting the kernel (make sure it isn't + just that you are running the console on the serial port, though). + Really old HP boxes may not have STI, and must use the PDC BIOS + console or the IODC BIOS. + +CONFIG_FBCON_FONTS + 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_FONT_8x16 + 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_FBCON_FONTWIDTH8_ONLY + Answer Y here will make the kernel provide only the 8x8 fonts (these + are the less readable). + + If unsure, say N. + +CONFIG_FONT_SUN8x16 + This is the high resolution console font for Sun machines. Say Y. + +CONFIG_FONT_SUN12x22 + 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_FONT_8x8 + 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_6x11 + Small console font with Macintosh-style high-half glyphs. Some Mac + framebuffer drivers don't support this one at all. + +CONFIG_FONT_PEARL_8x8 + Small console font with PC-style control-character and high-half + glyphs. + +CONFIG_FONT_ACORN_8x8 + Small console font with PC-style control characters and high-half + glyphs. + +CONFIG_FBCON_ADVANCED + 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_AFB + This is the low level frame buffer console driver for 1 to 8 + bitplanes (2 to 256 colors) on Amiga. + +CONFIG_FBCON_ILBM + This is the low level frame buffer console driver for 1 to 8 + interleaved bitplanes (2 to 256 colors) on Amiga. + +CONFIG_FBCON_IPLAN2P2 + This is the low level frame buffer console driver for 2 interleaved + bitplanes (4 colors) on Atari. + +CONFIG_FBCON_IPLAN2P4 + This is the low level frame buffer console driver for 4 interleaved + bitplanes (16 colors) on Atari. + +CONFIG_FBCON_IPLAN2P8 + This is the low level frame buffer console driver for 8 interleaved + bitplanes (256 colors) on Atari. + +CONFIG_FBCON_HGA + This is the low level frame buffer console driver for Hercules mono + graphics cards. + diff --git a/drivers/video/console/Config.in b/drivers/video/console/Config.in new file mode 100644 index 000000000000..25d1e8671b56 --- /dev/null +++ b/drivers/video/console/Config.in @@ -0,0 +1,162 @@ +# +# Console Display configuration +# + +if [ "$CONFIG_VT" != "n" ]; then + mainmenu_option next_comment + comment 'Console Display driver support' + + bool 'Video mode selection support' CONFIG_VIDEO_SELECT + if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" -a \ + "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then + bool 'VGA text console' CONFIG_VGA_CONSOLE +# 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 + fi + tristate 'MDA text console (dual-headed) ' CONFIG_MDA_CONSOLE + if [ "$CONFIG_FB" = "y" ]; then + define_bool CONFIG_PCI_CONSOLE y + fi +#if [ "$CONFIG_SGI_IP22" = "y" ]; then +# tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE +# if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then +# define_bool CONFIG_DUMMY_CONSOLE y +# else +# define_bool CONFIG_FONT_8x16 y +#fi + if [ "$CONFIG_ARCH_PARISC" = "y" ]; then +# bool 'IODC console' CONFIG_IODC_CONSOLE + bool 'STI console' CONFIG_STI_CONSOLE + if [ "$CONFIG_IODC_CONSOLE" = "n" ]; then + if [ "$CONFIG_GSC_PS2" = "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + fi + fi + if [ "$CONFIG_STI_CONSOLE" = "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + fi + fi + if [ "$CONFIG_SPARC32" = "y" -o "$CONFIG_SPARC64" = "y" ]; then + bool 'PROM console' CONFIG_PROM_CONSOLE + if [ "$CONFIG_PROM_CONSOLE" != "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + fi + fi + if [ "$CONFIG_FB" = "y" ]; then + bool 'Framebuffer Console support' CONFIG_FRAMEBUFFER_CONSOLE + if [ "$CONFIG_FRAMEBUFFER_CONSOLE" = "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + bool ' Advanced low level driver options' CONFIG_FBCON_ADVANCED + if [ "$CONFIG_FBCON_ADVANCED" = "y" ]; then + tristate ' Hardware acceleration support' CONFIG_FBCON_ACCEL + tristate ' Amiga bitplanes support' CONFIG_FBCON_AFB + tristate ' Amiga interleaved bitplanes support' CONFIG_FBCON_ILBM + tristate ' Atari interleaved bitplanes (2 planes) support' CONFIG_FBCON_IPLAN2P2 + tristate ' Atari interleaved bitplanes (4 planes) support' CONFIG_FBCON_IPLAN2P4 + tristate ' Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8 + tristate ' VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES + tristate ' HGA monochrome support ' CONFIG_FBCON_HGA + else + if [ "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \ + "$CONFIG_FB_FM2" = "y" -o "$CONFIG_FB_HIT" = "y" -o \ + "$CONFIG_FB_HP300" = "y" -o "$CONFIG_FB_Q40" = "y" -o \ + "$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_G364" = "y" -o \ + "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \ + "$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \ + "$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \ + "$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_APOLLO" = "y" -o \ + "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ + "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_OF" = "y" -o \ + "$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_SIS" = "y" ]; then + define_tristate CONFIG_FBCON_ACCEL y + else + if [ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_HIT" = "m" -o \ + "$CONFIG_FB_G364" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ + "$CONFIG_FB_CLPS711X" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \ + "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \ + "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_SIS" = "y" ]; then + define_tristate CONFIG_FBCON_ACCEL m + fi + fi + if [ "$CONFIG_FB_AMIGA" = "y" ]; then + define_tristate CONFIG_FBCON_AFB y + define_tristate CONFIG_FBCON_ILBM y + else + if [ "$CONFIG_FB_AMIGA" = "m" ]; then + define_tristate CONFIG_FBCON_AFB m + define_tristate CONFIG_FBCON_ILBM m + fi + fi + if [ "$CONFIG_FB_ATARI" = "y" ]; then + define_tristate CONFIG_FBCON_IPLAN2P2 y + define_tristate CONFIG_FBCON_IPLAN2P4 y + define_tristate CONFIG_FBCON_IPLAN2P8 y + else + if [ "$CONFIG_FB_ATARI" = "m" ]; then + define_tristate CONFIG_FBCON_IPLAN2P2 m + define_tristate CONFIG_FBCON_IPLAN2P4 m + define_tristate CONFIG_FBCON_IPLAN2P8 m + fi + fi + if [ "$CONFIG_FB_VGA16" = "y" ]; then + define_tristate CONFIG_FBCON_VGA_PLANES y + else + if [ "$CONFIG_FB_VGA16" = "m" ]; then + define_tristate CONFIG_FBCON_VGA_PLANES m + fi + fi + fi + bool ' Support only 8 pixels wide fonts' CONFIG_FBCON_FONTWIDTH8_ONLY + if [ "$CONFIG_SPARC32" = "y" -o "$CONFIG_SPARC64" = "y" ]; then + bool ' Sparc console 8x16 font' CONFIG_FONT_SUN8x16 + if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then + bool ' Sparc console 12x22 font (not supported by all drivers)' CONFIG_FONT_SUN12x22 + fi + bool ' Select other fonts' CONFIG_FBCON_FONTS + if [ "$CONFIG_FBCON_FONTS" = "y" ]; then + bool ' VGA 8x8 font' CONFIG_FONT_8x8 + bool ' VGA 8x16 font' CONFIG_FONT_8x16 + if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then + bool ' Mac console 6x11 font (not supported by all drivers)' CONFIG_FONT_6x11 + fi + bool ' Pearl (old m68k) console 8x8 font' CONFIG_FONT_PEARL_8x8 + bool ' Acorn console 8x8 font' CONFIG_FONT_ACORN_8x8 + fi + else + bool ' Select compiled-in fonts' CONFIG_FBCON_FONTS + if [ "$CONFIG_FBCON_FONTS" = "y" ]; then + bool ' VGA 8x8 font' CONFIG_FONT_8x8 + bool ' VGA 8x16 font' CONFIG_FONT_8x16 + bool ' Sparc console 8x16 font' CONFIG_FONT_SUN8x16 + if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then + bool ' Sparc console 12x22 font (not supported by all drivers)' CONFIG_FONT_SUN12x22 + bool ' Mac console 6x11 font (not supported by all drivers)' CONFIG_FONT_6x11 + fi + bool ' Pearl (old m68k) console 8x8 font' CONFIG_FONT_PEARL_8x8 + bool ' Acorn console 8x8 font' CONFIG_FONT_ACORN_8x8 + bool ' Mini 4x6 font' CONFIG_FONT_MINI_4x6 + else + define_bool CONFIG_FONT_8x8 y + define_bool CONFIG_FONT_8x16 y + if [ "$CONFIG_MAC" = "y" ]; then + if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then + define_bool CONFIG_FONT_6x11 y + fi + fi + if [ "$CONFIG_AMIGA" = "y" ]; then + define_bool CONFIG_FONT_PEARL_8x8 y + fi + if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_ACORN" = "y" ]; then + define_bool CONFIG_FONT_ACORN_8x8 y + fi + fi + fi + fi + fi + endmenu +fi + diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile new file mode 100644 index 000000000000..19ffc6d45dd7 --- /dev/null +++ b/drivers/video/console/Makefile @@ -0,0 +1,49 @@ +# 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 fbcon-accel.o fbcon-afb.o fbcon-ilbm.o \ + fbcon-iplan2p2.o fbcon-iplan2p4.o fbcon-iplan2p8.o \ + fbcon-vga-planes.o fbcon-vga8-planes.o fbcon-hga.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_FRAMEBUFFER_CONSOLE) += fbcon.o fonts.o + +# Generic Low Level Drivers + +obj-$(CONFIG_FBCON_AFB) += fbcon-afb.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_HGA) += fbcon-hga.o +obj-$(CONFIG_FBCON_STI) += fbcon-sti.o +obj-$(CONFIG_FBCON_ACCEL) += fbcon-accel.o + +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..82686f4b2633 100644 --- a/drivers/video/dummycon.c +++ b/drivers/video/console/dummycon.c diff --git a/drivers/video/fbcon-accel.c b/drivers/video/console/fbcon-accel.c index 8f6c5dfe0066..8f6c5dfe0066 100644 --- a/drivers/video/fbcon-accel.c +++ b/drivers/video/console/fbcon-accel.c diff --git a/drivers/video/fbcon-accel.h b/drivers/video/console/fbcon-accel.h index 80944b6e04c1..80944b6e04c1 100644 --- a/drivers/video/fbcon-accel.h +++ b/drivers/video/console/fbcon-accel.h diff --git a/drivers/video/fbcon-afb.c b/drivers/video/console/fbcon-afb.c index 6afee164b609..6afee164b609 100644 --- a/drivers/video/fbcon-afb.c +++ b/drivers/video/console/fbcon-afb.c diff --git a/drivers/video/fbcon-hga.c b/drivers/video/console/fbcon-hga.c index 4cb12c6e47f5..4cb12c6e47f5 100644 --- a/drivers/video/fbcon-hga.c +++ b/drivers/video/console/fbcon-hga.c diff --git a/drivers/video/fbcon-ilbm.c b/drivers/video/console/fbcon-ilbm.c index 157736e809a7..157736e809a7 100644 --- a/drivers/video/fbcon-ilbm.c +++ b/drivers/video/console/fbcon-ilbm.c diff --git a/drivers/video/fbcon-iplan2p2.c b/drivers/video/console/fbcon-iplan2p2.c index 9eea32a4efb9..9eea32a4efb9 100644 --- a/drivers/video/fbcon-iplan2p2.c +++ b/drivers/video/console/fbcon-iplan2p2.c diff --git a/drivers/video/fbcon-iplan2p4.c b/drivers/video/console/fbcon-iplan2p4.c index fdbb6a4d2790..fdbb6a4d2790 100644 --- a/drivers/video/fbcon-iplan2p4.c +++ b/drivers/video/console/fbcon-iplan2p4.c diff --git a/drivers/video/fbcon-iplan2p8.c b/drivers/video/console/fbcon-iplan2p8.c index 416f28fd1e59..416f28fd1e59 100644 --- a/drivers/video/fbcon-iplan2p8.c +++ b/drivers/video/console/fbcon-iplan2p8.c diff --git a/drivers/video/fbcon-sti.c b/drivers/video/console/fbcon-sti.c index ef6b9a49d119..ef6b9a49d119 100644 --- a/drivers/video/fbcon-sti.c +++ b/drivers/video/console/fbcon-sti.c diff --git a/drivers/video/fbcon-vga-planes.c b/drivers/video/console/fbcon-vga-planes.c index 2056b16117c2..2056b16117c2 100644 --- a/drivers/video/fbcon-vga-planes.c +++ b/drivers/video/console/fbcon-vga-planes.c diff --git a/drivers/video/fbcon.c b/drivers/video/console/fbcon.c index 136faec87d09..28cc533e65b8 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -335,14 +335,15 @@ int set_all_vcs(int fbidx, struct fb_ops *fb, struct fb_var_screeninfo *var, int unit, err; var->activate |= FB_ACTIVATE_TEST; - err = gen_set_var(var, PROC_CONSOLE(info), info); + err = fb_set_var(var, info); var->activate &= ~FB_ACTIVATE_TEST; gen_set_disp(PROC_CONSOLE(info), info); if (err) return err; for (unit = 0; unit < MAX_NR_CONSOLES; unit++) if (fb_display[unit].conp && con2fb_map[unit] == fbidx) { - gen_set_var(var, unit, info); + if (CON_IS_VISIBLE(fb_display[unit].conp)) + fb_set_var(var, info); gen_set_disp(unit, info); } return 0; @@ -983,6 +984,19 @@ 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(int unit, struct vc_data *conp, struct display *p, int count) { @@ -994,7 +1008,7 @@ static __inline__ void ywrap_up(int unit, struct vc_data *conp, info->var.xoffset = 0; info->var.yoffset = p->yscroll*fontheight(p); info->var.vmode |= FB_VMODE_YWRAP; - gen_update_var(unit, info); + update_var(unit, info); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; @@ -1012,7 +1026,7 @@ static __inline__ void ywrap_down(int unit, struct vc_data *conp, info->var.xoffset = 0; info->var.yoffset = p->yscroll*fontheight(p); info->var.vmode |= FB_VMODE_YWRAP; - gen_update_var(unit, info); + update_var(unit, info); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; @@ -1033,7 +1047,7 @@ static __inline__ void ypan_up(int unit, struct vc_data *conp, info->var.xoffset = 0; info->var.yoffset = p->yscroll*fontheight(p); info->var.vmode &= ~FB_VMODE_YWRAP; - gen_update_var(unit, info); + update_var(unit, info); if (p->dispsw->clear_margins) p->dispsw->clear_margins(conp, p, 1); scrollback_max += count; @@ -1057,7 +1071,7 @@ static __inline__ void ypan_down(int unit, struct vc_data *conp, info->var.xoffset = 0; info->var.yoffset = p->yscroll*fontheight(p); info->var.vmode &= ~FB_VMODE_YWRAP; - gen_update_var(unit, info); + update_var(unit, info); if (p->dispsw->clear_margins) p->dispsw->clear_margins(conp, p, 1); scrollback_max -= count; @@ -2148,7 +2162,7 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines) offset -= limit; info->var.xoffset = 0; info->var.yoffset = offset*fontheight(p); - gen_update_var(unit, info); + update_var(unit, info); if (!scrollback_current) fbcon_cursor(conp, CM_DRAW); return 0; diff --git a/drivers/video/font_6x11.c b/drivers/video/console/font_6x11.c index aa95f8863830..aa95f8863830 100644 --- a/drivers/video/font_6x11.c +++ b/drivers/video/console/font_6x11.c diff --git a/drivers/video/font_8x16.c b/drivers/video/console/font_8x16.c index 786619712560..786619712560 100644 --- a/drivers/video/font_8x16.c +++ b/drivers/video/console/font_8x16.c diff --git a/drivers/video/font_8x8.c b/drivers/video/console/font_8x8.c index 6358e671f1ce..6358e671f1ce 100644 --- a/drivers/video/font_8x8.c +++ b/drivers/video/console/font_8x8.c diff --git a/drivers/video/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c index 154d0fb39da7..154d0fb39da7 100644 --- a/drivers/video/font_acorn_8x8.c +++ b/drivers/video/console/font_acorn_8x8.c diff --git a/drivers/video/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c index 9fe2db2a6edc..9fe2db2a6edc 100644 --- a/drivers/video/font_mini_4x6.c +++ b/drivers/video/console/font_mini_4x6.c diff --git a/drivers/video/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c index c8d7da5714c5..c8d7da5714c5 100644 --- a/drivers/video/font_pearl_8x8.c +++ b/drivers/video/console/font_pearl_8x8.c diff --git a/drivers/video/font_sun12x22.c b/drivers/video/console/font_sun12x22.c index 803b35ea8d72..803b35ea8d72 100644 --- a/drivers/video/font_sun12x22.c +++ b/drivers/video/console/font_sun12x22.c diff --git a/drivers/video/font_sun8x16.c b/drivers/video/console/font_sun8x16.c index 9f5bc40b4762..9f5bc40b4762 100644 --- a/drivers/video/font_sun8x16.c +++ b/drivers/video/console/font_sun8x16.c diff --git a/drivers/video/fonts.c b/drivers/video/console/fonts.c index 436f3a5ec2fc..436f3a5ec2fc 100644 --- a/drivers/video/fonts.c +++ b/drivers/video/console/fonts.c diff --git a/drivers/video/mdacon.c b/drivers/video/console/mdacon.c index f1c47bfaa270..f1c47bfaa270 100644 --- a/drivers/video/mdacon.c +++ b/drivers/video/console/mdacon.c diff --git a/drivers/video/newport_con.c b/drivers/video/console/newport_con.c index 364874dff50d..364874dff50d 100644 --- a/drivers/video/newport_con.c +++ b/drivers/video/console/newport_con.c 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..d72ce48cb3f1 100644 --- a/drivers/video/promcon.c +++ b/drivers/video/console/promcon.c diff --git a/drivers/video/sti-bmode.h b/drivers/video/console/sti-bmode.h index 4aa38f6d9daa..4aa38f6d9daa 100644 --- a/drivers/video/sti-bmode.h +++ b/drivers/video/console/sti-bmode.h diff --git a/drivers/video/sticon-bmode.c b/drivers/video/console/sticon-bmode.c index 3ab5077ac27a..3ab5077ac27a 100644 --- a/drivers/video/sticon-bmode.c +++ b/drivers/video/console/sticon-bmode.c diff --git a/drivers/video/sticon.c b/drivers/video/console/sticon.c index 7dddbe42d40a..7dddbe42d40a 100644 --- a/drivers/video/sticon.c +++ b/drivers/video/console/sticon.c diff --git a/drivers/video/vgacon.c b/drivers/video/console/vgacon.c index b798756cef74..b798756cef74 100644 --- a/drivers/video/vgacon.c +++ b/drivers/video/console/vgacon.c diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index e10d65f53d69..a916cf5fdfcd 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -181,62 +181,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 @@ -353,7 +297,6 @@ void fb_invert_cmaps(void) EXPORT_SYMBOL(fb_alloc_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/fbgen.c b/drivers/video/fbgen.c index 9c055a0bb39b..3f9c2b28bc4e 100644 --- a/drivers/video/fbgen.c +++ b/drivers/video/fbgen.c @@ -20,13 +20,11 @@ #include <asm/uaccess.h> #include <asm/io.h> -#include <video/fbcon.h> - -int gen_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +int fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info) { int err; - if (con < 0 || (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo)))) { + if (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { if (!info->fbops->fb_check_var) { *var = info->var; return 0; @@ -38,20 +36,18 @@ int gen_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) 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_set_par) + info->fbops->fb_set_par(info); - if (info->fbops->fb_pan_display) - info->fbops->fb_pan_display(&info->var, info); - fb_set_cmap(&info->cmap, 1, info); - } + if (info->fbops->fb_pan_display) + info->fbops->fb_pan_display(&info->var, info); + fb_set_cmap(&info->cmap, 1, info); } } return 0; } -int fbgen_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { int xoffset = var->xoffset; int yoffset = var->yoffset; @@ -79,21 +75,8 @@ int fbgen_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) /* ---- Helper functions --------------------------------------------------- */ -int gen_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; -} - /** - * fbgen_blank - blank the screen + * fb_blank - blank the screen * @blank: boolean, 0 unblank, 1 blank * @info: frame buffer info structure * @@ -101,7 +84,7 @@ int gen_update_var(int con, struct fb_info *info) * */ -int fbgen_blank(int blank, struct fb_info *info) +int fb_blank(int blank, struct fb_info *info) { struct fb_cmap cmap; u16 black[16]; @@ -129,10 +112,8 @@ int fbgen_blank(int blank, struct fb_info *info) } /* generic frame buffer operations */ -EXPORT_SYMBOL(gen_set_var); -EXPORT_SYMBOL(fbgen_pan_display); -/* helper functions */ -EXPORT_SYMBOL(gen_update_var); -EXPORT_SYMBOL(fbgen_blank); +EXPORT_SYMBOL(fb_set_var); +EXPORT_SYMBOL(fb_pan_display); +EXPORT_SYMBOL(fb_blank); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index a0f671c84323..c3217085ee32 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -466,10 +466,10 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, int fbidx = GET_FB_IDX(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; struct fb_con2fbmap con2fb; + struct fb_cmap cmap; int i; if (! fb) @@ -485,9 +485,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, i = set_all_vcs(fbidx, fb, &var, info); if (i) return i; } else { - i = gen_set_var(&var, PROC_CONSOLE(info), info); + i = fb_set_var(&var, info); if (i) return i; - gen_set_disp(PROC_CONSOLE(info), info); } if (copy_to_user((void *) arg, &var, sizeof(var))) return -EFAULT; @@ -512,6 +511,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (copy_to_user((void *) arg, &var, sizeof(var))) return -EFAULT; return i; +#ifdef CONFIG_VT case FBIOGET_CON2FBMAP: if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb))) return -EFAULT; @@ -540,6 +540,7 @@ 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 case FBIOBLANK: if (fb->fb_blank == NULL) return -EINVAL; diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index d659e07782de..f33874aa81af 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1870,8 +1870,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 diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index 7fad95ecea2d..4582175b2648 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -99,7 +99,6 @@ 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_check_var = sgivwfb_check_var, .fb_set_par = sgivwfb_set_par, .fb_setcolreg = sgivwfb_setcolreg, 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/include/linux/fb.h b/include/linux/fb.h index 5f1dd158fe42..d6ba52c1e461 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -317,6 +317,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); + /* 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 */ @@ -336,6 +339,8 @@ struct fb_ops { void (*fb_imageblit)(struct fb_info *info, struct fb_image *image); /* perform polling on fb device */ int (*fb_poll)(struct fb_info *info, poll_table *wait); + /* wait for blit idle, optional */ + void (*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, struct fb_info *info); @@ -414,23 +419,13 @@ struct fb_info { * `Generic' versions of the frame buffer device operations */ -extern int gen_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info); -extern int fb_pan_display(struct fb_var_screeninfo *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 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); - /* - * Helper functions - */ - -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_blank(int blank, struct fb_info *info); -extern void gen_set_disp(int con, struct fb_info *info); - /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info); @@ -447,10 +442,6 @@ extern int fbmon_dpms(const struct fb_info *fb_info); extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); 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); 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; |
