Commit 143b8e9d authored by James Simmons's avatar James Simmons

Cleaned up and moved all the graphics related code inf drivers/video and move...

Cleaned up and moved all the graphics related code inf drivers/video and move the console display related stuff into lower directory called console.
parent 007376bd
......@@ -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 \
......
......@@ -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'
......
......@@ -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 \
......
......@@ -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'
......
......@@ -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
mainmenu_option next_comment
comment 'Sound'
......
......@@ -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'
......
......@@ -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
......
......@@ -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
......
......@@ -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'
......
......@@ -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
......
......@@ -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'
......
......@@ -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'
......
......@@ -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
......
......@@ -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
......
......@@ -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'
......
......@@ -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/
......
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.
......@@ -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
......@@ -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/' > $@
......@@ -7,13 +7,23 @@
* Ani Joshi / Jeff Garzik
* - Code cleanup
*
* Michel Dnzer <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,7 +102,7 @@
#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) */
......@@ -102,7 +112,7 @@ static struct fb_var_screeninfo default_var __initdata = {
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 = {
......@@ -112,7 +122,7 @@ static struct fb_var_screeninfo default_var = {
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) */
......@@ -155,6 +165,7 @@ static struct aty128_chip_info aty128_pci_probe_list[] __initdata =
{"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}
......@@ -213,6 +224,16 @@ static const struct aty128_meminfo sdr_sgram =
static const struct aty128_meminfo 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,16 +243,21 @@ 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
......@@ -256,7 +282,7 @@ struct aty128_crtc {
u32 offset, offset_cntl;
u32 xoffset, yoffset;
u32 vxres, vyres;
u32 bpp;
u32 depth, bpp;
};
struct aty128_pll {
......@@ -276,33 +302,11 @@ struct aty128fb_par {
struct aty128_pll pll;
struct aty128_ddafifo fifo_reg;
u32 accel_flags;
};
struct fb_info_aty128 {
struct fb_info fb_info;
struct fb_info_aty128 *next;
struct aty128_constants constants; /* PLL and others */
unsigned long regbase_phys; /* physical mmio */
void *regbase; /* remapped mmio */
unsigned long frame_buffer_phys; /* physical fb memory */
void *frame_buffer; /* remaped framebuffer */
u32 vram_size; /* onboard video ram */
int chip_gen;
const struct aty128_meminfo *mem; /* onboard mem info */
struct aty128fb_par default_par, current_par;
struct display disp;
struct { u8 red, green, blue, pad; } palette[256];
union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
#endif
#ifdef FBCON_HAS_CFB24
u32 cfb24[16];
#endif
#ifdef FBCON_HAS_CFB32
u32 cfb32[16];
#endif
} fbcon_cmap;
#ifdef CONFIG_PCI
struct pci_dev *pdev;
#endif
......@@ -311,10 +315,33 @@ struct fb_info_aty128 {
#endif
int blitter_may_be_busy;
int fifo_slots; /* free slots in FIFO (64 max) */
#ifdef CONFIG_PMAC_PBOOK
unsigned char *save_framebuffer;
int pm_reg;
int crt_on, lcd_on;
#endif
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,
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,
static void __init aty128_get_pllinfo(struct aty128fb_par *par,
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 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_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_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,15 +431,14 @@ 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;
#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;
......@@ -459,75 +446,75 @@ _aty_ld_le32(volatile unsigned int regindex,
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");
"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);
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_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);
}
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;
while (time_before(jiffies, timeout))
if (aty_pll_readupdate(info)) {
if (aty_pll_readupdate(par)) {
reset = 0;
break;
}
......@@ -539,9 +526,9 @@ aty_pll_wait_readupdate(const struct fb_info_aty128 *info)
/* 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);
......@@ -550,7 +537,7 @@ aty_pll_writeupdate(const struct fb_info_aty128 *info)
/* 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;
......@@ -570,56 +557,56 @@ register_test(const struct fb_info_aty128 *info)
}
/*
/*
* 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)
par->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff;
if (par->fifo_slots >= entries)
return;
}
aty128_reset_engine(info);
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);
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(info);
info->blitter_may_be_busy = 0;
aty128_flush_pixel_cache(par);
par->blitter_may_be_busy = 0;
return;
}
}
aty128_reset_engine(info);
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;
......@@ -636,11 +623,11 @@ aty128_flush_pixel_cache(const struct fb_info_aty128 *info)
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;
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);
......@@ -665,25 +652,24 @@ aty128_reset_engine(const struct fb_info_aty128 *info)
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);
wait_for_idle(par);
/* 3D scaler not spoken here */
wait_for_fifo(1, info);
wait_for_fifo(1, par);
aty_st_le32(SCALE_3D_CNTL, 0x00000000);
aty128_reset_engine(info);
aty128_reset_engine(par);
pitch_value = par->crtc.pitch;
if (par->crtc.bpp == 24) {
pitch_value = pitch_value * 3;
}
wait_for_fifo(4, info);
wait_for_fifo(4, par);
/* setup engine offset registers */
aty_st_le32(DEFAULT_OFFSET, 0x00000000);
......@@ -700,7 +686,7 @@ aty128_init_engine(const struct aty128fb_par *par,
GMC_SRC_CLIP_DEFAULT |
GMC_DST_CLIP_DEFAULT |
GMC_BRUSH_SOLIDCOLOR |
(bpp_to_depth(par->crtc.bpp) << 8) |
(depth_to_dst(par->crtc.depth) << 8) |
GMC_SRC_DSTCOLOR |
GMC_BYTE_ORDER_MSB_TO_LSB |
GMC_DP_CONVERSION_TEMP_6500 |
......@@ -711,7 +697,7 @@ aty128_init_engine(const struct aty128fb_par *par,
GMC_AUX_CLIP_CLEAR |
GMC_WRITE_MASK_SET);
wait_for_fifo(8, info);
wait_for_fifo(8, par);
/* clear the line drawing registers */
aty_st_le32(DST_BRES_ERR, 0);
aty_st_le32(DST_BRES_INC, 0);
......@@ -729,35 +715,37 @@ aty128_init_engine(const struct aty128fb_par *par,
aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
/* Wait for all the writes to be completed before returning */
wait_for_idle(info);
wait_for_idle(par);
}
/* convert bpp values to their register representation */
/* convert depth values to their register representation */
static u32
bpp_to_depth(u32 bpp)
depth_to_dst(u32 depth)
{
if (bpp <= 8)
if (depth <= 8)
return DST_8BPP;
else if (bpp <= 16)
else if (depth <= 15)
return DST_15BPP;
else if (bpp <= 24)
else if (depth == 16)
return DST_16BPP;
else if (depth <= 24)
return DST_24BPP;
else if (bpp <= 32)
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);
......@@ -767,26 +755,21 @@ aty128_set_crtc(const struct aty128_crtc *crtc,
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
/* 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)
const struct aty128fb_par *par)
{
u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
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 hsync_strt_pix[5] = { 0, 0x12, 9, 6, 5 };
u8 mode_bytpp[7] = { 0, 0, 1, 2, 2, 3, 4 };
/* input */
......@@ -806,6 +789,11 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
sync = var->sync;
vmode = var->vmode;
if (bpp != 16)
depth = bpp;
else
depth = (var->green.length == 6) ? 16 : 15;
/* check for mode eligibility
* accept only non interlaced modes */
if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
......@@ -821,20 +809,19 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
if (vyres < yres + yoffset)
vyres = yres + yoffset;
/* convert bpp into ATI register depth */
depth = bpp_to_depth(bpp);
/* convert depth into ATI register depth */
dst = depth_to_dst(depth);
/* make sure we didn't get an invalid depth */
if (depth == -EINVAL) {
printk(KERN_ERR "aty128fb: Invalid depth\n");
if (dst == -EINVAL) {
printk(KERN_ERR "aty128fb: Invalid depth or RGBA\n");
return -EINVAL;
}
/* convert depth to bpp */
bytpp = mode_bytpp[depth];
/* convert register depth to bytes per pixel */
bytpp = mode_bytpp[dst];
/* make sure there is enough video ram for the mode */
if ((u32)(vxres * vyres * bytpp) > info->vram_size) {
if ((u32)(vxres * vyres * bytpp) > par->vram_size) {
printk(KERN_ERR "aty128fb: Not enough memory for mode\n");
return -EINVAL;
}
......@@ -857,7 +844,7 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
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)
......@@ -872,13 +859,13 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
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_sync_strt_wid = hsync_strt_pix[bytpp] | (h_sync_strt << 3) |
(h_sync_wid << 16) | (h_sync_pol << 23);
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);
......@@ -895,6 +882,7 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
crtc->vyres = vyres;
crtc->xoffset = xoffset;
crtc->yoffset = yoffset;
crtc->depth = depth;
crtc->bpp = bpp;
return 0;
......@@ -902,10 +890,17 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
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 */
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.offset = 0;
var->blue.msb_right = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
switch (pix_width) {
case CRTC_PIX_WIDTH_8BPP:
var->bits_per_pixel = 8;
......@@ -913,22 +908,23 @@ aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
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;
var->blue.offset = 0;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
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;
......@@ -936,10 +932,7 @@ aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
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;
......@@ -947,7 +940,6 @@ aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
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;
......@@ -998,7 +990,7 @@ aty128_crtc_to_var(const struct aty128_crtc *crtc,
(v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
(c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
aty128_bpp_to_var(pix_width, var);
aty128_pix_width_to_var(pix_width, var);
var->xres = xres;
var->yres = yres;
......@@ -1018,8 +1010,47 @@ aty128_crtc_to_var(const struct aty128_crtc *crtc,
return 0;
}
#ifdef CONFIG_PMAC_PBOOK
static void
aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info)
aty128_set_crt_enable(struct aty128fb_par *par, int on)
{
if (on) {
aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) | CRT_CRTC_ON);
aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) | DAC_PALETTE2_SNOOP_EN));
} else
aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) & ~CRT_CRTC_ON);
}
static void
aty128_set_lcd_enable(struct aty128fb_par *par, int on)
{
u32 reg;
if (on) {
reg = aty_ld_le32(LVDS_GEN_CNTL);
reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION;
reg &= ~LVDS_DISPLAY_DIS;
aty_st_le32(LVDS_GEN_CNTL, reg);
#ifdef CONFIG_PMAC_BACKLIGHT
aty128_set_backlight_enable(get_backlight_enable(),
get_backlight_level(), par);
#endif
} else {
#ifdef CONFIG_PMAC_BACKLIGHT
aty128_set_backlight_enable(0, 0, par);
#endif
reg = aty_ld_le32(LVDS_GEN_CNTL);
reg |= LVDS_DISPLAY_DIS;
aty_st_le32(LVDS_GEN_CNTL, reg);
mdelay(100);
reg &= ~(LVDS_ON /*| LVDS_EN*/);
aty_st_le32(LVDS_GEN_CNTL, reg);
}
}
#endif
static void
aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
{
u32 div3;
......@@ -1034,9 +1065,9 @@ aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info)
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);
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;
......@@ -1045,13 +1076,13 @@ aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info)
div3 |= post_conv[pll->post_divider] << 16;
/* write feedback and post dividers */
aty_pll_wait_readupdate(info);
aty_pll_wait_readupdate(par);
aty_st_pll(PPLL_DIV_3, div3);
aty_pll_writeupdate(info);
aty_pll_writeupdate(par);
aty_pll_wait_readupdate(info);
aty_pll_wait_readupdate(par);
aty_st_pll(HTOTAL_CNTL, 0); /* no horiz crtc adjustment */
aty_pll_writeupdate(info);
aty_pll_writeupdate(par);
/* clear the reset, just in case */
aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
......@@ -1060,9 +1091,9 @@ aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info)
static int
aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
const struct fb_info_aty128 *info)
const struct aty128fb_par *par)
{
const struct aty128_constants c = info->constants;
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 */
......@@ -1102,8 +1133,7 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
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;
......@@ -1113,7 +1143,7 @@ aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var,
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);
......@@ -1123,19 +1153,18 @@ aty128_set_fifo(const struct aty128_ddafifo *dsp,
static int
aty128_ddafifo(struct aty128_ddafifo *dsp,
const struct aty128_pll *pll,
u32 bpp,
const struct fb_info_aty128 *info)
u32 depth,
const struct aty128fb_par *par)
{
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;
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;
u32 n, d, bpp;
/* 15bpp is really 16bpp */
if (bpp == 15)
bpp = 16;
/* round up to multiple of 8 */
bpp = (depth+7) & ~7;
n = xclk * fifo_width;
d = pll->vclk * bpp;
......@@ -1182,16 +1211,14 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
/*
* 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)
{
struct aty128fb_par *par = info->par;
u32 config;
info->current_par = *par;
if (info->blitter_may_be_busy)
wait_for_idle(info);
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);
......@@ -1209,57 +1236,64 @@ aty128_set_par(struct aty128fb_par *par,
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);
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 */
info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
info->fix.visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_DIRECTCOLOR;
#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, info);
aty128_init_engine(par);
#if defined(CONFIG_BOOTX_TEXT)
btext_update_display(info->frame_buffer_phys,
#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
*/
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)))
if ((err = aty128_var_to_crtc(var, &par->crtc, par)))
return err;
if ((err = aty128_var_to_pll(var->pixclock, &par->pll, info)))
if ((err = aty128_var_to_pll(var->pixclock, &par->pll, par)))
return err;
if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp, info)))
if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.depth, par)))
return err;
if (var->accel_flags & FB_ACCELF_TEXT)
par->accel_flags = FB_ACCELF_TEXT;
else
par->accel_flags = 0;
par->accel_flags = var->accel_flags;
return 0;
}
......@@ -1267,22 +1301,16 @@ aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par,
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;
if ((err = aty128_pll_to_var(&par->pll, var, info)))
if ((err = aty128_pll_to_var(&par->pll, var)))
return err;
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
var->activate = 0;
......@@ -1294,218 +1322,27 @@ aty128_encode_var(struct fb_var_screeninfo *var,
}
/*
* Get the User Defined Part of the Display
*/
static int
aty128fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
{
const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
if (con == -1)
aty128_encode_var(var, &info->default_par, info);
else
*var = fb_display[con].var;
return 0;
}
/*
* Set the User Defined Part of the Display
*/
static int
aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par par;
struct display *display;
int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
int accel, err;
display = (con >= 0) ? &fb_display[con] : fb->disp;
/* basic (in)sanity checks */
if (!var->xres)
var->xres = 1;
if (!var->yres)
var->yres = 1;
if (var->xres > var->xres_virtual)
var->xres_virtual = var->xres;
if (var->yres > var->yres_virtual)
var->yres_virtual = var->yres;
switch (var->bits_per_pixel) {
case 0 ... 8:
var->bits_per_pixel = 8;
break;
case 9 ... 16:
var->bits_per_pixel = 16;
break;
case 17 ... 24:
var->bits_per_pixel = 24;
break;
case 25 ... 32:
var->bits_per_pixel = 32;
break;
default:
return -EINVAL;
}
if ((err = aty128_decode_var(var, &par, info)))
return err;
aty128_encode_var(var, &par, info);
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
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);
struct aty128fb_par *par = info->par;
int err;
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
if ((err = aty128_decode_var(var, par)) != 0)
return err;
do_install_cmap(con, &info->fb_info);
}
aty128_encode_var(var, par);
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!)
*/
static int
aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par *par = &info->current_par;
struct aty128fb_par *par = fb->par;
u32 xoffset, yoffset;
u32 offset;
u32 xres, yres;
......@@ -1522,7 +1359,10 @@ aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
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;
if (par->crtc.bpp == 24)
offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */
aty_st_le32(CRTC_OFFSET, offset);
......@@ -1530,39 +1370,40 @@ aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
}
/*
* Get the Colormap
/*
* Helper function to store a single palette register
*/
static int
aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
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 (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
*/
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);
}
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;
}
......@@ -1589,13 +1430,19 @@ aty128fb_setup(char *options)
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;
}
#endif
#ifdef CONFIG_PPC
#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);
......@@ -1618,7 +1465,7 @@ aty128fb_setup(char *options)
break;
}
}
#endif /* CONFIG_PPC */
#endif /* CONFIG_ALL_PPC */
else
mode_option = this_opt;
}
......@@ -1626,54 +1473,59 @@ aty128fb_setup(char *options)
}
/*
/*
* Initialisation
*/
static int __init
aty128_init(struct fb_info_aty128 *info, const char *name)
aty128_init(struct fb_info *info, const char *name)
{
struct aty128fb_par *par = info->par;
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";
const char *video_card;
if (!info->vram_size) /* may have already been probed */
info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
if (!par->vram_size) /* may have already been probed */
par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
/* Get the chip revision */
chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
/* 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;
while (aci->name && par->pdev->device != aci->device)
aci++;
video_card = aci->name? aci->name: "Rage128";
par->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);
if (par->vram_size % (1024 * 1024) == 0)
printk("%dM %s\n", par->vram_size / (1024*1024), par->mem->name);
else
printk("%dk %s\n", info->vram_size / 1024, info->mem->name);
printk("%dk %s\n", par->vram_size / 1024, par->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;
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
var = default_var;
#ifdef CONFIG_PPC
#ifdef CONFIG_ALL_PPC
if (_machine == _MACH_Pmac) {
if (mode_option) {
if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
if (!mac_find_mode(&var, info, mode_option, 8))
var = default_var;
} else {
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
......@@ -1709,9 +1561,9 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
var = default_var;
}
} else
#endif /* CONFIG_PPC */
#endif /* CONFIG_ALL_PPC */
{
if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
if (fb_find_mode(&var, info, mode_option, NULL, 0,
&defaultmode, 8) == 0)
var = default_var;
}
......@@ -1721,70 +1573,55 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
else
var.accel_flags |= FB_ACCELF_TEXT;
if (aty128_decode_var(&var, &info->default_par, info)) {
if (aty128fb_check_var(&var, info)) {
printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
return 0;
}
/* 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];
}
/* setup the DAC the way we like it */
dac = aty_ld_le32(DAC_CNTL);
dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL);
dac |= DAC_MASK;
if (par->chip_gen == rage_M3)
dac |= DAC_PALETTE2_SNOOP_EN;
aty_st_le32(DAC_CNTL, dac);
/* turn off bus mastering, just in case */
aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS);
aty128fb_set_var(&var, -1, &info->fb_info);
aty128_init_engine(&info->default_par, info);
info->var = var;
fb_alloc_cmap(&info->cmap, 256, 0);
gen_set_disp(-1, info);
board_list = aty128_board_list_add(board_list, info);
var.activate = FB_ACTIVATE_NOW;
gen_set_var(&var, -1, info);
size = (var.bits_per_pixel <= 8) ? 256 : 32;
fb_alloc_cmap(&info->fb_info.cmap, size, 0);
aty128_init_engine(par);
if (register_framebuffer(&info->fb_info) < 0)
if (register_framebuffer(info) < 0)
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");
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->fb_info.node), aty128fb_name, name);
GET_FB_IDX(info->node), aty128fb_name, name);
return 1; /* success! */
}
/* 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;
new_node->next = NULL;
if(board_list == NULL)
return new_node;
while(i_p->next != NULL)
i_p = i_p->next;
i_p->next = new_node;
return board_list;
}
int __init
aty128fb_init(void)
{
......@@ -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 @@ aty128_pci_register(struct pci_dev *pdev,
/* 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,9 +1871,9 @@ 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
#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 */
......@@ -2032,95 +1881,68 @@ aty128_timings(struct fb_info_aty128 *info)
u32 x_mpll_ref_fb_div;
u32 xclk_cntl;
u32 Nx, M;
unsigned PostDivSet[] =
{ 0, 1, 2, 4, 8, 3, 6, 12 };
unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 };
#endif
if (!info->constants.dotclock)
info->constants.dotclock = 2950;
if (!par->constants.dotclock)
par->constants.dotclock = 2950;
#ifdef CONFIG_PPC
#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;
info->constants.xclk = round_div((2 * Nx *
info->constants.dotclock), (M * PostDivSet[xclk_cntl]));
par->constants.xclk = round_div((2 * Nx * par->constants.dotclock),
(M * PostDivSet[xclk_cntl]));
info->constants.ref_divider =
par->constants.ref_divider =
aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
#endif
if (!info->constants.ref_divider) {
info->constants.ref_divider = 0x3b;
if (!par->constants.ref_divider) {
par->constants.ref_divider = 0x3b;
aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);
aty_pll_writeupdate(info);
aty_pll_writeupdate(par);
}
aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider);
aty_pll_writeupdate(info);
aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider);
aty_pll_writeupdate(par);
/* 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 */
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 */
info->constants.fifo_width = 128;
info->constants.fifo_depth = 32;
par->constants.fifo_width = 128;
par->constants.fifo_depth = 32;
switch (aty_ld_le32(MEM_CNTL) & 0x3) {
case 0:
info->mem = &sdr_128;
par->mem = &sdr_128;
break;
case 1:
info->mem = &sdr_sgram;
par->mem = &sdr_sgram;
break;
case 2:
info->mem = &ddr_sgram;
par->mem = &ddr_sgram;
break;
default:
info->mem = &sdr_sgram;
par->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;
/* Do we have to save the colormap? */
if (fb_display[fb->currcon].cmap.len)
fb_get_cmap(&fb_display[fb->currcon].cmap, 1,
aty128_getcolreg, fb);
/* set the current console */
fb->currcon = con;
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);
do_install_cmap(con, fb);
return 1;
}
/*
* Blank the display.
*/
static int
aty128fb_blank(int blank, struct fb_info *fb)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
struct aty128fb_par *par = fb->par;
u8 state = 0;
#ifdef CONFIG_PMAC_BACKLIGHT
......@@ -2137,6 +1959,12 @@ aty128fb_blank(int blank, struct fb_info *fb)
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);
......@@ -2144,122 +1972,111 @@ aty128fb_blank(int blank, struct fb_info *fb)
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;
}
/*
/*
* 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)
u_int transp, struct fb_info *info)
{
struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
u32 col;
struct aty128fb_par *par = info->par;
if (regno > 255)
if (regno > 255
|| (par->crtc.depth == 16 && regno > 63)
|| (par->crtc.depth == 15 && regno > 31))
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)) {
if (regno < 16) {
int i;
if (info->chip_gen == rage_M3)
aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
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 (info->chip_gen == rage_M3) {
aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
for (i=16; i<256; i++) {
aty_st_8(PALETTE_INDEX, i);
col = (i << 16) | (i << 8) | i;
aty_st_le32(PALETTE_DATA, col);
}
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;
}
}
/* initialize palette */
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;
}
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);
}
#define ATY_MIRROR_LCD_ON 0x00000001
#define ATY_MIRROR_CRT_ON 0x00000002
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;
/* 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*))
i = (regno << 8) | regno;
info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
break;
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);
}
#endif
}
return 0;
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
}
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)
#ifdef CONFIG_PMAC_PBOOK
static void
aty128_set_suspend(struct aty128fb_par *par, int suspend)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
u32 pmgt;
u16 pwr_command;
if (fb->blitter_may_be_busy)
wait_for_idle(fb);
if (!par->pm_reg)
return;
fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
/* 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_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)
/*
* Save the contents of the frame buffer when we go to sleep,
* and restore it when we wake up again.
*/
int
aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
{
struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
if (fb->blitter_may_be_busy)
wait_for_idle(fb);
struct fb_info_aty128 *board;
int result;
fbcon_cfb32_putc(conp, p, c, yy, xx);
}
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;
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);
nb = info->var.yres * info->fix.line_length;
if (fb->blitter_may_be_busy)
wait_for_idle(fb);
switch (when) {
case PBOOK_SLEEP_REQUEST:
par->save_framebuffer = vmalloc(nb);
if (par->save_framebuffer == NULL)
return PBOOK_SLEEP_REFUSE;
break;
case PBOOK_SLEEP_REJECT:
if (par->save_framebuffer) {
vfree(par->save_framebuffer);
par->save_framebuffer = 0;
}
break;
case PBOOK_SLEEP_NOW:
if (info->currcon >= 0)
fb_display[info->currcon].dispsw = &fbcon_dummy;
fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
}
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);
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);
/* Blank display and LCD */
aty128fb_blank(VESA_POWERDOWN, info);
if (fb->blitter_may_be_busy)
wait_for_idle(fb);
/* Sleep the chip */
aty128_set_suspend(par, 1);
fbcon_cfb32_clear_margins(conp, p, bottom_only);
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>");
......@@ -2605,18 +2388,18 @@ cleanup_module(void)
unregister_framebuffer(&info->fb_info);
#ifdef CONFIG_MTRR
if (info->mtrr.vram_valid)
mtrr_del(info->mtrr.vram, info->frame_buffer_phys,
mtrr_del(info->mtrr.vram, info->fix.smem_start,
info->vram_size);
#endif /* CONFIG_MTRR */
iounmap(info->regbase);
iounmap(info->frame_buffer);
release_mem_region(pci_resource_start(info->pdev, 0),
pci_resource_len(info->pdev, 0));
release_mem_region(pci_resource_start(info->pdev, 1),
pci_resource_len(info->pdev, 1));
release_mem_region(pci_resource_start(info->pdev, 2),
pci_resource_len(info->pdev, 2));
iounmap(info->par.regbase);
iounmap(info->fb_info.screen_base);
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);
}
......
......@@ -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;
}
......@@ -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;
}
}
}
}
......@@ -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)
......@@ -97,7 +97,8 @@ 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) |
......@@ -118,7 +119,8 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
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) ^
......@@ -140,49 +142,85 @@ void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
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); */
/*
* 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;
n = (rect->width - start_index - end_index) / ppw;
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;
}
......@@ -23,6 +23,13 @@
* 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,48 +46,191 @@
#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 pad, ppw;
int x2, y2, n, i, j, k, l = 7;
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 fgx, bgx, fgcolor, bgcolor, eorx;
unsigned long end_mask;
unsigned long *dst = NULL;
u8 *dst1;
u8 *src;
unsigned long ppw = BITS_PER_LONG / p->var.bits_per_pixel;
unsigned long *dst;
u32 *tab = NULL;
char *src = image->data;
/*
* We could use hardware clipping but on many cards you get around hardware
* clipping by writing to framebuffer directly like we are doing here.
*/
x2 = image->dx + image->width;
y2 = image->dy + image->height;
image->dx = image->dx > 0 ? image->dx : 0;
image->dy = image->dy > 0 ? image->dy : 0;
x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual;
y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual;
image->width = x2 - image->dx;
image->height = y2 - image->dy;
switch (ppw) {
case 4:
tab = cfb_tab8;
break;
case 2:
tab = cfb_tab16;
break;
case 1:
tab = cfb_tab32;
break;
}
dst1 = p->screen_base + image->dy * p->fix.line_length +
((image->dx * p->var.bits_per_pixel) >> 3);
for (i = ppw - 1; i--;) {
fgx <<= p->var.bits_per_pixel;
bgx <<= p->var.bits_per_pixel;
fgx |= fgcolor;
bgx |= bgcolor;
}
ppw = BITS_PER_LONG/p->var.bits_per_pixel;
n = ((image->width + 7) >> 3);
pad = (n << 3) - image->width;
n = image->width % ppw;
src = image->data;
bit_mask = (1 << ppw) - 1;
eorx = fgx ^ bgx;
if (image->depth == 1) {
k = image->width / ppw;
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];
} else {
fgx = fgcolor = image->fg_color;
bgx = bgcolor = image->bg_color;
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 i, j, k, l = 8, n, pad, ppw;
unsigned long tmp = ~0 << (BITS_PER_LONG - p->var.bits_per_pixel);
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++) {
for (i = 0; i < ppw - 1; i++) {
fgx <<= p->var.bits_per_pixel;
bgx <<= p->var.bits_per_pixel;
fgx |= fgcolor;
......@@ -94,34 +244,95 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image)
for (i = 0; i < image->height; i++) {
dst = (unsigned long *) dst1;
for (j = image->width/ppw; j > 0; j--) {
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++; }
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);
}
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++; }
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);
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;
/*
* We could use hardware clipping but on many cards you get around hardware
* clipping by writing to framebuffer directly like we are doing here.
*/
x2 = image->dx + image->width;
y2 = image->dy + image->height;
image->dx = image->dx > 0 ? image->dx : 0;
image->dy = image->dy > 0 ? image->dy : 0;
x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual;
y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual;
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);
if (image->depth == 1) {
if (p->fix.visual == FB_VISUAL_TRUECOLOR) {
fgcolor =
((u32 *) (p->pseudo_palette))[image->fg_color];
bgcolor =
((u32 *) (p->pseudo_palette))[image->bg_color];
} else {
fgcolor = image->fg_color;
bgcolor = image->bg_color;
}
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;
......
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.
#
# 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
# 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/' > $@
......@@ -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;
......
......@@ -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);
......@@ -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,7 +36,6 @@ 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);
......@@ -47,11 +44,10 @@ int gen_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *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");
......@@ -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;
......
......@@ -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
......
......@@ -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,
......
/*
* 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 */
......@@ -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);
......
#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_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,
......@@ -84,18 +97,22 @@ struct video_info {
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment