diff options
Diffstat (limited to 'drivers/video')
121 files changed, 4992 insertions, 2710 deletions
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 6a3cfbdc6dc..3b0ddc55236 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -113,7 +113,6 @@ static struct fb_ops mc68x328fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = mc68x328fb_mmap, }; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 773ae11b4a1..3e470c8b419 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -65,15 +65,6 @@ config FB_CFB_IMAGEBLIT blitting. This is used by drivers that don't provide their own (accelerated) version. -config FB_SOFT_CURSOR - tristate - depends on FB - default n - ---help--- - Include the soft_cursor function for generic software cursor support. - This is used by drivers that don't provide their own (accelerated) - version. - config FB_MACMODES tristate depends on FB @@ -114,7 +105,6 @@ config FB_CIRRUS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This enables support for Cirrus Logic GD542x/543x based boards on Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. @@ -133,7 +123,6 @@ config FB_PM2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Permedia2 AGP frame buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a @@ -152,7 +141,6 @@ config FB_ARMCLCD select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This framebuffer device driver is for the ARM PrimeCell PL110 Colour LCD controller. ARM PrimeCells provide the building @@ -169,7 +157,6 @@ config FB_ACORN select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Acorn VIDC graphics hardware found in Acorn RISC PCs and other ARM-based machines. If @@ -181,7 +168,9 @@ config FB_CLPS711X select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR + help + Say Y to enable the Framebuffer driver for the CLPS7111 and + EP7212 processors. config FB_SA1100 bool "SA-1100 LCD support" @@ -189,7 +178,6 @@ config FB_SA1100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is a framebuffer device for the SA-1100 LCD Controller. See <http://www.linux-fbdev.org/> for information on framebuffer @@ -204,7 +192,6 @@ config FB_IMX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_CYBER2000 tristate "CyberPro 2000/2010/5000 support" @@ -212,7 +199,6 @@ config FB_CYBER2000 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Integraphics CyberPro 20x0 and 5000 VGA chips used in the Rebel.com Netwinder and other machines. @@ -225,7 +211,6 @@ config FB_APOLLO default y select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_Q40 bool @@ -234,12 +219,10 @@ config FB_Q40 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_AMIGA tristate "Amiga native chipset support" depends on FB && AMIGA - select FB_SOFT_CURSOR help This is the frame buffer device driver for the builtin graphics chipset found in Amigas. @@ -279,7 +262,6 @@ config FB_CYBER select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Cybervision 64 graphics card from Phase5. Please note that its use is not all that intuitive (i.e. if @@ -294,7 +276,6 @@ config FB_VIRGE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Cybervision 64/3D graphics card from Phase5. Please note that its use is not all that intuitive (i.e. if @@ -317,7 +298,6 @@ config FB_FM2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Amiga FrameMaster card from BSC (exhibited 1992 but not shipped as a CBM product). @@ -328,7 +308,6 @@ config FB_ARC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Arc Monochrome LCD board. The board is based on the KS-108 lcd controller and is typically a matrix @@ -351,7 +330,6 @@ config FB_OF select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help Say Y if you want support with Open Firmware for your graphics @@ -363,7 +341,6 @@ config FB_CONTROL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the graphics adapter in the @@ -375,7 +352,6 @@ config FB_PLATINUM select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the "platinum" graphics @@ -387,7 +363,6 @@ config FB_VALKYRIE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the "valkyrie" graphics @@ -399,42 +374,32 @@ config FB_CT65550 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Chips & Technologies 65550 graphics chip in PowerBooks. config FB_ASILIANT - bool "Chips 69000 display support" + bool "Asiliant (Chips) 69000 display support" depends on (FB = y) && PCI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_IMSTT bool "IMS Twin Turbo display support" depends on (FB = y) && PCI select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help The IMS Twin Turbo is a PCI-based frame buffer card bundled with many Macintosh and compatible computers. -config FB_S3TRIO - bool "S3 Trio display support" - depends on (FB = y) && PPC && BROKEN - help - If you have a S3 Trio say Y. Say N for S3 Virge. - config FB_VGA16 tristate "VGA 16-color graphics support" depends on FB && (X86 || PPC) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for VGA 16 color graphic cards. Say Y if you have such a card. @@ -448,7 +413,6 @@ config FB_STI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR default y ---help--- STI refers to the HP "Standard Text Interface" which is a set of @@ -469,7 +433,6 @@ config FB_MAC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES # bool ' Apple DAFB display support' CONFIG_FB_DAFB @@ -478,7 +441,6 @@ config FB_HP300 depends on (FB = y) && HP300 select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR default y config FB_TGA @@ -487,18 +449,16 @@ config FB_TGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for generic TGA graphic cards. Say Y if you have one of those. config FB_VESA bool "VESA VGA graphics support" - depends on (FB = y) && (X86 || X86_64) + depends on (FB = y) && X86 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for generic VESA 2.0 compliant graphic cards. The older VESA 1.2 cards are not supported. @@ -516,7 +476,6 @@ config FB_HGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you have a Hercules mono graphics card. @@ -545,7 +504,6 @@ config FB_SGIVW select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help SGI Visual Workstation support for framebuffer graphics. @@ -555,7 +513,6 @@ config FB_GBE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for SGI Graphics Backend. This chip is used in SGI O2 and Visual Workstation 320/540. @@ -577,22 +534,27 @@ config FB_SUN3 bool "Sun3 framebuffer support" depends on (FB = y) && (SUN3 || SUN3X) && BROKEN +config FB_SBUS + bool "SBUS and UPA framebuffers" + depends on (FB = y) && (SPARC32 || SPARC64) + help + Say Y if you want support for SBUS or UPA based frame buffer device. + config FB_BW2 bool "BWtwo support" depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the BWtwo frame buffer. config FB_CG3 bool "CGthree support" depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) + select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGthree frame buffer. @@ -601,7 +563,6 @@ config FB_CG6 depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGsix (GX, TurboGX) frame buffer. @@ -612,7 +573,6 @@ config FB_PVR2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Say Y here if you have a PowerVR 2 card in your box. If you plan to run linux on your Dreamcast, you will have to say Y here. @@ -634,13 +594,23 @@ config FB_EPSON1355 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Build in support for the SED1355 Epson Research Embedded RAMDAC LCD/CRT Controller (since redesignated as the S1D13505) as a framebuffer. Product specs at <http://www.erd.epson.com/vdc/html/products.htm>. +config FB_S1D13XXX + tristate "Epson S1D13XXX framebuffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for S1D13XXX framebuffer device family (currently only + working with S1D13806). Product specs at + <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm> + config FB_NVIDIA tristate "nVidia Framebuffer Support" depends on FB && PCI @@ -650,7 +620,6 @@ config FB_NVIDIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports graphics boards with the nVidia chips, TNT and newer. For very old chipsets, such as the RIVA128, then use @@ -662,7 +631,7 @@ config FB_NVIDIA config FB_NVIDIA_I2C bool "Enable DDC Support" - depends on FB_NVIDIA && !PPC_OF + depends on FB_NVIDIA help This enables I2C support for nVidia Chipsets. This is used only for getting EDID information from the attached display @@ -712,7 +681,7 @@ config FB_RIVA_DEBUG config FB_I810 tristate "Intel 810/815 support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64 + depends on FB && EXPERIMENTAL && PCI && X86_32 select AGP select AGP_INTEL select FB_MODE_HELPERS @@ -761,7 +730,7 @@ config FB_I810_I2C config FB_INTEL tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64 + depends on FB && EXPERIMENTAL && PCI && X86_32 select AGP select AGP_INTEL select FB_MODE_HELPERS @@ -790,7 +759,6 @@ config FB_MATROX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_TILEBLITTING select FB_MACMODES if PPC_PMAC ---help--- @@ -931,7 +899,6 @@ config FB_RADEON_OLD select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help Choose this option if you want to use an ATI Radeon graphics card as @@ -949,7 +916,6 @@ config FB_RADEON select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC_OF help Choose this option if you want to use an ATI Radeon graphics card as @@ -987,7 +953,6 @@ config FB_ATY128 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC_PMAC help This driver supports graphics boards with the ATI Rage128 chips. @@ -1003,7 +968,6 @@ config FB_ATY select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help This driver supports graphics boards with the ATI Mach64 chips. @@ -1046,6 +1010,12 @@ config FB_ATY_GX is at <http://support.ati.com/products/pc/mach64/graphics_xpression.html>. +config FB_S3TRIO + bool "S3 Trio display support" + depends on (FB = y) && PPC && BROKEN + help + If you have a S3 Trio say Y. Say N for S3 Virge. + config FB_SAVAGE tristate "S3 Savage support" depends on FB && PCI && EXPERIMENTAL @@ -1055,7 +1025,6 @@ config FB_SAVAGE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports notebooks and computers with S3 Savage PCI/AGP chips. @@ -1092,7 +1061,6 @@ config FB_SIS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the SiS 300, 315, 330 and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. @@ -1122,7 +1090,6 @@ config FB_NEOMAGIC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports notebooks with NeoMagic PCI chips. Say Y if you have such a graphics card. @@ -1136,7 +1103,6 @@ config FB_KYRO select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you have a STG4000 / Kyro / PowerVR 3 based graphics board. @@ -1150,7 +1116,6 @@ config FB_3DFX select FB_CFB_IMAGEBLIT select FB_CFB_FILLRECT select FB_CFB_COPYAREA - select FB_SOFT_CURSOR help This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 chips. Say Y if you have such a graphics board. @@ -1172,7 +1137,6 @@ config FB_VOODOO1 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or Voodoo2 (cvg) based graphics card. @@ -1189,7 +1153,6 @@ config FB_CYBLA tristate "Cyberblade/i1 support" depends on FB && PCI select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select VIDEO_SELECT ---help--- This driver is supposed to support the Trident Cyberblade/i1 @@ -1217,7 +1180,6 @@ config FB_TRIDENT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This driver is supposed to support graphics boards with the Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops @@ -1249,56 +1211,17 @@ config FB_PM3 similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 and maybe other boards. -config FB_E1356 - tristate "Epson SED1356 framebuffer support" - depends on FB && EXPERIMENTAL && PCI && MIPS - -config PB1000_CRT - bool "Use CRT on Pb1000 (J65)" - depends on MIPS_PB1000=y && FB_E1356 - -config PB1000_NTSC - bool "Use Compsite NTSC on Pb1000 (J63)" - depends on MIPS_PB1000=y && FB_E1356 - -config PB1000_TFT - bool "Use TFT Panel on Pb1000 (J64)" - depends on MIPS_PB1000=y && FB_E1356 - -config PB1500_CRT - bool "Use CRT on Pb1500 " if MIPS_PB1500=y - depends on FB_E1356 - -config PB1500_CRT - prompt "Use CRT on Pb1100 " - depends on FB_E1356 && MIPS_PB1100=y - -config PB1500_TFT - bool "Use TFT Panel on Pb1500 " if MIPS_PB1500=y - depends on FB_E1356 - -config PB1500_TFT - prompt "Use TFT Panel on Pb1100 " - depends on FB_E1356 && MIPS_PB1100=y - config FB_AU1100 bool "Au1100 LCD Driver" depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y source "drivers/video/geode/Kconfig" -config FB_SBUS - bool "SBUS and UPA framebuffers" - depends on (FB = y) && (SPARC32 || SPARC64) - help - Say Y if you want support for SBUS or UPA based frame buffer device. - config FB_FFB bool "Creator/Creator3D/Elite3D support" depends on FB_SBUS && SPARC64 select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Creator, Creator3D, and Elite3D graphics boards. @@ -1309,7 +1232,6 @@ config FB_TCX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the TCX 24/8bit frame buffer. @@ -1320,7 +1242,6 @@ config FB_CG14 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGfourteen frame buffer on Desktop SPARCsystems with the SX graphics option. @@ -1331,7 +1252,6 @@ config FB_P9100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the P9100 card supported on Sparcbook 3 machines. @@ -1342,7 +1262,6 @@ config FB_LEO select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the SBUS-based Sun ZX (leo) frame buffer cards. @@ -1357,7 +1276,6 @@ config FB_IGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the framebuffer device for the INTERGRAPHICS 1680 and successor frame buffer cards. @@ -1368,40 +1286,36 @@ config FB_HIT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Hitachi HD64461 LCD frame buffer card. config FB_PMAG_AA bool "PMAG-AA TURBOchannel framebuffer support" - depends on (FB = y) && MACH_DECSTATION && TC + depends on (FB = y) && TC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1) used mainly in the MIPS-based DECstation series. config FB_PMAG_BA bool "PMAG-BA TURBOchannel framebuffer support" - depends on (FB = y) && MACH_DECSTATION && TC + depends on (FB = y) && TC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8) used mainly in the MIPS-based DECstation series. config FB_PMAGB_B bool "PMAGB-B TURBOchannel framebuffer support" - depends on (FB = y) && MACH_DECSTATION && TC + depends on (FB = y) && TC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAGB-B TURBOchannel framebuffer card used mainly in the MIPS-based DECstation series. The card is currently only @@ -1409,11 +1323,10 @@ config FB_PMAGB_B config FB_MAXINE bool "Maxine (Personal DECstation) onboard framebuffer support" - depends on (FB = y) && MACH_DECSTATION && TC + depends on (FB = y) && MACH_DECSTATION select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the onboard framebuffer (1024x768x8) in the Personal DECstation series (Personal DECstation 5000/20, /25, /33, /50, @@ -1425,7 +1338,6 @@ config FB_TX3912 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>. @@ -1438,7 +1350,6 @@ config FB_G364 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help The G364 driver is the framebuffer used in MIPS Magnum 4000 and Olivetti M700-10 systems. @@ -1449,7 +1360,6 @@ config FB_68328 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you want to support the built-in frame buffer of the Motorola 68328 CPU family. @@ -1460,7 +1370,6 @@ config FB_PXA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the built-in LCD controller in the Intel PXA2x0 processor. @@ -1472,23 +1381,6 @@ config FB_PXA If unsure, say N. -config FB_W100 - tristate "W100 frame buffer support" - depends on FB && PXA_SHARPSL - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR - ---help--- - Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called vfb. If you want to compile it as a module, - say M here and read <file:Documentation/modules.txt>. - - If unsure, say N. - config FB_PXA_PARAMETERS bool "PXA LCD command line parameters" default n @@ -1506,17 +1398,21 @@ config FB_PXA_PARAMETERS <file:Documentation/fb/pxafb.txt> describes the available parameters. -config FB_S1D13XXX - tristate "Epson S1D13XXX framebuffer support" - depends on FB - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR - help - Support for S1D13XXX framebuffer device family (currently only - working with S1D13806). Product specs at - <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm> +config FB_W100 + tristate "W100 frame buffer support" + depends on FB && PXA_SHARPSL + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called vfb. If you want to compile it as a module, + say M here and read <file:Documentation/modules.txt>. + + If unsure, say N. config FB_S3C2410 tristate "S3C2410 LCD framebuffer support" @@ -1524,7 +1420,6 @@ config FB_S3C2410 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the built-in LCD controller in the Samsung S3C2410 processor. @@ -1548,7 +1443,6 @@ config FB_VIRTUAL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This is a `virtual' frame buffer device. It operates on a chunk of unswappable kernel memory instead of on the memory of a graphics diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 1fff29f48ca..aa434e725c0 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -16,7 +16,6 @@ fb-objs := $(fb-y) obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o -obj-$(CONFIG_FB_SOFT_CURSOR) += softcursor.o obj-$(CONFIG_FB_MACMODES) += macmodes.o # Hardware specific drivers go first @@ -86,7 +85,7 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o obj-$(CONFIG_FB_PXA) += pxafb.o obj-$(CONFIG_FB_W100) += w100fb.o -obj-$(CONFIG_FB_AU1100) += au1100fb.o fbgen.o +obj-$(CONFIG_FB_AU1100) += au1100fb.o obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index f02965f3950..750cebb1830 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -26,7 +26,7 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/fb.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <asm/hardware.h> @@ -926,7 +926,6 @@ static struct fb_ops acornfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = acornfb_mmap, - .fb_cursor = soft_cursor, }; /* @@ -1280,7 +1279,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end) printk("acornfb: freed %dK memory\n", mb_freed); } -static int __init acornfb_probe(struct device *dev) +static int __init acornfb_probe(struct platform_device *dev) { unsigned long size; u_int h_sync, v_sync; @@ -1293,7 +1292,7 @@ static int __init acornfb_probe(struct device *dev) acornfb_init_fbinfo(); - current_par.dev = dev; + current_par.dev = &dev->dev; if (current_par.montype == -1) current_par.montype = acornfb_detect_monitortype(); @@ -1454,15 +1453,16 @@ static int __init acornfb_probe(struct device *dev) return 0; } -static struct device_driver acornfb_driver = { - .name = "acornfb", - .bus = &platform_bus_type, +static struct platform_driver acornfb_driver = { .probe = acornfb_probe, + .driver = { + .name = "acornfb", + }, }; static int __init acornfb_init(void) { - return driver_register(&acornfb_driver); + return platform_driver_register(&acornfb_driver); } module_init(acornfb_init); diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 321dbe91dc1..a3c2c45e29e 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -22,6 +22,7 @@ #include <linux/ioport.h> #include <linux/list.h> +#include <asm/sizes.h> #include <asm/hardware/amba.h> #include <asm/hardware/clock.h> @@ -332,7 +333,6 @@ static struct fb_ops clcdfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = clcdfb_mmap, }; @@ -504,21 +504,21 @@ static int clcdfb_remove(struct amba_device *dev) static struct amba_id clcdfb_id_table[] = { { .id = 0x00041110, - .mask = 0x000fffff, + .mask = 0x000ffffe, }, { 0, 0 }, }; static struct amba_driver clcd_driver = { .drv = { - .name = "clcd-pl110", + .name = "clcd-pl11x", }, .probe = clcdfb_probe, .remove = clcdfb_remove, .id_table = clcdfb_id_table, }; -int __init amba_clcdfb_init(void) +static int __init amba_clcdfb_init(void) { if (fb_get_options("ambafb", NULL)) return -ENODEV; diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index cf8bb67462d..d549e215f3c 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1185,7 +1185,6 @@ static struct fb_ops amifb_ops = { .fb_fillrect = amifb_fillrect, .fb_copyarea = amifb_copyarea, .fb_imageblit = amifb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = amifb_ioctl, }; diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index d28457e0c06..080db812ca4 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -47,6 +47,7 @@ #include <linux/fb.h> #include <linux/init.h> #include <linux/arcfb.h> +#include <linux/platform_device.h> #include <asm/uaccess.h> @@ -501,10 +502,6 @@ static ssize_t arcfb_write(struct file *file, const char *buf, size_t count, return err; } -static void arcfb_platform_release(struct device *device) -{ -} - static struct fb_ops arcfb_ops = { .owner = THIS_MODULE, .fb_open = arcfb_open, @@ -514,13 +511,11 @@ static struct fb_ops arcfb_ops = { .fb_fillrect = arcfb_fillrect, .fb_copyarea = arcfb_copyarea, .fb_imageblit = arcfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = arcfb_ioctl, }; -static int __init arcfb_probe(struct device *device) +static int __init arcfb_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(device); struct fb_info *info; int retval = -ENOMEM; int videomemorysize; @@ -563,7 +558,7 @@ static int __init arcfb_probe(struct device *device) retval = register_framebuffer(info); if (retval < 0) goto err1; - dev_set_drvdata(&dev->dev, info); + platform_set_drvdata(dev, info); if (irq) { par->irq = irq; if (request_irq(par->irq, &arcfb_interrupt, SA_SHIRQ, @@ -604,9 +599,9 @@ err: return retval; } -static int arcfb_remove(struct device *device) +static int arcfb_remove(struct platform_device *dev) { - struct fb_info *info = dev_get_drvdata(device); + struct fb_info *info = platform_get_drvdata(dev); if (info) { unregister_framebuffer(info); @@ -616,20 +611,15 @@ static int arcfb_remove(struct device *device) return 0; } -static struct device_driver arcfb_driver = { - .name = "arcfb", - .bus = &platform_bus_type, +static struct platform_driver arcfb_driver = { .probe = arcfb_probe, .remove = arcfb_remove, + .driver = { + .name = "arcfb", + }, }; -static struct platform_device arcfb_device = { - .name = "arcfb", - .id = 0, - .dev = { - .release = arcfb_platform_release, - } -}; +static struct platform_device *arcfb_device; static int __init arcfb_init(void) { @@ -638,11 +628,18 @@ static int __init arcfb_init(void) if (!arcfb_enable) return -ENXIO; - ret = driver_register(&arcfb_driver); + ret = platform_driver_register(&arcfb_driver); if (!ret) { - ret = platform_device_register(&arcfb_device); - if (ret) - driver_unregister(&arcfb_driver); + arcfb_device = platform_device_alloc("arcfb", 0); + if (arcfb_device) { + ret = platform_device_add(arcfb_device); + } else { + ret = -ENOMEM; + } + if (ret) { + platform_device_put(arcfb_device); + platform_driver_unregister(&arcfb_driver); + } } return ret; @@ -650,8 +647,8 @@ static int __init arcfb_init(void) static void __exit arcfb_exit(void) { - platform_device_unregister(&arcfb_device); - driver_unregister(&arcfb_driver); + platform_device_unregister(arcfb_device); + platform_driver_unregister(&arcfb_driver); } module_param(num_cols, ulong, 0); diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index f4729f4df8c..c64de59398f 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -106,7 +106,6 @@ static struct fb_ops asiliantfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* Calculate the ratios for the dot clocks without using a single long long diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h index 13321c689cf..39ab483fc25 100644 --- a/drivers/video/aty/ati_ids.h +++ b/drivers/video/aty/ati_ids.h @@ -150,6 +150,7 @@ #define PCI_CHIP_RV200_QX 0x5158 #define PCI_CHIP_RV100_QY 0x5159 #define PCI_CHIP_RV100_QZ 0x515A +#define PCI_CHIP_RN50 0x515E #define PCI_CHIP_RAGE128RE 0x5245 #define PCI_CHIP_RAGE128RF 0x5246 #define PCI_CHIP_RAGE128RG 0x5247 diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index e380ee8b024..e686185a076 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -478,7 +478,6 @@ static struct fb_ops aty128fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; #ifdef CONFIG_PMAC_BACKLIGHT diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 037fe9d32fe..08edbfcfca5 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -292,7 +292,6 @@ static struct fb_ops atyfb_ops = { .fb_fillrect = atyfb_fillrect, .fb_copyarea = atyfb_copyarea, .fb_imageblit = atyfb_imageblit, - .fb_cursor = soft_cursor, #ifdef __sparc__ .fb_mmap = atyfb_mmap, #endif @@ -2157,11 +2156,38 @@ static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) static struct fb_info *fb_list = NULL; +#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) +static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par, + struct fb_var_screeninfo *var) +{ + int ret = -EINVAL; + + if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { + *var = default_var; + var->xres = var->xres_virtual = par->lcd_hdisp; + var->right_margin = par->lcd_right_margin; + var->left_margin = par->lcd_hblank_len - + (par->lcd_right_margin + par->lcd_hsync_dly + + par->lcd_hsync_len); + var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly; + var->yres = var->yres_virtual = par->lcd_vdisp; + var->lower_margin = par->lcd_lower_margin; + var->upper_margin = par->lcd_vblank_len - + (par->lcd_lower_margin + par->lcd_vsync_len); + var->vsync_len = par->lcd_vsync_len; + var->pixclock = par->lcd_pixclock; + ret = 0; + } + + return ret; +} +#endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */ + static int __init aty_init(struct fb_info *info, const char *name) { struct atyfb_par *par = (struct atyfb_par *) info->par; const char *ramname = NULL, *xtal; - int gtb_memsize; + int gtb_memsize, has_var = 0; struct fb_var_screeninfo var; u8 pll_ref_div; u32 i; @@ -2469,8 +2495,8 @@ static int __init aty_init(struct fb_info *info, const char *name) * applies to all Mac video cards */ if (mode) { - if (!mac_find_mode(&var, info, mode, 8)) - var = default_var; + if (mac_find_mode(&var, info, mode, 8)) + has_var = 1; } else { if (default_vmode == VMODE_CHOOSE) { if (M64_HAS(G3_PB_1024x768)) @@ -2492,20 +2518,23 @@ static int __init aty_init(struct fb_info *info, const char *name) default_vmode = VMODE_640_480_60; if (default_cmode < CMODE_8 || default_cmode > CMODE_32) default_cmode = CMODE_8; - if (mac_vmode_to_var(default_vmode, default_cmode, &var)) - var = default_var; + if (!mac_vmode_to_var(default_vmode, default_cmode, + &var)) + has_var = 1; } - } else + } + #endif /* !CONFIG_PPC */ - if ( -#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) - /* On Sparc, unless the user gave a specific mode - * specification, use the PROM probed values in - * default_var. - */ - !mode || + +#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) + if (!atyfb_get_timings_from_lcd(par, &var)) + has_var = 1; #endif - !fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8)) + + if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8)) + has_var = 1; + + if (!has_var) var = default_var; if (noaccel) diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 046b4786026..4f01ccc02aa 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -69,7 +69,6 @@ #include <linux/pci.h> #include <linux/vmalloc.h> #include <linux/device.h> -#include <linux/i2c.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -113,6 +112,7 @@ static struct pci_device_id radeonfb_pci_table[] = { /* Radeon VE/7000 */ CHIP_DEF(PCI_CHIP_RV100_QY, RV100, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV100_QZ, RV100, CHIP_HAS_CRTC2), + CHIP_DEF(PCI_CHIP_RN50, RV100, CHIP_HAS_CRTC2), /* Radeon IGP320M (U1) */ CHIP_DEF(PCI_CHIP_RS100_4336, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), /* Radeon IGP320 (A3) */ @@ -475,7 +475,7 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo) */ /* Flush PCI buffers ? */ - tmp = INREG(DEVICE_ID); + tmp = INREG16(DEVICE_ID); local_irq_disable(); @@ -1874,7 +1874,6 @@ static struct fb_ops radeonfb_ops = { .fb_fillrect = radeonfb_fillrect, .fb_copyarea = radeonfb_copyarea, .fb_imageblit = radeonfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 59a1b6f8506..097d668c4fe 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -62,9 +62,9 @@ static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) OUTPLL(pllSCLK_CNTL, tmp); return; } - /* RV350 (M10) */ + /* RV350 (M10/M11) */ if (rinfo->family == CHIP_FAMILY_RV350) { - /* for RV350/M10, no delays are required. */ + /* for RV350/M10/M11, no delays are required. */ tmp = INPLL(pllSCLK_CNTL2); tmp |= (SCLK_CNTL2__R300_FORCE_TCL | SCLK_CNTL2__R300_FORCE_GA | @@ -248,7 +248,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) return; } - /* M10 */ + /* M10/M11 */ if (rinfo->family == CHIP_FAMILY_RV350) { tmp = INPLL(pllSCLK_CNTL2); tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL | @@ -1155,7 +1155,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo) OUTREG( CRTC_GEN_CNTL, (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) ); OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) ); - /* This is the code for the Aluminium PowerBooks M10 */ + /* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */ if (rinfo->family == CHIP_FAMILY_RV350) { u32 sdram_mode_reg = rinfo->save_regs[35]; static u32 default_mrtable[] = @@ -2741,9 +2741,11 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) rinfo->pm_mode |= radeon_pm_d2; /* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip - * in some desktop G4s), and Via (M9+ chip on iBook G4) + * in some desktop G4s), Via (M9+ chip on iBook G4) and + * Snowy (M11 chip on iBook G4 manufactured after July 2005) */ - if (!strcmp(rinfo->of_node->name, "ATY,JasperParent")) { + if (!strcmp(rinfo->of_node->name, "ATY,JasperParent") || + !strcmp(rinfo->of_node->name, "ATY,SnowyParent")) { rinfo->reinit_func = radeon_reinitialize_M10; rinfo->pm_mode |= radeon_pm_off; } diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 659bc9f6224..217e00ab4a2 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -10,9 +10,10 @@ #include <linux/fb.h> +#ifdef CONFIG_FB_RADEON_I2C #include <linux/i2c.h> -#include <linux/i2c-id.h> #include <linux/i2c-algo-bit.h> +#endif #include <asm/io.h> @@ -395,6 +396,8 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms) #define INREG8(addr) readb((rinfo->mmio_base)+addr) #define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) +#define INREG16(addr) readw((rinfo->mmio_base)+addr) +#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr) #define INREG(addr) readl((rinfo->mmio_base)+addr) #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) diff --git a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c index 0bea0d8d782..a085cbf74ec 100644 --- a/drivers/video/aty/xlinit.c +++ b/drivers/video/aty/xlinit.c @@ -253,9 +253,11 @@ int atyfb_xl_init(struct fb_info *info) aty_st_le32(0xFC, 0x00000000, par); #if defined (CONFIG_FB_ATY_GENERIC_LCD) - int i; - for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); i++) { - aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par); + { + int i; + + for (i = 0; i < ARRAY_SIZE(lcd_tbl); i++) + aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par); } #endif diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index b6fe30c3ad6..a5129806172 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -2,6 +2,11 @@ * BRIEF MODULE DESCRIPTION * Au1100 LCD Driver. * + * Rewritten for 2.6 by Embedded Alley Solutions + * <source@embeddedalley.com>, based on submissions by + * Karl Lessard <klessard@sunrisetelecom.com> + * <c.pellegrin@exadron.com> + * * Copyright 2002 MontaVista Software * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com @@ -33,298 +38,253 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/mm.h> -#include <linux/tty.h> -#include <linux/slab.h> -#include <linux/delay.h> #include <linux/fb.h> #include <linux/init.h> -#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/ctype.h> +#include <linux/dma-mapping.h> -#include <asm/au1000.h> -#include <asm/pb1100.h> -#include "au1100fb.h" +#include <asm/mach-au1x00/au1000.h> -#include <video/fbcon.h> -#include <video/fbcon-mfb.h> -#include <video/fbcon-cfb2.h> -#include <video/fbcon-cfb4.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> +#define DEBUG 0 + +#include "au1100fb.h" /* * Sanity check. If this is a new Au1100 based board, search for * the PB1100 ifdefs to make sure you modify the code accordingly. */ -#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_HYDROGEN3) +#if defined(CONFIG_MIPS_PB1100) + #include <asm/mach-pb1x00/pb1100.h> +#elif defined(CONFIG_MIPS_DB1100) + #include <asm/mach-db1x00/db1x00.h> #else -error Unknown Au1100 board + #error "Unknown Au1100 board, Au1100 FB driver not supported" #endif -#define CMAPSIZE 16 - -static int my_lcd_index; /* default is zero */ -struct known_lcd_panels *p_lcd; -AU1100_LCD *p_lcd_reg = (AU1100_LCD *)AU1100_LCD_ADDR; - -struct au1100fb_info { - struct fb_info_gen gen; - unsigned long fb_virt_start; - unsigned long fb_size; - unsigned long fb_phys; - int mmaped; - int nohwcursor; +#define DRIVER_NAME "au1100fb" +#define DRIVER_DESC "LCD controller driver for AU1100 processors" - struct { unsigned red, green, blue, pad; } palette[256]; +#define to_au1100fb_device(_info) \ + (_info ? container_of(_info, struct au1100fb_device, info) : NULL); -#if defined(FBCON_HAS_CFB16) - u16 fbcon_cmap16[16]; -#endif +/* Bitfields format supported by the controller. Note that the order of formats + * SHOULD be the same as in the LCD_CONTROL_SBPPF field, so we can retrieve the + * right pixel format by doing rgb_bitfields[LCD_CONTROL_SBPPF_XXX >> LCD_CONTROL_SBPPF] + */ +struct fb_bitfield rgb_bitfields[][4] = +{ + /* Red, Green, Blue, Transp */ + { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, + { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, + { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, + { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, + { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, + + /* The last is used to describe 12bpp format */ + { { 8, 4, 0 }, { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } }, }; - -struct au1100fb_par { - struct fb_var_screeninfo var; - - int line_length; // in bytes - int cmap_len; // color-map length +static struct fb_fix_screeninfo au1100fb_fix __initdata = { + .id = "AU1100 FB", + .xpanstep = 1, + .ypanstep = 1, + .type = FB_TYPE_PACKED_PIXELS, + .accel = FB_ACCEL_NONE, }; - -static struct au1100fb_info fb_info; -static struct au1100fb_par current_par; -static struct display disp; - -int au1100fb_init(void); -void au1100fb_setup(char *options, int *ints); -static int au1100fb_mmap(struct fb_info *fb, struct file *file, - struct vm_area_struct *vma); -static int au1100_blank(int blank_mode, struct fb_info_gen *info); -static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con, struct fb_info *info); - -void au1100_nocursor(struct display *p, int mode, int xx, int yy){}; - -static struct fb_ops au1100fb_ops = { - .owner = THIS_MODULE, - .fb_get_fix = fbgen_get_fix, - .fb_get_var = fbgen_get_var, - .fb_set_var = fbgen_set_var, - .fb_get_cmap = fbgen_get_cmap, - .fb_set_cmap = fbgen_set_cmap, - .fb_pan_display = fbgen_pan_display, - .fb_ioctl = au1100fb_ioctl, - .fb_mmap = au1100fb_mmap, +static struct fb_var_screeninfo au1100fb_var __initdata = { + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .vmode = FB_VMODE_NONINTERLACED, }; -static void au1100_detect(void) -{ - /* - * This function should detect the current video mode settings - * and store it as the default video mode - */ +static struct au1100fb_drv_info drv_info; - /* - * Yeh, well, we're not going to change any settings so we're - * always stuck with the default ... +/* + * Set hardware with var settings. This will enable the controller with a specific + * mode, normally validated with the fb_check_var method */ - -} - -static int au1100_encode_fix(struct fb_fix_screeninfo *fix, - const void *_par, struct fb_info_gen *_info) +int au1100fb_setmode(struct au1100fb_device *fbdev) { - struct au1100fb_info *info = (struct au1100fb_info *) _info; - struct au1100fb_par *par = (struct au1100fb_par *) _par; - struct fb_var_screeninfo *var = &par->var; - - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - - fix->smem_start = info->fb_phys; - fix->smem_len = info->fb_size; - fix->type = FB_TYPE_PACKED_PIXELS; - fix->type_aux = 0; - fix->visual = (var->bits_per_pixel == 8) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - fix->ywrapstep = 0; - fix->xpanstep = 1; - fix->ypanstep = 1; - fix->line_length = current_par.line_length; - return 0; -} + struct fb_info *info = &fbdev->info; + u32 words; + int index; -static void set_color_bitfields(struct fb_var_screeninfo *var) -{ - switch (var->bits_per_pixel) { - case 8: - var->red.offset = 0; - var->red.length = 8; - var->green.offset = 0; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - break; - case 16: /* RGB 565 */ - var->red.offset = 11; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 0; - var->transp.length = 0; - break; + if (!fbdev) + return -EINVAL; + + /* Update var-dependent FB info */ + if (panel_is_active(fbdev->panel) || panel_is_color(fbdev->panel)) { + if (info->var.bits_per_pixel <= 8) { + /* palettized */ + info->var.red.offset = 0; + info->var.red.length = info->var.bits_per_pixel; + info->var.red.msb_right = 0; + + info->var.green.offset = 0; + info->var.green.length = info->var.bits_per_pixel; + info->var.green.msb_right = 0; + + info->var.blue.offset = 0; + info->var.blue.length = info->var.bits_per_pixel; + info->var.blue.msb_right = 0; + + info->var.transp.offset = 0; + info->var.transp.length = 0; + info->var.transp.msb_right = 0; + + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + info->fix.line_length = info->var.xres_virtual / + (8/info->var.bits_per_pixel); + } else { + /* non-palettized */ + index = (fbdev->panel->control_base & LCD_CONTROL_SBPPF_MASK) >> LCD_CONTROL_SBPPF_BIT; + info->var.red = rgb_bitfields[index][0]; + info->var.green = rgb_bitfields[index][1]; + info->var.blue = rgb_bitfields[index][2]; + info->var.transp = rgb_bitfields[index][3]; + + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */ + } + } else { + /* mono */ + info->fix.visual = FB_VISUAL_MONO10; + info->fix.line_length = info->var.xres_virtual / 8; } - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - var->transp.msb_right = 0; -} + info->screen_size = info->fix.line_length * info->var.yres_virtual; -static int au1100_decode_var(const struct fb_var_screeninfo *var, - void *_par, struct fb_info_gen *_info) -{ + /* Determine BPP mode and format */ + fbdev->regs->lcd_control = fbdev->panel->control_base | + ((info->var.rotate/90) << LCD_CONTROL_SM_BIT); - struct au1100fb_par *par = (struct au1100fb_par *)_par; + fbdev->regs->lcd_intenable = 0; + fbdev->regs->lcd_intstatus = 0; - /* - * Don't allow setting any of these yet: xres and yres don't - * make sense for LCD panels. - */ - if (var->xres != p_lcd->xres || - var->yres != p_lcd->yres || - var->xres != p_lcd->xres || - var->yres != p_lcd->yres) { - return -EINVAL; - } - if(var->bits_per_pixel != p_lcd->bpp) { - return -EINVAL; - } + fbdev->regs->lcd_horztiming = fbdev->panel->horztiming; - memset(par, 0, sizeof(struct au1100fb_par)); - par->var = *var; - - /* FIXME */ - switch (var->bits_per_pixel) { - case 8: - par->var.bits_per_pixel = 8; - break; - case 16: - par->var.bits_per_pixel = 16; - break; - default: - printk("color depth %d bpp not supported\n", - var->bits_per_pixel); - return -EINVAL; + fbdev->regs->lcd_verttiming = fbdev->panel->verttiming; + + fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base; + fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys); + + if (panel_is_dual(fbdev->panel)) { + /* Second panel display seconf half of screen if possible, + * otherwise display the same as the first panel */ + if (info->var.yres_virtual >= (info->var.yres << 1)) { + fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys + + (info->fix.line_length * + (info->var.yres_virtual >> 1))); + } else { + fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys); + } } - set_color_bitfields(&par->var); - par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16; - return 0; -} -static int au1100_encode_var(struct fb_var_screeninfo *var, - const void *par, struct fb_info_gen *_info) -{ + words = info->fix.line_length / sizeof(u32); + if (!info->var.rotate || (info->var.rotate == 180)) { + words *= info->var.yres_virtual; + if (info->var.rotate /* 180 */) { + words -= (words % 8); /* should be divisable by 8 */ + } + } + fbdev->regs->lcd_words = LCD_WRD_WRDS_N(words); - *var = ((struct au1100fb_par *)par)->var; - return 0; -} + fbdev->regs->lcd_pwmdiv = 0; + fbdev->regs->lcd_pwmhi = 0; -static void -au1100_get_par(void *_par, struct fb_info_gen *_info) -{ - *(struct au1100fb_par *)_par = current_par; -} + /* Resume controller */ + fbdev->regs->lcd_control |= LCD_CONTROL_GO; -static void au1100_set_par(const void *par, struct fb_info_gen *info) -{ - /* nothing to do: we don't change any settings */ + return 0; } -static int au1100_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info) +/* fb_setcolreg + * Set color in LCD palette. + */ +int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi) { + struct au1100fb_device *fbdev = to_au1100fb_device(fbi); + u32 *palette = fbdev->regs->lcd_pallettebase; + u32 value; - struct au1100fb_info* i = (struct au1100fb_info*)info; - - if (regno > 255) - return 1; + if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1)) + return -EINVAL; - *red = i->palette[regno].red; - *green = i->palette[regno].green; - *blue = i->palette[regno].blue; - *transp = 0; + if (fbi->var.grayscale) { + /* Convert color to grayscale */ + red = green = blue = + (19595 * red + 38470 * green + 7471 * blue) >> 16; + } - return 0; -} + if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { + /* Place color in the pseudopalette */ + if (regno > 16) + return -EINVAL; -static int au1100_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) -{ - struct au1100fb_info* i = (struct au1100fb_info *)info; - u32 rgbcol; - - if (regno > 255) - return 1; - - i->palette[regno].red = red; - i->palette[regno].green = green; - i->palette[regno].blue = blue; - - switch(p_lcd->bpp) { -#ifdef FBCON_HAS_CFB8 - case 8: - red >>= 10; - green >>= 10; - blue >>= 10; - p_lcd_reg->lcd_pallettebase[regno] = (blue&0x1f) | - ((green&0x3f)<<5) | ((red&0x1f)<<11); - break; -#endif -#ifdef FBCON_HAS_CFB16 - case 16: - i->fbcon_cmap16[regno] = - ((red & 0xf800) >> 0) | - ((green & 0xfc00) >> 5) | - ((blue & 0xf800) >> 11); - break; -#endif - default: - break; + palette = (u32*)fbi->pseudo_palette; + + red >>= (16 - fbi->var.red.length); + green >>= (16 - fbi->var.green.length); + blue >>= (16 - fbi->var.blue.length); + + value = (red << fbi->var.red.offset) | + (green << fbi->var.green.offset)| + (blue << fbi->var.blue.offset); + value &= 0xFFFF; + + } else if (panel_is_active(fbdev->panel)) { + /* COLOR TFT PALLETTIZED (use RGB 565) */ + value = (red & 0xF800)|((green >> 5) & 0x07E0)|((blue >> 11) & 0x001F); + value &= 0xFFFF; + + } else if (panel_is_color(fbdev->panel)) { + /* COLOR STN MODE */ + value = (((panel_swap_rgb(fbdev->panel) ? blue : red) >> 12) & 0x000F) | + ((green >> 8) & 0x00F0) | + (((panel_swap_rgb(fbdev->panel) ? red : blue) >> 4) & 0x0F00); + value &= 0xFFF; + } else { + /* MONOCHROME MODE */ + value = (green >> 12) & 0x000F; + value &= 0xF; } + palette[regno] = value; + return 0; } - -static int au1100_blank(int blank_mode, struct fb_info_gen *_info) +/* fb_blank + * Blank the screen. Depending on the mode, the screen will be + * activated with the backlight color, or desactivated + */ +int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) { + struct au1100fb_device *fbdev = to_au1100fb_device(fbi); + + print_dbg("fb_blank %d %p", blank_mode, fbi); switch (blank_mode) { + case VESA_NO_BLANKING: - /* turn on panel */ - //printk("turn on panel\n"); + /* Turn on panel */ + fbdev->regs->lcd_control |= LCD_CONTROL_GO; #ifdef CONFIG_MIPS_PB1100 - p_lcd_reg->lcd_control |= LCD_CONTROL_GO; - au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight, + if (drv_info.panel_idx == 1) { + au_writew(au_readw(PB1100_G_CONTROL) + | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), PB1100_G_CONTROL); -#endif -#ifdef CONFIG_MIPS_HYDROGEN3 - /* Turn controller & power supply on, GPIO213 */ - au_writel(0x20002000, 0xB1700008); - au_writel(0x00040000, 0xB1900108); - au_writel(0x01000100, 0xB1700008); + } #endif au_sync(); break; @@ -332,12 +292,14 @@ static int au1100_blank(int blank_mode, struct fb_info_gen *_info) case VESA_VSYNC_SUSPEND: case VESA_HSYNC_SUSPEND: case VESA_POWERDOWN: - /* turn off panel */ - //printk("turn off panel\n"); + /* Turn off panel */ + fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; #ifdef CONFIG_MIPS_PB1100 - au_writew(au_readw(PB1100_G_CONTROL) & ~p_lcd->mode_backlight, + if (drv_info.panel_idx == 1) { + au_writew(au_readw(PB1100_G_CONTROL) + & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), PB1100_G_CONTROL); - p_lcd_reg->lcd_control &= ~LCD_CONTROL_GO; + } #endif au_sync(); break; @@ -348,49 +310,87 @@ static int au1100_blank(int blank_mode, struct fb_info_gen *_info) return 0; } -static void au1100_set_disp(const void *unused, struct display *disp, - struct fb_info_gen *info) +/* fb_pan_display + * Pan display in x and/or y as specified + */ +int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi) { - disp->screen_base = (char *)fb_info.fb_virt_start; - - switch (disp->var.bits_per_pixel) { -#ifdef FBCON_HAS_CFB8 - case 8: - disp->dispsw = &fbcon_cfb8; - if (fb_info.nohwcursor) - fbcon_cfb8.cursor = au1100_nocursor; - break; -#endif -#ifdef FBCON_HAS_CFB16 - case 16: - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = fb_info.fbcon_cmap16; - if (fb_info.nohwcursor) - fbcon_cfb16.cursor = au1100_nocursor; - break; -#endif - default: - disp->dispsw = &fbcon_dummy; - disp->dispsw_data = NULL; - break; + struct au1100fb_device *fbdev = to_au1100fb_device(fbi); + int dy; + + print_dbg("fb_pan_display %p %p", var, fbi); + + if (!var || !fbdev) { + return -EINVAL; + } + + if (var->xoffset - fbi->var.xoffset) { + /* No support for X panning for now! */ + return -EINVAL; + } + + print_dbg("fb_pan_display 2 %p %p", var, fbi); + dy = var->yoffset - fbi->var.yoffset; + if (dy) { + + u32 dmaaddr; + + print_dbg("Panning screen of %d lines", dy); + + dmaaddr = fbdev->regs->lcd_dmaaddr0; + dmaaddr += (fbi->fix.line_length * dy); + + /* TODO: Wait for current frame to finished */ + fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr); + + if (panel_is_dual(fbdev->panel)) { + dmaaddr = fbdev->regs->lcd_dmaaddr1; + dmaaddr += (fbi->fix.line_length * dy); + fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr); + } + } + print_dbg("fb_pan_display 3 %p %p", var, fbi); + + return 0; +} + +/* fb_rotate + * Rotate the display of this angle. This doesn't seems to be used by the core, + * but as our hardware supports it, so why not implementing it... + */ +void au1100fb_fb_rotate(struct fb_info *fbi, int angle) +{ + struct au1100fb_device *fbdev = to_au1100fb_device(fbi); + + print_dbg("fb_rotate %p %d", fbi, angle); + + if (fbdev && (angle > 0) && !(angle % 90)) { + + fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; + + fbdev->regs->lcd_control &= ~(LCD_CONTROL_SM_MASK); + fbdev->regs->lcd_control |= ((angle/90) << LCD_CONTROL_SM_BIT); + + fbdev->regs->lcd_control |= LCD_CONTROL_GO; } } -static int -au1100fb_mmap(struct fb_info *_fb, - struct file *file, - struct vm_area_struct *vma) +/* fb_mmap + * Map video memory in user space. We don't use the generic fb_mmap method mainly + * to allow the use of the TLB streaming flag (CCA=6) + */ +int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma) { + struct au1100fb_device *fbdev = to_au1100fb_device(fbi); unsigned int len; unsigned long start=0, off; - struct au1100fb_info *fb = (struct au1100fb_info *)_fb; if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { return -EINVAL; } - start = fb_info.fb_phys & PAGE_MASK; - len = PAGE_ALIGN((start & ~PAGE_MASK) + fb_info.fb_size); + start = fbdev->fb_phys & PAGE_MASK; + len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); off = vma->vm_pgoff << PAGE_SHIFT; @@ -401,276 +401,309 @@ au1100fb_mmap(struct fb_info *_fb, off += start; vma->vm_pgoff = off >> PAGE_SHIFT; - pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; - //pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 - /* This is an IO map - tell maydump to skip this VMA */ vma->vm_flags |= VM_IO; - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + if (io_remap_page_range(vma, vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot)) { return -EAGAIN; } - fb->mmaped = 1; return 0; } -int au1100_pan_display(const struct fb_var_screeninfo *var, - struct fb_info_gen *info) +static struct fb_ops au1100fb_ops = { - return 0; -} + .owner = THIS_MODULE, + .fb_setcolreg = au1100fb_fb_setcolreg, + .fb_blank = au1100fb_fb_blank, + .fb_pan_display = au1100fb_fb_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_rotate = au1100fb_fb_rotate, + .fb_mmap = au1100fb_fb_mmap, +}; -static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con, struct fb_info *info) -{ - /* nothing to do yet */ - return -EINVAL; -} -static struct fbgen_hwswitch au1100_switch = { - au1100_detect, - au1100_encode_fix, - au1100_decode_var, - au1100_encode_var, - au1100_get_par, - au1100_set_par, - au1100_getcolreg, - au1100_setcolreg, - au1100_pan_display, - au1100_blank, - au1100_set_disp -}; +/*-------------------------------------------------------------------------*/ +/* AU1100 LCD controller device driver */ -int au1100_setmode(void) +int au1100fb_drv_probe(struct device *dev) { - int words; - - /* FIXME Need to accomodate for swivel mode and 12bpp, <8bpp*/ - switch (p_lcd->mode_control & LCD_CONTROL_SM) - { - case LCD_CONTROL_SM_0: - case LCD_CONTROL_SM_180: - words = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 32; - break; - case LCD_CONTROL_SM_90: - case LCD_CONTROL_SM_270: - /* is this correct? */ - words = (p_lcd->xres * p_lcd->bpp) / 8; - break; - default: - printk("mode_control reg not initialized\n"); + struct au1100fb_device *fbdev = NULL; + struct resource *regs_res; + unsigned long page; + u32 sys_clksrc; + + if (!dev) return -EINVAL; + + /* Allocate new device private */ + if (!(fbdev = kmalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) { + print_err("fail to allocate device private record"); + return -ENOMEM; } + memset((void*)fbdev, 0, sizeof(struct au1100fb_device)); - /* - * Setup LCD controller - */ + fbdev->panel = &known_lcd_panels[drv_info.panel_idx]; - p_lcd_reg->lcd_control = p_lcd->mode_control; - p_lcd_reg->lcd_intstatus = 0; - p_lcd_reg->lcd_intenable = 0; - p_lcd_reg->lcd_horztiming = p_lcd->mode_horztiming; - p_lcd_reg->lcd_verttiming = p_lcd->mode_verttiming; - p_lcd_reg->lcd_clkcontrol = p_lcd->mode_clkcontrol; - p_lcd_reg->lcd_words = words - 1; - p_lcd_reg->lcd_dmaaddr0 = fb_info.fb_phys; + dev_set_drvdata(dev, (void*)fbdev); - /* turn on panel */ -#ifdef CONFIG_MIPS_PB1100 - au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight, - PB1100_G_CONTROL); -#endif -#ifdef CONFIG_MIPS_HYDROGEN3 - /* Turn controller & power supply on, GPIO213 */ - au_writel(0x20002000, 0xB1700008); - au_writel(0x00040000, 0xB1900108); - au_writel(0x01000100, 0xB1700008); -#endif + /* Allocate region for our registers and map them */ + if (!(regs_res = platform_get_resource(to_platform_device(dev), + IORESOURCE_MEM, 0))) { + print_err("fail to retrieve registers resource"); + return -EFAULT; + } - p_lcd_reg->lcd_control |= LCD_CONTROL_GO; + au1100fb_fix.mmio_start = regs_res->start; + au1100fb_fix.mmio_len = regs_res->end - regs_res->start + 1; - return 0; -} + if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len, + DRIVER_NAME)) { + print_err("fail to lock memory region at 0x%08x", + au1100fb_fix.mmio_start); + return -EBUSY; + } + fbdev->regs = (struct au1100fb_regs*)KSEG1ADDR(au1100fb_fix.mmio_start); -int __init au1100fb_init(void) -{ - uint32 sys_clksrc; - unsigned long page; + print_dbg("Register memory map at %p", fbdev->regs); + print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); - /* - * Get the panel information/display mode and update the registry - */ - p_lcd = &panels[my_lcd_index]; - - switch (p_lcd->mode_control & LCD_CONTROL_SM) - { - case LCD_CONTROL_SM_0: - case LCD_CONTROL_SM_180: - p_lcd->xres = - (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1; - p_lcd->yres = - (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1; - break; - case LCD_CONTROL_SM_90: - case LCD_CONTROL_SM_270: - p_lcd->yres = - (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1; - p_lcd->xres = - (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1; - break; - } - /* - * Panel dimensions x bpp must be divisible by 32 - */ - if (((p_lcd->yres * p_lcd->bpp) % 32) != 0) - printk("VERT %% 32\n"); - if (((p_lcd->xres * p_lcd->bpp) % 32) != 0) - printk("HORZ %% 32\n"); - /* - * Allocate LCD framebuffer from system memory - */ - fb_info.fb_size = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 8; - - current_par.var.xres = p_lcd->xres; - current_par.var.xres_virtual = p_lcd->xres; - current_par.var.yres = p_lcd->yres; - current_par.var.yres_virtual = p_lcd->yres; - current_par.var.bits_per_pixel = p_lcd->bpp; - - /* FIX!!! only works for 8/16 bpp */ - current_par.line_length = p_lcd->xres * p_lcd->bpp / 8; /* in bytes */ - fb_info.fb_virt_start = (unsigned long ) - __get_free_pages(GFP_ATOMIC | GFP_DMA, - get_order(fb_info.fb_size + 0x1000)); - if (!fb_info.fb_virt_start) { - printk("Unable to allocate fb memory\n"); + /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ + fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * + (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; + + fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len), + &fbdev->fb_phys, GFP_KERNEL); + if (!fbdev->fb_mem) { + print_err("fail to allocate frambuffer (size: %dK))", + fbdev->fb_len / 1024); return -ENOMEM; } - fb_info.fb_phys = virt_to_bus((void *)fb_info.fb_virt_start); + + au1100fb_fix.smem_start = fbdev->fb_phys; + au1100fb_fix.smem_len = fbdev->fb_len; /* * Set page reserved so that mmap will work. This is necessary * since we'll be remapping normal memory. */ - for (page = fb_info.fb_virt_start; - page < PAGE_ALIGN(fb_info.fb_virt_start + fb_info.fb_size); + for (page = (unsigned long)fbdev->fb_mem; + page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len); page += PAGE_SIZE) { +#if CONFIG_DMA_NONCOHERENT + SetPageReserved(virt_to_page(CAC_ADDR(page))); +#else SetPageReserved(virt_to_page(page)); +#endif } - memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size); - - /* set freqctrl now to allow more time to stabilize */ - /* zero-out out LCD bits */ - sys_clksrc = au_readl(SYS_CLKSRC) & ~0x000003e0; - sys_clksrc |= p_lcd->mode_toyclksrc; - au_writel(sys_clksrc, SYS_CLKSRC); - - /* FIXME add check to make sure auxpll is what is expected! */ - au1100_setmode(); - - fb_info.gen.parsize = sizeof(struct au1100fb_par); - fb_info.gen.fbhw = &au1100_switch; - - strcpy(fb_info.gen.info.modename, "Au1100 LCD"); - fb_info.gen.info.changevar = NULL; - fb_info.gen.info.node = -1; - - fb_info.gen.info.fbops = &au1100fb_ops; - fb_info.gen.info.disp = &disp; - fb_info.gen.info.switch_con = &fbgen_switch; - fb_info.gen.info.updatevar = &fbgen_update_var; - fb_info.gen.info.blank = &fbgen_blank; - fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT; - - /* This should give a reasonable default video mode */ - fbgen_get_var(&disp.var, -1, &fb_info.gen.info); - fbgen_do_set_var(&disp.var, 1, &fb_info.gen); - fbgen_set_disp(-1, &fb_info.gen); - fbgen_install_cmap(0, &fb_info.gen); - if (register_framebuffer(&fb_info.gen.info) < 0) - return -EINVAL; - printk(KERN_INFO "fb%d: %s frame buffer device\n", - GET_FB_IDX(fb_info.gen.info.node), - fb_info.gen.info.modename); + print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); + print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); + + /* Setup LCD clock to AUX (48 MHz) */ + sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL); + au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC); + + /* load the panel info into the var struct */ + au1100fb_var.bits_per_pixel = fbdev->panel->bpp; + au1100fb_var.xres = fbdev->panel->xres; + au1100fb_var.xres_virtual = au1100fb_var.xres; + au1100fb_var.yres = fbdev->panel->yres; + au1100fb_var.yres_virtual = au1100fb_var.yres; + + fbdev->info.screen_base = fbdev->fb_mem; + fbdev->info.fbops = &au1100fb_ops; + fbdev->info.fix = au1100fb_fix; + + if (!(fbdev->info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL))) { + return -ENOMEM; + } + memset(fbdev->info.pseudo_palette, 0, sizeof(u32) * 16); + + if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { + print_err("Fail to allocate colormap (%d entries)", + AU1100_LCD_NBR_PALETTE_ENTRIES); + kfree(fbdev->info.pseudo_palette); + return -EFAULT; + } + + fbdev->info.var = au1100fb_var; + + /* Set h/w registers */ + au1100fb_setmode(fbdev); + + /* Register new framebuffer */ + if (register_framebuffer(&fbdev->info) < 0) { + print_err("cannot register new framebuffer"); + goto failed; + } + + return 0; + +failed: + if (fbdev->regs) { + release_mem_region(fbdev->regs_phys, fbdev->regs_len); + } + if (fbdev->fb_mem) { + dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys); + } + if (fbdev->info.cmap.len != 0) { + fb_dealloc_cmap(&fbdev->info.cmap); + } + kfree(fbdev); + dev_set_drvdata(dev, NULL); return 0; } +int au1100fb_drv_remove(struct device *dev) +{ + struct au1100fb_device *fbdev = NULL; + + if (!dev) + return -ENODEV; + + fbdev = (struct au1100fb_device*) dev_get_drvdata(dev); + +#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) + au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); +#endif + fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; -void au1100fb_cleanup(struct fb_info *info) + /* Clean up all probe data */ + unregister_framebuffer(&fbdev->info); + + release_mem_region(fbdev->regs_phys, fbdev->regs_len); + + dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); + + fb_dealloc_cmap(&fbdev->info.cmap); + kfree(fbdev->info.pseudo_palette); + kfree((void*)fbdev); + + return 0; +} + +int au1100fb_drv_suspend(struct device *dev, u32 state, u32 level) +{ + /* TODO */ + return 0; +} + +int au1100fb_drv_resume(struct device *dev, u32 level) { - unregister_framebuffer(info); + /* TODO */ + return 0; } +static struct device_driver au1100fb_driver = { + .name = "au1100-lcd", + .bus = &platform_bus_type, -void au1100fb_setup(char *options, int *ints) + .probe = au1100fb_drv_probe, + .remove = au1100fb_drv_remove, + .suspend = au1100fb_drv_suspend, + .resume = au1100fb_drv_resume, +}; + +/*-------------------------------------------------------------------------*/ + +/* Kernel driver */ + +int au1100fb_setup(char *options) { char* this_opt; - int i; - int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels); + int num_panels = ARRAY_SIZE(known_lcd_panels); + char* mode = NULL; + int panel_idx = 0; + if (num_panels <= 0) { + print_err("No LCD panels supported by driver!"); + return -EFAULT; + } - if (!options || !*options) - return; - - for(this_opt=strtok(options, ","); this_opt; - this_opt=strtok(NULL, ",")) { + if (options) { + while ((this_opt = strsep(&options,",")) != NULL) { + /* Panel option */ if (!strncmp(this_opt, "panel:", 6)) { -#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) - /* Read Pb1100 Switch S10 ? */ - if (!strncmp(this_opt+6, "s10", 3)) - { - int panel; - panel = *(volatile int *)0xAE000008; /* BCSR SWITCHES */ - panel >>= 8; - panel &= 0x0F; - if (panel >= num_panels) panel = 0; - my_lcd_index = panel; - } - else -#endif - /* Get the panel name, everything else if fixed */ - for (i=0; i<num_panels; i++) { - if (!strncmp(this_opt+6, panels[i].panel_name, + int i; + this_opt += 6; + for (i = 0; i < num_panels; i++) { + if (!strncmp(this_opt, + known_lcd_panels[i].name, strlen(this_opt))) { - my_lcd_index = i; + panel_idx = i; break; } } + if (i >= num_panels) { + print_warn("Panel %s not supported!", this_opt); + } + } + /* Mode option (only option that start with digit) */ + else if (isdigit(this_opt[0])) { + mode = kmalloc(strlen(this_opt) + 1, GFP_KERNEL); + strncpy(mode, this_opt, strlen(this_opt) + 1); + } + /* Unsupported option */ + else { + print_warn("Unsupported option \"%s\"", this_opt); } - else if (!strncmp(this_opt, "nohwcursor", 10)) { - printk("nohwcursor\n"); - fb_info.nohwcursor = 1; } } - printk("au1100fb: Panel %d %s\n", my_lcd_index, - panels[my_lcd_index].panel_name); -} + drv_info.panel_idx = panel_idx; + drv_info.opt_mode = mode; + print_info("Panel=%s Mode=%s", + known_lcd_panels[drv_info.panel_idx].name, + drv_info.opt_mode ? drv_info.opt_mode : "default"); + return 0; +} -#ifdef MODULE -MODULE_LICENSE("GPL"); -int init_module(void) +int __init au1100fb_init(void) { - return au1100fb_init(); + char* options; + int ret; + + print_info("" DRIVER_DESC ""); + + memset(&drv_info, 0, sizeof(drv_info)); + + if (fb_get_options(DRIVER_NAME, &options)) + return -ENODEV; + + /* Setup driver with options */ + ret = au1100fb_setup(options); + if (ret < 0) { + print_err("Fail to setup driver"); + return ret; + } + + return driver_register(&au1100fb_driver); } -void cleanup_module(void) +void __exit au1100fb_cleanup(void) { - au1100fb_cleanup(void); + driver_unregister(&au1100fb_driver); + + if (drv_info.opt_mode) + kfree(drv_info.opt_mode); } -MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>"); -MODULE_DESCRIPTION("Au1100 LCD framebuffer device driver"); -#endif /* MODULE */ +module_init(au1100fb_init); +module_exit(au1100fb_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h index 657c560ab73..2855534dc23 100644 --- a/drivers/video/au1100fb.h +++ b/drivers/video/au1100fb.h @@ -30,352 +30,352 @@ #ifndef _AU1100LCD_H #define _AU1100LCD_H +#include <asm/mach-au1x00/au1000.h> + +#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) +#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) +#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) + +#if DEBUG +#define print_dbg(f, arg...) printk(__FILE__ ": " f "\n", ## arg) +#else +#define print_dbg(f, arg...) do {} while (0) +#endif + +#if defined(__BIG_ENDIAN) +#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 +#else +#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 +#endif +#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 + /********************************************************************/ -#define uint32 unsigned long -typedef volatile struct -{ - uint32 lcd_control; - uint32 lcd_intstatus; - uint32 lcd_intenable; - uint32 lcd_horztiming; - uint32 lcd_verttiming; - uint32 lcd_clkcontrol; - uint32 lcd_dmaaddr0; - uint32 lcd_dmaaddr1; - uint32 lcd_words; - uint32 lcd_pwmdiv; - uint32 lcd_pwmhi; - uint32 reserved[(0x0400-0x002C)/4]; - uint32 lcd_pallettebase[256]; - -} AU1100_LCD; + +/* LCD controller restrictions */ +#define AU1100_LCD_MAX_XRES 800 +#define AU1100_LCD_MAX_YRES 600 +#define AU1100_LCD_MAX_BPP 16 +#define AU1100_LCD_MAX_CLK 48000000 +#define AU1100_LCD_NBR_PALETTE_ENTRIES 256 + +/* Default number of visible screen buffer to allocate */ +#define AU1100FB_NBR_VIDEO_BUFFERS 4 /********************************************************************/ -#define AU1100_LCD_ADDR 0xB5000000 +struct au1100fb_panel +{ + const char name[25]; /* Full name <vendor>_<model> */ -/* - * Register bit definitions - */ + u32 control_base; /* Mode-independent control values */ + u32 clkcontrol_base; /* Panel pixclock preferences */ -/* lcd_control */ -#define LCD_CONTROL_SBPPF (7<<18) -#define LCD_CONTROL_SBPPF_655 (0<<18) -#define LCD_CONTROL_SBPPF_565 (1<<18) -#define LCD_CONTROL_SBPPF_556 (2<<18) -#define LCD_CONTROL_SBPPF_1555 (3<<18) -#define LCD_CONTROL_SBPPF_5551 (4<<18) -#define LCD_CONTROL_WP (1<<17) -#define LCD_CONTROL_WD (1<<16) -#define LCD_CONTROL_C (1<<15) -#define LCD_CONTROL_SM (3<<13) -#define LCD_CONTROL_SM_0 (0<<13) -#define LCD_CONTROL_SM_90 (1<<13) -#define LCD_CONTROL_SM_180 (2<<13) -#define LCD_CONTROL_SM_270 (3<<13) -#define LCD_CONTROL_DB (1<<12) -#define LCD_CONTROL_CCO (1<<11) -#define LCD_CONTROL_DP (1<<10) -#define LCD_CONTROL_PO (3<<8) -#define LCD_CONTROL_PO_00 (0<<8) -#define LCD_CONTROL_PO_01 (1<<8) -#define LCD_CONTROL_PO_10 (2<<8) -#define LCD_CONTROL_PO_11 (3<<8) -#define LCD_CONTROL_MPI (1<<7) -#define LCD_CONTROL_PT (1<<6) -#define LCD_CONTROL_PC (1<<5) -#define LCD_CONTROL_BPP (7<<1) -#define LCD_CONTROL_BPP_1 (0<<1) -#define LCD_CONTROL_BPP_2 (1<<1) -#define LCD_CONTROL_BPP_4 (2<<1) -#define LCD_CONTROL_BPP_8 (3<<1) -#define LCD_CONTROL_BPP_12 (4<<1) -#define LCD_CONTROL_BPP_16 (5<<1) -#define LCD_CONTROL_GO (1<<0) - -/* lcd_intstatus, lcd_intenable */ -#define LCD_INT_SD (1<<7) -#define LCD_INT_OF (1<<6) -#define LCD_INT_UF (1<<5) -#define LCD_INT_SA (1<<3) -#define LCD_INT_SS (1<<2) -#define LCD_INT_S1 (1<<1) -#define LCD_INT_S0 (1<<0) - -/* lcd_horztiming */ -#define LCD_HORZTIMING_HN2 (255<<24) -#define LCD_HORZTIMING_HN2_N(N) (((N)-1)<<24) -#define LCD_HORZTIMING_HN1 (255<<16) -#define LCD_HORZTIMING_HN1_N(N) (((N)-1)<<16) -#define LCD_HORZTIMING_HPW (63<<10) -#define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<10) -#define LCD_HORZTIMING_PPL (1023<<0) -#define LCD_HORZTIMING_PPL_N(N) (((N)-1)<<0) - -/* lcd_verttiming */ -#define LCD_VERTTIMING_VN2 (255<<24) -#define LCD_VERTTIMING_VN2_N(N) (((N)-1)<<24) -#define LCD_VERTTIMING_VN1 (255<<16) -#define LCD_VERTTIMING_VN1_N(N) (((N)-1)<<16) -#define LCD_VERTTIMING_VPW (63<<10) -#define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<10) -#define LCD_VERTTIMING_LPP (1023<<0) -#define LCD_VERTTIMING_LPP_N(N) (((N)-1)<<0) - -/* lcd_clkcontrol */ -#define LCD_CLKCONTROL_IB (1<<18) -#define LCD_CLKCONTROL_IC (1<<17) -#define LCD_CLKCONTROL_IH (1<<16) -#define LCD_CLKCONTROL_IV (1<<15) -#define LCD_CLKCONTROL_BF (31<<10) -#define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10) -#define LCD_CLKCONTROL_PCD (1023<<0) -#define LCD_CLKCONTROL_PCD_N(N) ((N)<<0) - -/* lcd_pwmdiv */ -#define LCD_PWMDIV_EN (1<<12) -#define LCD_PWMDIV_PWMDIV (2047<<0) -#define LCD_PWMDIV_PWMDIV_N(N) (((N)-1)<<0) - -/* lcd_pwmhi */ -#define LCD_PWMHI_PWMHI1 (2047<<12) -#define LCD_PWMHI_PWMHI1_N(N) ((N)<<12) -#define LCD_PWMHI_PWMHI0 (2047<<0) -#define LCD_PWMHI_PWMHI0_N(N) ((N)<<0) - -/* lcd_pallettebase - MONOCHROME */ -#define LCD_PALLETTE_MONO_MI (15<<0) -#define LCD_PALLETTE_MONO_MI_N(N) ((N)<<0) - -/* lcd_pallettebase - COLOR */ -#define LCD_PALLETTE_COLOR_BI (15<<8) -#define LCD_PALLETTE_COLOR_BI_N(N) ((N)<<8) -#define LCD_PALLETTE_COLOR_GI (15<<4) -#define LCD_PALLETTE_COLOR_GI_N(N) ((N)<<4) -#define LCD_PALLETTE_COLOR_RI (15<<0) -#define LCD_PALLETTE_COLOR_RI_N(N) ((N)<<0) - -/* lcd_palletebase - COLOR TFT PALLETIZED */ -#define LCD_PALLETTE_TFT_DC (65535<<0) -#define LCD_PALLETTE_TFT_DC_N(N) ((N)<<0) + u32 horztiming; + u32 verttiming; -/********************************************************************/ + u32 xres; /* Maximum horizontal resolution */ + u32 yres; /* Maximum vertical resolution */ + u32 bpp; /* Maximum depth supported */ +}; -struct known_lcd_panels +struct au1100fb_regs { - uint32 xres; - uint32 yres; - uint32 bpp; - unsigned char panel_name[256]; - uint32 mode_control; - uint32 mode_horztiming; - uint32 mode_verttiming; - uint32 mode_clkcontrol; - uint32 mode_pwmdiv; - uint32 mode_pwmhi; - uint32 mode_toyclksrc; - uint32 mode_backlight; + u32 lcd_control; + u32 lcd_intstatus; + u32 lcd_intenable; + u32 lcd_horztiming; + u32 lcd_verttiming; + u32 lcd_clkcontrol; + u32 lcd_dmaaddr0; + u32 lcd_dmaaddr1; + u32 lcd_words; + u32 lcd_pwmdiv; + u32 lcd_pwmhi; + u32 reserved[(0x0400-0x002C)/4]; + u32 lcd_pallettebase[256]; +}; + +struct au1100fb_device { + + struct fb_info info; /* FB driver info record */ + struct au1100fb_panel *panel; /* Panel connected to this device */ + + struct au1100fb_regs* regs; /* Registers memory map */ + size_t regs_len; + unsigned int regs_phys; + + unsigned char* fb_mem; /* FrameBuffer memory map */ + size_t fb_len; + dma_addr_t fb_phys; }; -#if defined(__BIG_ENDIAN) -#define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_11 -#else -#define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_00 -#endif +/********************************************************************/ -/* - * The fb driver assumes that AUX PLL is at 48MHz. That can - * cover up to 800x600 resolution; if you need higher resolution, - * you should modify the driver as needed, not just this structure. +#define LCD_CONTROL (AU1100_LCD_BASE + 0x0) + #define LCD_CONTROL_SBB_BIT 21 + #define LCD_CONTROL_SBB_MASK (0x3 << LCD_CONTROL_SBB_BIT) + #define LCD_CONTROL_SBB_1 (0 << LCD_CONTROL_SBB_BIT) + #define LCD_CONTROL_SBB_2 (1 << LCD_CONTROL_SBB_BIT) + #define LCD_CONTROL_SBB_3 (2 << LCD_CONTROL_SBB_BIT) + #define LCD_CONTROL_SBB_4 (3 << LCD_CONTROL_SBB_BIT) + #define LCD_CONTROL_SBPPF_BIT 18 + #define LCD_CONTROL_SBPPF_MASK (0x7 << LCD_CONTROL_SBPPF_BIT) + #define LCD_CONTROL_SBPPF_655 (0 << LCD_CONTROL_SBPPF_BIT) + #define LCD_CONTROL_SBPPF_565 (1 << LCD_CONTROL_SBPPF_BIT) + #define LCD_CONTROL_SBPPF_556 (2 << LCD_CONTROL_SBPPF_BIT) + #define LCD_CONTROL_SBPPF_1555 (3 << LCD_CONTROL_SBPPF_BIT) + #define LCD_CONTROL_SBPPF_5551 (4 << LCD_CONTROL_SBPPF_BIT) + #define LCD_CONTROL_WP (1<<17) + #define LCD_CONTROL_WD (1<<16) + #define LCD_CONTROL_C (1<<15) + #define LCD_CONTROL_SM_BIT 13 + #define LCD_CONTROL_SM_MASK (0x3 << LCD_CONTROL_SM_BIT) + #define LCD_CONTROL_SM_0 (0 << LCD_CONTROL_SM_BIT) + #define LCD_CONTROL_SM_90 (1 << LCD_CONTROL_SM_BIT) + #define LCD_CONTROL_SM_180 (2 << LCD_CONTROL_SM_BIT) + #define LCD_CONTROL_SM_270 (3 << LCD_CONTROL_SM_BIT) + #define LCD_CONTROL_DB (1<<12) + #define LCD_CONTROL_CCO (1<<11) + #define LCD_CONTROL_DP (1<<10) + #define LCD_CONTROL_PO_BIT 8 + #define LCD_CONTROL_PO_MASK (0x3 << LCD_CONTROL_PO_BIT) + #define LCD_CONTROL_PO_00 (0 << LCD_CONTROL_PO_BIT) + #define LCD_CONTROL_PO_01 (1 << LCD_CONTROL_PO_BIT) + #define LCD_CONTROL_PO_10 (2 << LCD_CONTROL_PO_BIT) + #define LCD_CONTROL_PO_11 (3 << LCD_CONTROL_PO_BIT) + #define LCD_CONTROL_MPI (1<<7) + #define LCD_CONTROL_PT (1<<6) + #define LCD_CONTROL_PC (1<<5) + #define LCD_CONTROL_BPP_BIT 1 + #define LCD_CONTROL_BPP_MASK (0x7 << LCD_CONTROL_BPP_BIT) + #define LCD_CONTROL_BPP_1 (0 << LCD_CONTROL_BPP_BIT) + #define LCD_CONTROL_BPP_2 (1 << LCD_CONTROL_BPP_BIT) + #define LCD_CONTROL_BPP_4 (2 << LCD_CONTROL_BPP_BIT) + #define LCD_CONTROL_BPP_8 (3 << LCD_CONTROL_BPP_BIT) + #define LCD_CONTROL_BPP_12 (4 << LCD_CONTROL_BPP_BIT) + #define LCD_CONTROL_BPP_16 (5 << LCD_CONTROL_BPP_BIT) + #define LCD_CONTROL_GO (1<<0) + +#define LCD_INTSTATUS (AU1100_LCD_BASE + 0x4) +#define LCD_INTENABLE (AU1100_LCD_BASE + 0x8) + #define LCD_INT_SD (1<<7) + #define LCD_INT_OF (1<<6) + #define LCD_INT_UF (1<<5) + #define LCD_INT_SA (1<<3) + #define LCD_INT_SS (1<<2) + #define LCD_INT_S1 (1<<1) + #define LCD_INT_S0 (1<<0) + +#define LCD_HORZTIMING (AU1100_LCD_BASE + 0xC) + #define LCD_HORZTIMING_HN2_BIT 24 + #define LCD_HORZTIMING_HN2_MASK (0xFF << LCD_HORZTIMING_HN2_BIT) + #define LCD_HORZTIMING_HN2_N(N) ((((N)-1) << LCD_HORZTIMING_HN2_BIT) & LCD_HORZTIMING_HN2_MASK) + #define LCD_HORZTIMING_HN1_BIT 16 + #define LCD_HORZTIMING_HN1_MASK (0xFF << LCD_HORZTIMING_HN1_BIT) + #define LCD_HORZTIMING_HN1_N(N) ((((N)-1) << LCD_HORZTIMING_HN1_BIT) & LCD_HORZTIMING_HN1_MASK) + #define LCD_HORZTIMING_HPW_BIT 10 + #define LCD_HORZTIMING_HPW_MASK (0x3F << LCD_HORZTIMING_HPW_BIT) + #define LCD_HORZTIMING_HPW_N(N) ((((N)-1) << LCD_HORZTIMING_HPW_BIT) & LCD_HORZTIMING_HPW_MASK) + #define LCD_HORZTIMING_PPL_BIT 0 + #define LCD_HORZTIMING_PPL_MASK (0x3FF << LCD_HORZTIMING_PPL_BIT) + #define LCD_HORZTIMING_PPL_N(N) ((((N)-1) << LCD_HORZTIMING_PPL_BIT) & LCD_HORZTIMING_PPL_MASK) + +#define LCD_VERTTIMING (AU1100_LCD_BASE + 0x10) + #define LCD_VERTTIMING_VN2_BIT 24 + #define LCD_VERTTIMING_VN2_MASK (0xFF << LCD_VERTTIMING_VN2_BIT) + #define LCD_VERTTIMING_VN2_N(N) ((((N)-1) << LCD_VERTTIMING_VN2_BIT) & LCD_VERTTIMING_VN2_MASK) + #define LCD_VERTTIMING_VN1_BIT 16 + #define LCD_VERTTIMING_VN1_MASK (0xFF << LCD_VERTTIMING_VN1_BIT) + #define LCD_VERTTIMING_VN1_N(N) ((((N)-1) << LCD_VERTTIMING_VN1_BIT) & LCD_VERTTIMING_VN1_MASK) + #define LCD_VERTTIMING_VPW_BIT 10 + #define LCD_VERTTIMING_VPW_MASK (0x3F << LCD_VERTTIMING_VPW_BIT) + #define LCD_VERTTIMING_VPW_N(N) ((((N)-1) << LCD_VERTTIMING_VPW_BIT) & LCD_VERTTIMING_VPW_MASK) + #define LCD_VERTTIMING_LPP_BIT 0 + #define LCD_VERTTIMING_LPP_MASK (0x3FF << LCD_VERTTIMING_LPP_BIT) + #define LCD_VERTTIMING_LPP_N(N) ((((N)-1) << LCD_VERTTIMING_LPP_BIT) & LCD_VERTTIMING_LPP_MASK) + +#define LCD_CLKCONTROL (AU1100_LCD_BASE + 0x14) + #define LCD_CLKCONTROL_IB (1<<18) + #define LCD_CLKCONTROL_IC (1<<17) + #define LCD_CLKCONTROL_IH (1<<16) + #define LCD_CLKCONTROL_IV (1<<15) + #define LCD_CLKCONTROL_BF_BIT 10 + #define LCD_CLKCONTROL_BF_MASK (0x1F << LCD_CLKCONTROL_BF_BIT) + #define LCD_CLKCONTROL_BF_N(N) ((((N)-1) << LCD_CLKCONTROL_BF_BIT) & LCD_CLKCONTROL_BF_MASK) + #define LCD_CLKCONTROL_PCD_BIT 0 + #define LCD_CLKCONTROL_PCD_MASK (0x3FF << LCD_CLKCONTROL_PCD_BIT) + #define LCD_CLKCONTROL_PCD_N(N) (((N) << LCD_CLKCONTROL_PCD_BIT) & LCD_CLKCONTROL_PCD_MASK) + +#define LCD_DMAADDR0 (AU1100_LCD_BASE + 0x18) +#define LCD_DMAADDR1 (AU1100_LCD_BASE + 0x1C) + #define LCD_DMA_SA_BIT 5 + #define LCD_DMA_SA_MASK (0x7FFFFFF << LCD_DMA_SA_BIT) + #define LCD_DMA_SA_N(N) ((N) & LCD_DMA_SA_MASK) + +#define LCD_WORDS (AU1100_LCD_BASE + 0x20) + #define LCD_WRD_WRDS_BIT 0 + #define LCD_WRD_WRDS_MASK (0xFFFFFFFF << LCD_WRD_WRDS_BIT) + #define LCD_WRD_WRDS_N(N) ((((N)-1) << LCD_WRD_WRDS_BIT) & LCD_WRD_WRDS_MASK) + +#define LCD_PWMDIV (AU1100_LCD_BASE + 0x24) + #define LCD_PWMDIV_EN (1<<12) + #define LCD_PWMDIV_PWMDIV_BIT 0 + #define LCD_PWMDIV_PWMDIV_MASK (0xFFF << LCD_PWMDIV_PWMDIV_BIT) + #define LCD_PWMDIV_PWMDIV_N(N) ((((N)-1) << LCD_PWMDIV_PWMDIV_BIT) & LCD_PWMDIV_PWMDIV_MASK) + +#define LCD_PWMHI (AU1100_LCD_BASE + 0x28) + #define LCD_PWMHI_PWMHI1_BIT 12 + #define LCD_PWMHI_PWMHI1_MASK (0xFFF << LCD_PWMHI_PWMHI1_BIT) + #define LCD_PWMHI_PWMHI1_N(N) (((N) << LCD_PWMHI_PWMHI1_BIT) & LCD_PWMHI_PWMHI1_MASK) + #define LCD_PWMHI_PWMHI0_BIT 0 + #define LCD_PWMHI_PWMHI0_MASK (0xFFF << LCD_PWMHI_PWMHI0_BIT) + #define LCD_PWMHI_PWMHI0_N(N) (((N) << LCD_PWMHI_PWMHI0_BIT) & LCD_PWMHI_PWMHI0_MASK) + +#define LCD_PALLETTEBASE (AU1100_LCD_BASE + 0x400) + #define LCD_PALLETTE_MONO_MI_BIT 0 + #define LCD_PALLETTE_MONO_MI_MASK (0xF << LCD_PALLETTE_MONO_MI_BIT) + #define LCD_PALLETTE_MONO_MI_N(N) (((N)<< LCD_PALLETTE_MONO_MI_BIT) & LCD_PALLETTE_MONO_MI_MASK) + + #define LCD_PALLETTE_COLOR_RI_BIT 8 + #define LCD_PALLETTE_COLOR_RI_MASK (0xF << LCD_PALLETTE_COLOR_RI_BIT) + #define LCD_PALLETTE_COLOR_RI_N(N) (((N)<< LCD_PALLETTE_COLOR_RI_BIT) & LCD_PALLETTE_COLOR_RI_MASK) + #define LCD_PALLETTE_COLOR_GI_BIT 4 + #define LCD_PALLETTE_COLOR_GI_MASK (0xF << LCD_PALLETTE_COLOR_GI_BIT) + #define LCD_PALLETTE_COLOR_GI_N(N) (((N)<< LCD_PALLETTE_COLOR_GI_BIT) & LCD_PALLETTE_COLOR_GI_MASK) + #define LCD_PALLETTE_COLOR_BI_BIT 0 + #define LCD_PALLETTE_COLOR_BI_MASK (0xF << LCD_PALLETTE_COLOR_BI_BIT) + #define LCD_PALLETTE_COLOR_BI_N(N) (((N)<< LCD_PALLETTE_COLOR_BI_BIT) & LCD_PALLETTE_COLOR_BI_MASK) + + #define LCD_PALLETTE_TFT_DC_BIT 0 + #define LCD_PALLETTE_TFT_DC_MASK (0xFFFF << LCD_PALLETTE_TFT_DC_BIT) + #define LCD_PALLETTE_TFT_DC_N(N) (((N)<< LCD_PALLETTE_TFT_DC_BIT) & LCD_PALLETTE_TFT_DC_MASK) + +/********************************************************************/ + +/* List of panels known to work with the AU1100 LCD controller. + * To add a new panel, enter the same specifications as the + * Generic_TFT one, and MAKE SURE that it doesn't conflicts + * with the controller restrictions. Restrictions are: + * + * STN color panels: max_bpp <= 12 + * STN mono panels: max_bpp <= 4 + * TFT panels: max_bpp <= 16 + * max_xres <= 800 + * max_yres <= 600 */ -struct known_lcd_panels panels[] = +static struct au1100fb_panel known_lcd_panels[] = { - { /* 0: Pb1100 LCDA: Sharp 320x240 TFT panel */ - 320, /* xres */ - 240, /* yres */ - 16, /* bpp */ - - "Sharp_320x240_16", - /* mode_control */ + /* 800x600x16bpp CRT */ + [0] = { + .name = "CRT_800x600_16", + .xres = 800, + .yres = 600, + .bpp = 16, + .control_base = 0x0004886A | + LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF | + LCD_CONTROL_BPP_16, + .clkcontrol_base = 0x00020000, + .horztiming = 0x005aff1f, + .verttiming = 0x16000e57, + }, + /* just the standard LCD */ + [1] = { + .name = "WWPC LCD", + .xres = 240, + .yres = 320, + .bpp = 16, + .control_base = 0x0006806A, + .horztiming = 0x0A1010EF, + .verttiming = 0x0301013F, + .clkcontrol_base = 0x00018001, + }, + /* Sharp 320x240 TFT panel */ + [2] = { + .name = "Sharp_LQ038Q5DR01", + .xres = 320, + .yres = 240, + .bpp = 16, + .control_base = ( LCD_CONTROL_SBPPF_565 - /*LCD_CONTROL_WP*/ - /*LCD_CONTROL_WD*/ | LCD_CONTROL_C | LCD_CONTROL_SM_0 - /*LCD_CONTROL_DB*/ - /*LCD_CONTROL_CCO*/ - /*LCD_CONTROL_DP*/ - | LCD_DEFAULT_PIX_FORMAT - /*LCD_CONTROL_MPI*/ + | LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_PT | LCD_CONTROL_PC | LCD_CONTROL_BPP_16 ), - - /* mode_horztiming */ + .horztiming = ( LCD_HORZTIMING_HN2_N(8) | LCD_HORZTIMING_HN1_N(60) | LCD_HORZTIMING_HPW_N(12) | LCD_HORZTIMING_PPL_N(320) ), - - /* mode_verttiming */ + .verttiming = ( LCD_VERTTIMING_VN2_N(5) | LCD_VERTTIMING_VN1_N(17) | LCD_VERTTIMING_VPW_N(1) | LCD_VERTTIMING_LPP_N(240) ), - - /* mode_clkcontrol */ - ( 0 - /*LCD_CLKCONTROL_IB*/ - /*LCD_CLKCONTROL_IC*/ - /*LCD_CLKCONTROL_IH*/ - /*LCD_CLKCONTROL_IV*/ - | LCD_CLKCONTROL_PCD_N(1) ), - - /* mode_pwmdiv */ - 0, - - /* mode_pwmhi */ - 0, - - /* mode_toyclksrc */ - ((1<<7) | (1<<6) | (1<<5)), - - /* mode_backlight */ - 6 + .clkcontrol_base = LCD_CLKCONTROL_PCD_N(1), }, - { /* 1: Pb1100 LCDC 640x480 TFT panel */ - 640, /* xres */ - 480, /* yres */ - 16, /* bpp */ - - "Generic_640x480_16", - - /* mode_control */ - 0x004806a | LCD_DEFAULT_PIX_FORMAT, - - /* mode_horztiming */ - 0x3434d67f, - - /* mode_verttiming */ - 0x0e0e39df, - - /* mode_clkcontrol */ - ( 0 - /*LCD_CLKCONTROL_IB*/ - /*LCD_CLKCONTROL_IC*/ - /*LCD_CLKCONTROL_IH*/ - /*LCD_CLKCONTROL_IV*/ - | LCD_CLKCONTROL_PCD_N(1) ), - - /* mode_pwmdiv */ - 0, - - /* mode_pwmhi */ - 0, - - /* mode_toyclksrc */ - ((1<<7) | (1<<6) | (0<<5)), - - /* mode_backlight */ - 7 + /* Hitachi SP14Q005 and possibly others */ + [3] = { + .name = "Hitachi_SP14Qxxx", + .xres = 320, + .yres = 240, + .bpp = 4, + .control_base = + ( LCD_CONTROL_C + | LCD_CONTROL_BPP_4 ), + .horztiming = + ( LCD_HORZTIMING_HN2_N(1) + | LCD_HORZTIMING_HN1_N(1) + | LCD_HORZTIMING_HPW_N(1) + | LCD_HORZTIMING_PPL_N(320) ), + .verttiming = + ( LCD_VERTTIMING_VN2_N(1) + | LCD_VERTTIMING_VN1_N(1) + | LCD_VERTTIMING_VPW_N(1) + | LCD_VERTTIMING_LPP_N(240) ), + .clkcontrol_base = LCD_CLKCONTROL_PCD_N(4), }, - { /* 2: Pb1100 LCDB 640x480 PrimeView TFT panel */ - 640, /* xres */ - 480, /* yres */ - 16, /* bpp */ - - "PrimeView_640x480_16", - - /* mode_control */ - 0x0004886a | LCD_DEFAULT_PIX_FORMAT, - - /* mode_horztiming */ - 0x0e4bfe7f, - - /* mode_verttiming */ - 0x210805df, - - /* mode_clkcontrol */ - 0x00038001, - - /* mode_pwmdiv */ - 0, - - /* mode_pwmhi */ - 0, - - /* mode_toyclksrc */ - ((1<<7) | (1<<6) | (0<<5)), - - /* mode_backlight */ - 7 + /* Generic 640x480 TFT panel */ + [4] = { + .name = "TFT_640x480_16", + .xres = 640, + .yres = 480, + .bpp = 16, + .control_base = 0x004806a | LCD_CONTROL_DEFAULT_PO, + .horztiming = 0x3434d67f, + .verttiming = 0x0e0e39df, + .clkcontrol_base = LCD_CLKCONTROL_PCD_N(1), }, - { /* 3: Pb1100 800x600x16bpp NEON CRT */ - 800, /* xres */ - 600, /* yres */ - 16, /* bpp */ - - "NEON_800x600_16", - - /* mode_control */ - 0x0004886A | LCD_DEFAULT_PIX_FORMAT, - - /* mode_horztiming */ - 0x005AFF1F, - - /* mode_verttiming */ - 0x16000E57, - - /* mode_clkcontrol */ - 0x00020000, - - /* mode_pwmdiv */ - 0, - - /* mode_pwmhi */ - 0, - - /* mode_toyclksrc */ - ((1<<7) | (1<<6) | (0<<5)), - - /* mode_backlight */ - 7 + /* Pb1100 LCDB 640x480 PrimeView TFT panel */ + [5] = { + .name = "PrimeView_640x480_16", + .xres = 640, + .yres = 480, + .bpp = 16, + .control_base = 0x0004886a | LCD_CONTROL_DEFAULT_PO, + .horztiming = 0x0e4bfe7f, + .verttiming = 0x210805df, + .clkcontrol_base = 0x00038001, }, +}; - { /* 4: Pb1100 640x480x16bpp NEON CRT */ - 640, /* xres */ - 480, /* yres */ - 16, /* bpp */ - - "NEON_640x480_16", - - /* mode_control */ - 0x0004886A | LCD_DEFAULT_PIX_FORMAT, - - /* mode_horztiming */ - 0x0052E27F, - - /* mode_verttiming */ - 0x18000DDF, - - /* mode_clkcontrol */ - 0x00020000, +struct au1100fb_drv_info { + int panel_idx; + char *opt_mode; +}; - /* mode_pwmdiv */ - 0, +/********************************************************************/ - /* mode_pwmhi */ - 0, +/* Inline helpers */ - /* mode_toyclksrc */ - ((1<<7) | (1<<6) | (0<<5)), +#define panel_is_dual(panel) (panel->control_base & LCD_CONTROL_DP) +#define panel_is_active(panel)(panel->control_base & LCD_CONTROL_PT) +#define panel_is_color(panel) (panel->control_base & LCD_CONTROL_PC) +#define panel_swap_rgb(panel) (panel->control_base & LCD_CONTROL_CCO) - /* mode_backlight */ - 7 - }, -}; #endif /* _AU1100LCD_H */ diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index acc81cb01d5..9d5015e9937 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -5,7 +5,6 @@ * */ -#include <linux/version.h> #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 630f2dfa969..6a219b2c77e 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -14,12 +14,11 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/spinlock.h> #include <linux/fb.h> #include <linux/backlight.h> -#include <asm/mach-types.h> #include <asm/arch/sharpsl.h> #define CORGI_DEFAULT_INTENSITY 0x1f @@ -49,6 +48,12 @@ static void corgibl_send_intensity(int intensity) corgibl_mach_set_intensity(intensity); spin_unlock_irqrestore(&bl_lock, flags); + + corgi_kick_batt = symbol_get(sharpsl_battery_kick); + if (corgi_kick_batt) { + corgi_kick_batt(); + symbol_put(sharpsl_battery_kick); + } } static void corgibl_blank(int blank) @@ -74,17 +79,15 @@ static void corgibl_blank(int blank) } #ifdef CONFIG_PM -static int corgibl_suspend(struct device *dev, pm_message_t state, u32 level) +static int corgibl_suspend(struct platform_device *dev, pm_message_t state) { - if (level == SUSPEND_POWER_DOWN) - corgibl_blank(FB_BLANK_POWERDOWN); + corgibl_blank(FB_BLANK_POWERDOWN); return 0; } -static int corgibl_resume(struct device *dev, u32 level) +static int corgibl_resume(struct platform_device *dev) { - if (level == RESUME_POWER_ON) - corgibl_blank(FB_BLANK_UNBLANK); + corgibl_blank(FB_BLANK_UNBLANK); return 0; } #else @@ -140,9 +143,9 @@ static struct backlight_properties corgibl_data = { static struct backlight_device *corgi_backlight_device; -static int __init corgibl_probe(struct device *dev) +static int __init corgibl_probe(struct platform_device *pdev) { - struct corgibl_machinfo *machinfo = dev->platform_data; + struct corgibl_machinfo *machinfo = pdev->dev.platform_data; corgibl_data.max_brightness = machinfo->max_intensity; corgibl_mach_set_intensity = machinfo->set_bl_intensity; @@ -159,7 +162,7 @@ static int __init corgibl_probe(struct device *dev) return 0; } -static int corgibl_remove(struct device *dev) +static int corgibl_remove(struct platform_device *dev) { backlight_device_unregister(corgi_backlight_device); @@ -169,23 +172,24 @@ static int corgibl_remove(struct device *dev) return 0; } -static struct device_driver corgibl_driver = { - .name = "corgi-bl", - .bus = &platform_bus_type, +static struct platform_driver corgibl_driver = { .probe = corgibl_probe, .remove = corgibl_remove, .suspend = corgibl_suspend, .resume = corgibl_resume, + .driver = { + .name = "corgi-bl", + }, }; static int __init corgibl_init(void) { - return driver_register(&corgibl_driver); + return platform_driver_register(&corgibl_driver); } static void __exit corgibl_exit(void) { - driver_unregister(&corgibl_driver); + platform_driver_unregister(&corgibl_driver); } module_init(corgibl_init); diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 470e6f0ee4d..68c690605aa 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -5,7 +5,6 @@ * */ -#include <linux/version.h> #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 3d20b2d47d4..d3728f60961 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -51,7 +51,9 @@ static struct fb_ops bw2_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = bw2_mmap, .fb_ioctl = bw2_ioctl, - .fb_cursor = soft_cursor, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sbusfb_compat_ioctl, +#endif }; /* OBio addresses for the bwtwo registers */ diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c index 67711f7b11b..cdc71572cf3 100644 --- a/drivers/video/cfbcopyarea.c +++ b/drivers/video/cfbcopyarea.c @@ -349,46 +349,10 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) unsigned long __iomem *dst = NULL, *src = NULL; int bits = BITS_PER_LONG, bytes = bits >> 3; int dst_idx = 0, src_idx = 0, rev_copy = 0; - int x2, y2, vxres, vyres; if (p->state != FBINFO_STATE_RUNNING) return; - /* We want rotation but lack hardware to do it for us. */ - if (!p->fbops->fb_rotate && p->var.rotate) { - } - - vxres = p->var.xres_virtual; - vyres = p->var.yres_virtual; - - if (area->dx > vxres || area->sx > vxres || - area->dy > vyres || area->sy > vyres) - return; - - /* clip the destination - * We could use hardware clipping but on many cards you get around - * hardware clipping by writing to framebuffer directly. - */ - x2 = area->dx + area->width; - y2 = area->dy + area->height; - dx = area->dx > 0 ? area->dx : 0; - dy = area->dy > 0 ? area->dy : 0; - x2 = x2 < vxres ? x2 : vxres; - y2 = y2 < vyres ? y2 : vyres; - width = x2 - dx; - height = y2 - dy; - - if ((width==0) ||(height==0)) - return; - - /* update sx1,sy1 */ - sx += (dx - area->dx); - sy += (dy - area->dy); - - /* the source must be completely inside the virtual screen */ - if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres) - return; - /* if the beginning of the target area might overlap with the end of the source area, be have to copy the area reverse. */ if ((dy == sy && dx > sx) || (dy > sy)) { diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c index e4fc42b013e..167d9314e6e 100644 --- a/drivers/video/cfbfillrect.c +++ b/drivers/video/cfbfillrect.c @@ -344,7 +344,8 @@ bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) { - unsigned long x2, y2, vxres, vyres, height, width, pat, fg; + unsigned long pat, fg; + unsigned long width = rect->width, height = rect->height; int bits = BITS_PER_LONG, bytes = bits >> 3; u32 bpp = p->var.bits_per_pixel; unsigned long __iomem *dst; @@ -353,27 +354,6 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) if (p->state != FBINFO_STATE_RUNNING) return; - /* We want rotation but lack hardware to do it for us. */ - if (!p->fbops->fb_rotate && p->var.rotate) { - } - - vxres = p->var.xres_virtual; - vyres = p->var.yres_virtual; - - if (!rect->width || !rect->height || - rect->dx > vxres || rect->dy > vyres) - return; - - /* We could use hardware clipping but on many cards you get around - * hardware clipping by writing to framebuffer directly. */ - - x2 = rect->dx + rect->width; - y2 = rect->dy + rect->height; - x2 = x2 < vxres ? x2 : vxres; - y2 = y2 < vyres ? y2 : vyres; - width = x2 - rect->dx; - height = y2 - rect->dy; - if (p->fix.visual == FB_VISUAL_TRUECOLOR || p->fix.visual == FB_VISUAL_DIRECTCOLOR ) fg = ((u32 *) (p->pseudo_palette))[rect->color]; diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index 4c123abaa84..a7770c4f17d 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -80,10 +80,12 @@ static u32 cfb_tab32[] = { #define LEFT_POS(bpp) (32 - bpp) #define SHIFT_HIGH(val, bits) ((val) >> (bits)) #define SHIFT_LOW(val, bits) ((val) << (bits)) +#define BIT_NR(b) (7 - (b)) #else #define LEFT_POS(bpp) (0) #define SHIFT_HIGH(val, bits) ((val) << (bits)) #define SHIFT_LOW(val, bits) ((val) >> (bits)) +#define BIT_NR(b) (b) #endif static inline void color_imageblit(const struct fb_image *image, @@ -177,7 +179,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * while (j--) { l--; - color = (*s & (1 << l)) ? fgcolor : bgcolor; + color = (*s & 1 << (BIT_NR(l))) ? fgcolor : bgcolor; color <<= LEFT_POS(bpp); val |= SHIFT_HIGH(color, shift); @@ -272,33 +274,13 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) { u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; - u32 width = image->width, height = image->height; + u32 width = image->width; u32 dx = image->dx, dy = image->dy; - int x2, y2, vxres, vyres; u8 __iomem *dst1; if (p->state != FBINFO_STATE_RUNNING) return; - vxres = p->var.xres_virtual; - vyres = p->var.yres_virtual; - /* - * We could use hardware clipping but on many cards you get around - * hardware clipping by writing to framebuffer directly like we are - * doing here. - */ - if (image->dx > vxres || image->dy > vyres) - return; - - x2 = image->dx + image->width; - y2 = image->dy + image->height; - dx = image->dx > 0 ? image->dx : 0; - dy = image->dy > 0 ? image->dy : 0; - x2 = x2 < vxres ? x2 : vxres; - y2 = y2 < vyres ? y2 : vyres; - width = x2 - dx; - height = y2 - dy; - bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); start_index = bitstart & (32 - 1); pitch_index = (p->fix.line_length & (bpl - 1)) * 8; diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index 18e60b941e2..1bed50f2a27 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -49,7 +49,9 @@ static struct fb_ops cg14_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = cg14_mmap, .fb_ioctl = cg14_ioctl, - .fb_cursor = soft_cursor, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sbusfb_compat_ioctl, +#endif }; #define CG14_MCR_INTENABLE_SHIFT 7 diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 6e7d8d45dc6..a1354e7e051 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -50,7 +50,9 @@ static struct fb_ops cg3_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = cg3_mmap, .fb_ioctl = cg3_ioctl, - .fb_cursor = soft_cursor, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sbusfb_compat_ioctl, +#endif }; diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 49a2545671d..9debe642fd2 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -54,7 +54,9 @@ static struct fb_ops cg6_ops = { .fb_sync = cg6_sync, .fb_mmap = cg6_mmap, .fb_ioctl = cg6_ioctl, - .fb_cursor = soft_cursor, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sbusfb_compat_ioctl, +#endif }; /* Offset of interesting structures in the OBIO space */ @@ -654,12 +656,6 @@ static void cg6_chip_init(struct fb_info *info) sbus_writel(0, &fbc->clipminy); sbus_writel(info->var.xres - 1, &fbc->clipmaxx); sbus_writel(info->var.yres - 1, &fbc->clipmaxy); - - /* Disable cursor in Brooktree DAC. */ - sbus_writel(0x06 << 24, &par->bt->addr); - tmp = sbus_readl(&par->bt->control); - tmp &= ~(0x03 << 24); - sbus_writel(tmp, &par->bt->control); } struct all_info { diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 4131243cfdf..bc061d4ec78 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -91,7 +91,6 @@ static struct fb_ops chipsfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int chipsfb_check_var(struct fb_var_screeninfo *var, diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index a3040429c27..e0dbdfc0c8b 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -275,20 +275,20 @@ static const struct cirrusfb_board_info_rec { #ifdef CONFIG_PCI #define CHIP(id, btype) \ - { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_##id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) } + { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) } static struct pci_device_id cirrusfb_pci_table[] = { - CHIP( CIRRUS_5436, BT_ALPINE ), - CHIP( CIRRUS_5434_8, BT_ALPINE ), - CHIP( CIRRUS_5434_4, BT_ALPINE ), - CHIP( CIRRUS_5430, BT_ALPINE ), /* GD-5440 has identical id */ - CHIP( CIRRUS_7543, BT_ALPINE ), - CHIP( CIRRUS_7548, BT_ALPINE ), - CHIP( CIRRUS_5480, BT_GD5480 ), /* MacPicasso probably */ - CHIP( CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is a GD5446 */ - CHIP( CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */ - CHIP( CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */ - CHIP( CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/ + CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ), + CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ), + CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ), + CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */ + CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ), + CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ), + CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */ + CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */ + CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */ + CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */ + CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/ { 0, } }; MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); @@ -404,7 +404,7 @@ struct cirrusfb_info { struct cirrusfb_regs currentmode; int blank_mode; - u32 pseudo_palette[17]; + u32 pseudo_palette[16]; struct { u8 red, green, blue, pad; } palette[256]; #ifdef CONFIG_ZORRO @@ -548,7 +548,6 @@ static struct fb_ops cirrusfb_ops = { .fb_fillrect = cirrusfb_fillrect, .fb_copyarea = cirrusfb_copyarea, .fb_imageblit = cirrusfb_imageblit, - .fb_cursor = soft_cursor, }; /*--- Hardware Specific Routines -------------------------------------------*/ @@ -1604,14 +1603,14 @@ static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green, switch (info->var.bits_per_pixel) { case 8: - ((u8*)(info->pseudo_palette))[regno] = v; + cinfo->pseudo_palette[regno] = v; break; case 16: - ((u16*)(info->pseudo_palette))[regno] = v; + cinfo->pseudo_palette[regno] = v; break; case 24: case 32: - ((u32*)(info->pseudo_palette))[regno] = v; + cinfo->pseudo_palette[regno] = v; break; } return 0; @@ -2021,18 +2020,21 @@ static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo, const struct fb_fillrect *region) { int m; /* bytes per pixel */ + u32 color = (cinfo->info->fix.visual == FB_VISUAL_TRUECOLOR) ? + cinfo->pseudo_palette[region->color] : region->color; + if(cinfo->info->var.bits_per_pixel == 1) { cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel, region->dx / 8, region->dy, region->width / 8, region->height, - region->color, + color, cinfo->currentmode.line_length); } else { m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8; cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel, region->dx * m, region->dy, region->width * m, region->height, - region->color, + color, cinfo->currentmode.line_length); } return; diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c index 8692e002986..50b78af0fa2 100644 --- a/drivers/video/clps711xfb.c +++ b/drivers/video/clps711xfb.c @@ -219,7 +219,6 @@ static struct fb_ops clps7111fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index eb83a7874c7..5f74df99340 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -28,7 +28,7 @@ config VGA_CONSOLE config VIDEO_SELECT bool "Video mode selection support" - depends on (X86 || X86_64) && VGA_CONSOLE + depends on X86 && VGA_CONSOLE ---help--- This enables support for text mode selection on kernel startup. If you want to take advantage of some high-resolution text mode your @@ -98,6 +98,18 @@ config FRAMEBUFFER_CONSOLE tristate "Framebuffer Console support" depends on FB select CRC32 + help + Low-level framebuffer-based console driver. + +config FRAMEBUFFER_CONSOLE_ROTATION + bool "Framebuffer Console Rotation" + depends on FRAMEBUFFER_CONSOLE + help + Enable display rotation for the framebuffer console. This is done + in software and may be significantly slower than a normally oriented + display. Note that the rotation is done at the console level only + such that other users of the framebuffer will remain normally + oriented. config STI_CONSOLE tristate "STI text console" @@ -110,7 +122,7 @@ config STI_CONSOLE config FONTS bool "Select compiled-in fonts" - depends on FRAMEBUFFER_CONSOLE + depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE help Say Y here if you would like to use fonts other than the default your frame buffer console usually use. @@ -123,7 +135,7 @@ config FONTS config FONT_8x8 bool "VGA 8x8 font" if FONTS - depends on FRAMEBUFFER_CONSOLE + depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE default y if !SPARC32 && !SPARC64 && !FONTS help This is the "high resolution" font for the VGA frame buffer (the one @@ -137,7 +149,7 @@ config FONT_8x8 config FONT_8x16 bool "VGA 8x16 font" if FONTS - depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON + depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || STI_CONSOLE || USB_SISUSBVGA_CON default y if !SPARC32 && !SPARC64 && !FONTS help This is the "high resolution" font for the VGA frame buffer (the one @@ -147,7 +159,7 @@ config FONT_8x16 config FONT_6x11 bool "Mac console 6x11 font (not supported by all drivers)" if FONTS - depends on FRAMEBUFFER_CONSOLE + depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE default y if !SPARC32 && !SPARC64 && !FONTS && MAC help Small console font with Macintosh-style high-half glyphs. Some Mac diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 42c7b8dcd22..9b26dda18a3 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -26,10 +26,14 @@ obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o -obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o ifeq ($(CONFIG_FB_TILEBLITTING),y) obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o endif +ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION),y) +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \ + fbcon_ccw.o +endif obj-$(CONFIG_FB_STI) += sticore.o font.o diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 9f70e512b88..e65fc3ef763 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -22,35 +22,6 @@ /* * Accelerated handlers. */ -#define FBCON_ATTRIBUTE_UNDERLINE 1 -#define FBCON_ATTRIBUTE_REVERSE 2 -#define FBCON_ATTRIBUTE_BOLD 4 - -static inline int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos - rows; -} - - -static inline int get_attribute(struct fb_info *info, u16 c) -{ - int attribute = 0; - - if (fb_get_color_depth(&info->var, &info->fix) == 1) { - if (attr_underline(c)) - attribute |= FBCON_ATTRIBUTE_UNDERLINE; - if (attr_reverse(c)) - attribute |= FBCON_ATTRIBUTE_REVERSE; - if (attr_bold(c)) - attribute |= FBCON_ATTRIBUTE_BOLD; - } - - return attribute; -} - static inline void update_attr(u8 *dst, u8 *src, int attribute, struct vc_data *vc) { @@ -272,6 +243,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int w = (vc->vc_font.width + 7) >> 3, c; int y = real_y(p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1; char *src; cursor.set = 0; @@ -408,11 +380,27 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, cursor.image.depth = 1; cursor.rop = ROP_XOR; - info->fbops->fb_cursor(info, &cursor); + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); ops->cursor_reset = 0; } +static int bit_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + int err; + + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + void fbcon_set_bitops(struct fbcon_ops *ops) { ops->bmove = bit_bmove; @@ -420,6 +408,11 @@ void fbcon_set_bitops(struct fbcon_ops *ops) ops->putcs = bit_putcs; ops->clear_margins = bit_clear_margins; ops->cursor = bit_cursor; + ops->update_start = bit_update_start; + ops->rotate_font = NULL; + + if (ops->rotate) + fbcon_set_rotate(ops); } EXPORT_SYMBOL(fbcon_set_bitops); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 0fc8bb499c3..bcea87c3cc0 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -106,7 +106,8 @@ enum { FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ }; -struct display fb_display[MAX_NR_CONSOLES]; +static struct display fb_display[MAX_NR_CONSOLES]; + static signed char con2fb_map[MAX_NR_CONSOLES]; static signed char con2fb_map_boot[MAX_NR_CONSOLES]; static int logo_height; @@ -130,6 +131,9 @@ static char fontname[40]; /* current fb_info */ static int info_idx = -1; +/* console rotation */ +static int rotate; + static const struct consw fb_con; #define CM_SOFTBACK (8) @@ -176,7 +180,6 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines); /* * Internal routines */ -static __inline__ int real_y(struct display *p, int ypos); static __inline__ void ywrap_up(struct vc_data *vc, int count); static __inline__ void ywrap_down(struct vc_data *vc, int count); static __inline__ void ypan_up(struct vc_data *vc, int count); @@ -189,6 +192,8 @@ static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *va int unit); static void fbcon_redraw_move(struct vc_data *vc, struct display *p, int line, int count, int dy); +static void fbcon_modechanged(struct fb_info *info); +static void fbcon_set_all_vcs(struct fb_info *info); #ifdef CONFIG_MAC /* @@ -203,6 +208,88 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp) } #endif +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION +static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) +{ + struct fbcon_ops *ops = info->fbcon_par; + + if (!(info->flags & FBINFO_MISC_TILEBLITTING) && + p->con_rotate < 4) + ops->rotate = p->con_rotate; + else + ops->rotate = 0; +} + +static void fbcon_rotate(struct fb_info *info, u32 rotate) +{ + struct fbcon_ops *ops= info->fbcon_par; + struct fb_info *fb_info; + + if (!ops || ops->currcon == -1) + return; + + fb_info = registered_fb[con2fb_map[ops->currcon]]; + + if (info == fb_info) { + struct display *p = &fb_display[ops->currcon]; + + if (rotate < 4) + p->con_rotate = rotate; + else + p->con_rotate = 0; + + fbcon_modechanged(info); + } +} + +static void fbcon_rotate_all(struct fb_info *info, u32 rotate) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct vc_data *vc; + struct display *p; + int i; + + if (!ops || ops->currcon < 0 || rotate > 3) + return; + + for (i = 0; i < MAX_NR_CONSOLES; i++) { + vc = vc_cons[i].d; + if (!vc || vc->vc_mode != KD_TEXT || + registered_fb[con2fb_map[i]] != info) + continue; + + p = &fb_display[vc->vc_num]; + p->con_rotate = rotate; + } + + fbcon_set_all_vcs(info); +} +#else +static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) +{ + struct fbcon_ops *ops = info->fbcon_par; + + ops->rotate = FB_ROTATE_UR; +} + +static void fbcon_rotate(struct fb_info *info, u32 rotate) +{ + return; +} + +static void fbcon_rotate_all(struct fb_info *info, u32 rotate) +{ + return; +} +#endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ + +static int fbcon_get_rotate(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + + return (ops) ? ops->rotate : 0; +} + static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; @@ -281,6 +368,18 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info, return color; } +static void fbcon_update_softback(struct vc_data *vc) +{ + int l = fbcon_softback_size / vc->vc_size_row; + + if (l > 5) + softback_end = softback_buf + l * vc->vc_size_row; + else + /* Smaller scrollback makes no sense, and 0 would screw + the operation totally */ + softback_top = 0; +} + static void fb_flashcursor(void *private) { struct fb_info *info = private; @@ -410,6 +509,14 @@ static int __init fb_console_setup(char *this_opt) last_fb_vc = simple_strtoul(options, &options, 10) - 1; fbcon_is_default = 0; } + + if (!strncmp(options, "rotate:", 7)) { + options += 7; + if (*options) + rotate = simple_strtoul(options, &options, 0); + if (rotate > 3) + rotate = 0; + } } return 0; } @@ -468,6 +575,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, int cols, int rows, int new_cols, int new_rows) { /* Need to make room for the logo */ + struct fbcon_ops *ops = info->fbcon_par; int cnt, erase = vc->vc_video_erase_char, step; unsigned short *save = NULL, *r, *q; @@ -477,7 +585,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, */ if (fb_get_color_depth(&info->var, &info->fix) == 1) erase &= ~0x400; - logo_height = fb_prepare_logo(info); + logo_height = fb_prepare_logo(info, ops->rotate); logo_lines = (logo_height + vc->vc_font.height - 1) / vc->vc_font.height; q = (unsigned short *) (vc->vc_origin + @@ -544,10 +652,14 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, { struct fbcon_ops *ops = info->fbcon_par; + ops->p = (p) ? p : &fb_display[vc->vc_num]; + if ((info->flags & FBINFO_MISC_TILEBLITTING)) fbcon_set_tileops(vc, info, p, ops); - else + else { + fbcon_set_rotation(info, ops->p); fbcon_set_bitops(ops); + } } #else static void set_blitting_type(struct vc_data *vc, struct fb_info *info, @@ -556,6 +668,8 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, struct fbcon_ops *ops = info->fbcon_par; info->flags &= ~FBINFO_MISC_TILEBLITTING; + ops->p = (p) ? p : &fb_display[vc->vc_num]; + fbcon_set_rotation(info, ops->p); fbcon_set_bitops(ops); } #endif /* CONFIG_MISC_TILEBLITTING */ @@ -615,9 +729,19 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, fbcon_del_cursor_timer(oldinfo); kfree(ops->cursor_state.mask); kfree(ops->cursor_data); + kfree(ops->fontbuffer); kfree(oldinfo->fbcon_par); oldinfo->fbcon_par = NULL; module_put(oldinfo->fbops->owner); + /* + If oldinfo and newinfo are driving the same hardware, + the fb_release() method of oldinfo may attempt to + restore the hardware state. This will leave the + newinfo in an undefined state. Thus, a call to + fb_set_par() may be needed for the newinfo. + */ + if (newinfo->fbops->fb_set_par) + newinfo->fbops->fb_set_par(newinfo); } return err; @@ -806,7 +930,9 @@ static const char *fbcon_startup(void) memset(ops, 0, sizeof(struct fbcon_ops)); ops->currcon = -1; ops->graphics = 1; + ops->cur_rotate = -1; info->fbcon_par = ops; + p->con_rotate = rotate; set_blitting_type(vc, info, NULL); if (info->fix.type != FB_TYPE_TEXT) { @@ -845,8 +971,10 @@ static const char *fbcon_startup(void) vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ } - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); DPRINTK("mode: %s\n", info->fix.id); @@ -932,8 +1060,6 @@ static void fbcon_init(struct vc_data *vc, int init) (info->fix.type == FB_TYPE_TEXT)) logo = 0; - info->var.xoffset = info->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ - if (var_to_display(p, &info->var, info)) return; @@ -965,13 +1091,18 @@ static void fbcon_init(struct vc_data *vc, int init) if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc, svc); + ops = info->fbcon_par; + p->con_rotate = rotate; + set_blitting_type(vc, info, NULL); + cols = vc->vc_cols; rows = vc->vc_rows; - new_cols = info->var.xres / vc->vc_font.width; - new_rows = info->var.yres / vc->vc_font.height; + new_cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + new_cols /= vc->vc_font.width; + new_rows /= vc->vc_font.height; vc_resize(vc, new_cols, new_rows); - ops = info->fbcon_par; /* * We must always set the mode. The mode of the previous console * driver could be in the same resolution but we are using different @@ -1007,16 +1138,14 @@ static void fbcon_init(struct vc_data *vc, int init) if (logo) fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows); - if (vc == svc && softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - if (l > 5) - softback_end = softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 would screw - the operation totally */ - softback_top = 0; - } + if (vc == svc && softback_buf) + fbcon_update_softback(vc); + + if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + ops->rotate = FB_ROTATE_UR; + set_blitting_type(vc, info, p); } + } static void fbcon_deinit(struct vc_data *vc) @@ -1053,15 +1182,6 @@ static void fbcon_deinit(struct vc_data *vc) * restriction is simplicity & efficiency at the moment. */ -static __inline__ int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos - rows; -} - - static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, int width) { @@ -1149,13 +1269,6 @@ static int scrollback_phys_max = 0; static int scrollback_max = 0; static int scrollback_current = 0; -static int update_var(int con, struct fb_info *info) -{ - if (con == ((struct fbcon_ops *)info->fbcon_par)->currcon) - return fb_pan_display(info, &info->var); - return 0; -} - /* * If no vc is existent yet, just set struct display */ @@ -1165,7 +1278,6 @@ static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *va struct display *p = &fb_display[unit]; struct display *t = &fb_display[fg_console]; - var->xoffset = var->yoffset = p->yscroll = 0; if (var_to_display(p, var, info)) return; @@ -1181,9 +1293,9 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, struct display *p = &fb_display[vc->vc_num], *t; struct vc_data **default_mode = vc->vc_display_fg; struct vc_data *svc = *default_mode; + struct fbcon_ops *ops = info->fbcon_par; int rows, cols, charcnt = 256; - var->xoffset = var->yoffset = p->yscroll = 0; if (var_to_display(p, var, info)) return; t = &fb_display[svc->vc_num]; @@ -1200,9 +1312,10 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, var->activate = FB_ACTIVATE_NOW; info->var.activate = var->activate; - info->var.yoffset = info->var.xoffset = 0; + var->yoffset = info->var.yoffset; + var->xoffset = info->var.xoffset; fb_set_var(info, var); - + ops->var = info->var; vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; if (charcnt == 256) { @@ -1218,38 +1331,32 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc, svc); - cols = var->xres / vc->vc_font.width; - rows = var->yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); + if (CON_IS_VISIBLE(vc)) { update_screen(vc); - if (softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - - if (l > 5) - softback_end = softback_buf + l * - vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 - would screw the operation totally */ - softback_top = 0; - } - } + if (softback_buf) + fbcon_update_softback(vc); } } static __inline__ void ywrap_up(struct vc_data *vc, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode |= FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode |= FB_VMODE_YWRAP; + ops->update_start(info); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; @@ -1259,15 +1366,16 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count) static __inline__ void ywrap_down(struct vc_data *vc, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode |= FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode |= FB_VMODE_YWRAP; + ops->update_start(info); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; @@ -1286,10 +1394,11 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) 0, 0, 0, vc->vc_rows, vc->vc_cols); p->yscroll -= p->vrows - vc->vc_rows; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1300,6 +1409,7 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int redraw = 0; @@ -1309,12 +1419,13 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) redraw = 1; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; if (redraw) fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t); - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1334,10 +1445,11 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) 0, vc->vc_rows, vc->vc_cols); p->yscroll += p->vrows - vc->vc_rows; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1348,6 +1460,7 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int redraw = 0; @@ -1356,12 +1469,14 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) p->yscroll += p->vrows - vc->vc_rows; redraw = 1; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; + if (redraw) fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count); - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1835,31 +1950,41 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s height, width); } -static __inline__ void updatescrollmode(struct display *p, struct fb_info *info, +static __inline__ void updatescrollmode(struct display *p, + struct fb_info *info, struct vc_data *vc) { + struct fbcon_ops *ops = info->fbcon_par; int fh = vc->vc_font.height; int cap = info->flags; - int good_pan = (cap & FBINFO_HWACCEL_YPAN) - && divides(info->fix.ypanstep, vc->vc_font.height) - && info->var.yres_virtual > info->var.yres; - int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) - && divides(info->fix.ywrapstep, vc->vc_font.height) - && divides(vc->vc_font.height, info->var.yres_virtual); + u16 t = 0; + int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep, + info->fix.xpanstep); + int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t); + int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual, + info->var.xres_virtual); + int good_pan = (cap & FBINFO_HWACCEL_YPAN) && + divides(ypan, vc->vc_font.height) && vyres > yres; + int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) && + divides(ywrap, vc->vc_font.height) && + divides(vc->vc_font.height, vyres); int reading_fast = cap & FBINFO_READS_FAST; - int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED); - int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && !(cap & FBINFO_HWACCEL_DISABLED); - - p->vrows = info->var.yres_virtual/fh; - if (info->var.yres > (fh * (vc->vc_rows + 1))) - p->vrows -= (info->var.yres - (fh * vc->vc_rows)) / fh; - if ((info->var.yres % fh) && (info->var.yres_virtual % fh < - info->var.yres % fh)) + int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && + !(cap & FBINFO_HWACCEL_DISABLED); + int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && + !(cap & FBINFO_HWACCEL_DISABLED); + + p->vrows = vyres/fh; + if (yres > (fh * (vc->vc_rows + 1))) + p->vrows -= (yres - (fh * vc->vc_rows)) / fh; + if ((yres % fh) && (vyres % fh < yres % fh)) p->vrows--; if (good_wrap || good_pan) { if (reading_fast || fast_copyarea) - p->scrollmode = good_wrap ? SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; + p->scrollmode = good_wrap ? + SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; else p->scrollmode = good_wrap ? SCROLL_REDRAW : SCROLL_PAN_REDRAW; @@ -1875,41 +2000,34 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, unsigned int height) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var = info->var; - int x_diff, y_diff; - int fw = vc->vc_font.width; - int fh = vc->vc_font.height; - - var.xres = width * fw; - var.yres = height * fh; + int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; + + virt_w = FBCON_SWAP(ops->rotate, width, height); + virt_h = FBCON_SWAP(ops->rotate, height, width); + virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width, + vc->vc_font.height); + virt_fh = FBCON_SWAP(ops->rotate, vc->vc_font.height, + vc->vc_font.width); + var.xres = virt_w * virt_fw; + var.yres = virt_h * virt_fh; x_diff = info->var.xres - var.xres; y_diff = info->var.yres - var.yres; - if (x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh)) { + if (x_diff < 0 || x_diff > virt_fw || + y_diff < 0 || y_diff > virt_fh) { struct fb_videomode *mode; DPRINTK("attempting resize %ix%i\n", var.xres, var.yres); mode = fb_find_best_mode(&var, &info->modelist); if (mode == NULL) return -EINVAL; + display_to_var(&var, p); fb_videomode_to_var(&var, mode); - if (width > var.xres/fw || height > var.yres/fh) + + if (virt_w > var.xres/virt_fw || virt_h > var.yres/virt_fh) return -EINVAL; - /* - * The following can probably have any value... Do we need to - * set all of them? - */ - var.bits_per_pixel = p->bits_per_pixel; - var.xres_virtual = p->xres_virtual; - var.yres_virtual = p->yres_virtual; - var.accel_flags = p->accel_flags; - var.width = p->width; - var.height = p->height; - var.red = p->red; - var.green = p->green; - var.blue = p->blue; - var.transp = p->transp; - var.nonstd = p->nonstd; DPRINTK("resize now %ix%i\n", var.xres, var.yres); if (CON_IS_VISIBLE(vc)) { @@ -1918,6 +2036,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, fb_set_var(info, &var); } var_to_display(p, &info->var, info); + ops->var = info->var; } updatescrollmode(p, info, vc); return 0; @@ -1926,26 +2045,20 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, static int fbcon_switch(struct vc_data *vc) { struct fb_info *info, *old_info = NULL; + struct fbcon_ops *ops; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var; int i, prev_console; info = registered_fb[con2fb_map[vc->vc_num]]; + ops = info->fbcon_par; if (softback_top) { - int l = fbcon_softback_size / vc->vc_size_row; if (softback_lines) fbcon_set_origin(vc); softback_top = softback_curr = softback_in = softback_buf; softback_lines = 0; - - if (l > 5) - softback_end = softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 would screw - the operation totally */ - softback_top = 0; - } + fbcon_update_softback(vc); } if (logo_shown >= 0) { @@ -1957,7 +2070,7 @@ static int fbcon_switch(struct vc_data *vc) logo_shown = FBCON_LOGO_CANSHOW; } - prev_console = ((struct fbcon_ops *)info->fbcon_par)->currcon; + prev_console = ops->currcon; if (prev_console != -1) old_info = registered_fb[con2fb_map[prev_console]]; /* @@ -1970,9 +2083,9 @@ static int fbcon_switch(struct vc_data *vc) */ for (i = 0; i < FB_MAX; i++) { if (registered_fb[i] != NULL && registered_fb[i]->fbcon_par) { - struct fbcon_ops *ops = registered_fb[i]->fbcon_par; + struct fbcon_ops *o = registered_fb[i]->fbcon_par; - ops->currcon = vc->vc_num; + o->currcon = vc->vc_num; } } memset(&var, 0, sizeof(struct fb_var_screeninfo)); @@ -1984,8 +2097,11 @@ static int fbcon_switch(struct vc_data *vc) * in fb_set_var() */ info->var.activate = var.activate; - info->var.yoffset = info->var.xoffset = p->yscroll = 0; + var.yoffset = info->var.yoffset; + var.xoffset = info->var.xoffset; + var.vmode = info->var.vmode; fb_set_var(info, &var); + ops->var = info->var; if (old_info != NULL && old_info != info) { if (info->fbops->fb_set_par) @@ -1995,7 +2111,12 @@ static int fbcon_switch(struct vc_data *vc) } set_blitting_type(vc, info, p); - ((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1; + ops->cursor_reset = 1; + + if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + ops->rotate = FB_ROTATE_UR; + set_blitting_type(vc, info, p); + } vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; @@ -2015,10 +2136,11 @@ static int fbcon_switch(struct vc_data *vc) scrollback_phys_max = 0; break; } + scrollback_max = 0; scrollback_current = 0; - - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); fbcon_clear_margins(vc, 0); @@ -2026,7 +2148,7 @@ static int fbcon_switch(struct vc_data *vc) logo_shown = fg_console; /* This is protected above by initmem_freed */ - fb_show_logo(info); + fb_show_logo(info, ops->rotate); update_region(vc, vc->vc_origin + vc->vc_size_row * vc->vc_top, vc->vc_size_row * (vc->vc_bottom - @@ -2065,6 +2187,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; fb_set_var(info, &var); ops->graphics = 0; + ops->var = info->var; } } @@ -2153,6 +2276,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, const u8 * data, int userfont) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int resize; int cnt; @@ -2232,20 +2356,15 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, } if (resize) { - /* reset wrap/pan */ - info->var.xoffset = info->var.yoffset = p->yscroll = 0; - vc_resize(vc, info->var.xres / w, info->var.yres / h); - if (CON_IS_VISIBLE(vc) && softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - if (l > 5) - softback_end = - softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 would screw - the operation totally */ - softback_top = 0; - } - } + int cols, rows; + + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= w; + rows /= h; + vc_resize(vc, cols, rows); + if (CON_IS_VISIBLE(vc) && softback_buf) + fbcon_update_softback(vc); } else if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) { fbcon_clear_margins(vc, 0); @@ -2471,6 +2590,7 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt) static int fbcon_scrolldelta(struct vc_data *vc, int lines) { struct fb_info *info = registered_fb[con2fb_map[fg_console]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[fg_console]; int offset, limit, scrollback_old; @@ -2547,9 +2667,11 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) offset += limit; else if (offset >= limit) offset -= limit; - info->var.xoffset = 0; - info->var.yoffset = offset * vc->vc_font.height; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = offset * vc->vc_font.height; + ops->update_start(info); + if (!scrollback_current) fbcon_cursor(vc, CM_DRAW); return 0; @@ -2597,34 +2719,29 @@ static void fbcon_modechanged(struct fb_info *info) if (!ops || ops->currcon < 0) return; vc = vc_cons[ops->currcon].d; - if (vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[ops->currcon]] != info) + if (vc->vc_mode != KD_TEXT || + registered_fb[con2fb_map[ops->currcon]] != info) return; p = &fb_display[vc->vc_num]; - - info->var.xoffset = info->var.yoffset = p->yscroll = 0; + set_blitting_type(vc, info, p); if (CON_IS_VISIBLE(vc)) { var_to_display(p, &info->var, info); - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); updatescrollmode(p, info, vc); scrollback_max = 0; scrollback_current = 0; - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); update_screen(vc); - if (softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - if (l > 5) - softback_end = softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 - would screw the operation totally */ - softback_top = 0; - } - } + if (softback_buf) + fbcon_update_softback(vc); } } @@ -2645,30 +2762,24 @@ static void fbcon_set_all_vcs(struct fb_info *info) continue; p = &fb_display[vc->vc_num]; - - info->var.xoffset = info->var.yoffset = p->yscroll = 0; + set_blitting_type(vc, info, p); var_to_display(p, &info->var, info); - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); if (CON_IS_VISIBLE(vc)) { updatescrollmode(p, info, vc); scrollback_max = 0; scrollback_current = 0; - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); update_screen(vc); - if (softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - if (l > 5) - softback_end = softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 - would screw the operation totally */ - softback_top = 0; - } - } + if (softback_buf) + fbcon_update_softback(vc); } } } @@ -2758,7 +2869,8 @@ static void fbcon_new_modelist(struct fb_info *info) continue; vc = vc_cons[i].d; display_to_var(&var, &fb_display[i]); - mode = fb_find_nearest_mode(&var, &info->modelist); + mode = fb_find_nearest_mode(fb_display[i].mode, + &info->modelist); fb_videomode_to_var(&var, mode); if (vc) @@ -2813,6 +2925,14 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_NEW_MODELIST: fbcon_new_modelist(info); break; + case FB_EVENT_SET_CON_ROTATE: + fbcon_rotate(info, *(int *)event->data); + break; + case FB_EVENT_GET_CON_ROTATE: + ret = fbcon_get_rotate(info); + break; + case FB_EVENT_SET_CON_ROTATE_ALL: + fbcon_rotate_all(info, *(int *)event->data); } return ret; diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 0738cd62def..6892e7ff34d 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -27,15 +27,15 @@ */ struct display { - /* Filled in by the frame buffer device */ - u_short inverse; /* != 0 text black on white as default */ /* Filled in by the low-level console driver */ const u_char *fontdata; int userfont; /* != 0 if fontdata kmalloc()ed */ u_short scrollmode; /* Scroll Method */ + u_short inverse; /* != 0 text black on white as default */ short yscroll; /* Hardware scrolling */ int vrows; /* number of virtual rows */ int cursor_shape; + int con_rotate; u32 xres_virtual; u32 yres_virtual; u32 height; @@ -63,17 +63,27 @@ struct fbcon_ops { void (*clear_margins)(struct vc_data *vc, struct fb_info *info, int bottom_only); void (*cursor)(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, int fg, int bg); - + struct display *p, int mode, int softback_lines, + int fg, int bg); + int (*update_start)(struct fb_info *info); + int (*rotate_font)(struct fb_info *info, struct vc_data *vc, + struct display *p); + struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ struct timer_list cursor_timer; /* Cursor timer */ struct fb_cursor cursor_state; + struct display *p; int currcon; /* Current VC. */ int cursor_flash; int cursor_reset; int blank_state; int graphics; int flags; + int rotate; + int cur_rotate; char *cursor_data; + u8 *fontbuffer; + u8 *fontdata; + u32 fd_size; }; /* * Attribute Decoding @@ -167,5 +177,48 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, struct display *p, struct fbcon_ops *ops); #endif extern void fbcon_set_bitops(struct fbcon_ops *ops); +extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); + +#define FBCON_ATTRIBUTE_UNDERLINE 1 +#define FBCON_ATTRIBUTE_REVERSE 2 +#define FBCON_ATTRIBUTE_BOLD 4 + +static inline int real_y(struct display *p, int ypos) +{ + int rows = p->vrows; + + ypos += p->yscroll; + return ypos < rows ? ypos : ypos - rows; +} + + +static inline int get_attribute(struct fb_info *info, u16 c) +{ + int attribute = 0; + + if (fb_get_color_depth(&info->var, &info->fix) == 1) { + if (attr_underline(c)) + attribute |= FBCON_ATTRIBUTE_UNDERLINE; + if (attr_reverse(c)) + attribute |= FBCON_ATTRIBUTE_REVERSE; + if (attr_bold(c)) + attribute |= FBCON_ATTRIBUTE_BOLD; + } + + return attribute; +} + +#define FBCON_SWAP(i,r,v) ({ \ + typeof(r) _r = (r); \ + typeof(v) _v = (v); \ + (void) (&_r == &_v); \ + (i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; }) + +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION +extern void fbcon_set_rotate(struct fbcon_ops *ops); +#else +#define fbcon_set_rotate(x) do {} while(0) +#endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ #endif /* _VIDEO_FBCON_H */ + diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c new file mode 100644 index 00000000000..4952b66ae20 --- /dev/null +++ b/drivers/video/console/fbcon_ccw.c @@ -0,0 +1,426 @@ +/* + * linux/drivers/video/console/fbcon_ccw.c -- Software Rotation - 270 degrees + * + * Copyright (C) 2005 Antonino Daplas <adaplas @pol.net> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/fb.h> +#include <linux/vt_kern.h> +#include <linux/console.h> +#include <asm/types.h> +#include "fbcon.h" +#include "fbcon_rotate.h" + +/* + * Rotation 270 degrees + */ + +static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute, + struct vc_data *vc) +{ + int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; + int width = (vc->vc_font.height + 7) >> 3; + int mod = vc->vc_font.height % 8; + u8 c, msk = ~(0xff << offset), msk1 = 0; + + if (mod) + msk <<= (8 - mod); + + if (offset > mod) + msk1 |= 0x01; + + for (i = 0; i < vc->vc_font.width; i++) { + for (j = 0; j < width; j++) { + c = *src; + + if (attribute & FBCON_ATTRIBUTE_UNDERLINE) { + if (j == width - 1) + c |= msk; + + if (msk1 && j == width - 2) + c |= msk1; + } + + if (attribute & FBCON_ATTRIBUTE_BOLD && i) + *(dst - width) |= c; + + if (attribute & FBCON_ATTRIBUTE_REVERSE) + c = ~c; + src++; + *dst++ = c; + } + } +} + + +static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int dy, int dx, int height, int width) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct fb_copyarea area; + u32 vyres = GETVYRES(ops->p->scrollmode, info); + + area.sx = sy * vc->vc_font.height; + area.sy = vyres - ((sx + width) * vc->vc_font.width); + area.dx = dy * vc->vc_font.height; + area.dy = vyres - ((dx + width) * vc->vc_font.width); + area.width = height * vc->vc_font.height; + area.height = width * vc->vc_font.width; + + info->fbops->fb_copyarea(info, &area); +} + +static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int height, int width) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vyres = GETVYRES(ops->p->scrollmode, info); + + region.color = attr_bgcol_ec(bgshift,vc); + region.dx = sy * vc->vc_font.height; + region.dy = vyres - ((sx + width) * vc->vc_font.width); + region.height = width * vc->vc_font.width; + region.width = height * vc->vc_font.height; + region.rop = ROP_COPY; + + info->fbops->fb_fillrect(info, ®ion); +} + +static inline void ccw_putcs_aligned(struct vc_data *vc, struct fb_info *info, + const u16 *s, u32 attr, u32 cnt, + u32 d_pitch, u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, u8 *dst) +{ + struct fbcon_ops *ops = info->fbcon_par; + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + u32 idx = (vc->vc_font.height + 7) >> 3; + u8 *src; + + while (cnt--) { + src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; + + if (attr) { + ccw_update_attr(buf, src, attr, vc); + src = buf; + } + + if (likely(idx == 1)) + __fb_pad_aligned_buffer(dst, d_pitch, src, idx, + vc->vc_font.width); + else + fb_pad_aligned_buffer(dst, d_pitch, src, idx, + vc->vc_font.width); + + dst += d_pitch * vc->vc_font.width; + } + + info->fbops->fb_imageblit(info, image); +} + +static void ccw_putcs(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx, + int fg, int bg) +{ + struct fb_image image; + struct fbcon_ops *ops = info->fbcon_par; + u32 width = (vc->vc_font.height + 7)/8; + u32 cellsize = width * vc->vc_font.width; + u32 maxcnt = info->pixmap.size/cellsize; + u32 scan_align = info->pixmap.scan_align - 1; + u32 buf_align = info->pixmap.buf_align - 1; + u32 cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; + u32 vyres = GETVYRES(ops->p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + image.fg_color = fg; + image.bg_color = bg; + image.dx = yy * vc->vc_font.height; + image.dy = vyres - ((xx + count) * vc->vc_font.width); + image.width = vc->vc_font.height; + image.depth = 1; + + if (attribute) { + buf = kmalloc(cellsize, GFP_KERNEL); + if (!buf) + return; + } + + s += count - 1; + + while (count) { + if (count > maxcnt) + cnt = maxcnt; + else + cnt = count; + + image.height = vc->vc_font.width * cnt; + pitch = ((image.width + 7) >> 3) + scan_align; + pitch &= ~scan_align; + size = pitch * image.height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + image.data = dst; + ccw_putcs_aligned(vc, info, s, attribute, cnt, pitch, + width, cellsize, &image, buf, dst); + image.dy += image.height; + count -= cnt; + s -= cnt; + } + + /* buf is always NULL except when in monochrome mode, so in this case + it's a gain to check buf against NULL even though kfree() handles + NULL pointers just fine */ + if (unlikely(buf)) + kfree(buf); + +} + +static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, + int bottom_only) +{ + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.yres - (vc->vc_cols*cw); + unsigned int bh = info->var.xres - (vc->vc_rows*ch); + unsigned int bs = vc->vc_rows*ch; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + + region.color = attr_bgcol_ec(bgshift,vc); + region.rop = ROP_COPY; + + if (rw && !bottom_only) { + region.dx = 0; + region.dy = info->var.yoffset; + region.height = rw; + region.width = info->var.xres_virtual; + info->fbops->fb_fillrect(info, ®ion); + } + + if (bh) { + region.dx = info->var.xoffset + bs; + region.dy = 0; + region.height = info->var.yres_virtual; + region.width = bh; + info->fbops->fb_fillrect(info, ®ion); + } +} + +static void ccw_cursor(struct vc_data *vc, struct fb_info *info, + struct display *p, int mode, int softback_lines, + int fg, int bg) +{ + struct fb_cursor cursor; + struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + int w = (vc->vc_font.height + 7) >> 3, c; + int y = real_y(p, vc->vc_y); + int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1, dx, dy; + char *src; + u32 vyres = GETVYRES(p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + cursor.set = 0; + + if (softback_lines) { + if (y + softback_lines >= vc->vc_rows) { + mode = CM_ERASE; + ops->cursor_flash = 0; + return; + } else + y += softback_lines; + } + + c = scr_readw((u16 *) vc->vc_pos); + attribute = get_attribute(info, c); + src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + + if (ops->cursor_state.image.data != src || + ops->cursor_reset) { + ops->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; + } + + if (attribute) { + u8 *dst; + + dst = kmalloc(w * vc->vc_font.width, GFP_ATOMIC); + if (!dst) + return; + kfree(ops->cursor_data); + ops->cursor_data = dst; + ccw_update_attr(dst, src, attribute, vc); + src = dst; + } + + if (ops->cursor_state.image.fg_color != fg || + ops->cursor_state.image.bg_color != bg || + ops->cursor_reset) { + ops->cursor_state.image.fg_color = fg; + ops->cursor_state.image.bg_color = bg; + cursor.set |= FB_CUR_SETCMAP; + } + + if (ops->cursor_state.image.height != vc->vc_font.width || + ops->cursor_state.image.width != vc->vc_font.height || + ops->cursor_reset) { + ops->cursor_state.image.height = vc->vc_font.width; + ops->cursor_state.image.width = vc->vc_font.height; + cursor.set |= FB_CUR_SETSIZE; + } + + dx = y * vc->vc_font.height; + dy = vyres - ((vc->vc_x + 1) * vc->vc_font.width); + + if (ops->cursor_state.image.dx != dx || + ops->cursor_state.image.dy != dy || + ops->cursor_reset) { + ops->cursor_state.image.dx = dx; + ops->cursor_state.image.dy = dy; + cursor.set |= FB_CUR_SETPOS; + } + + if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || + ops->cursor_reset) { + ops->cursor_state.hot.x = cursor.hot.y = 0; + cursor.set |= FB_CUR_SETHOT; + } + + if (cursor.set & FB_CUR_SETSIZE || + vc->vc_cursor_type != p->cursor_shape || + ops->cursor_state.mask == NULL || + ops->cursor_reset) { + char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC); + int cur_height, size, i = 0; + int width = (vc->vc_font.width + 7)/8; + + if (!mask) + return; + + tmp = kmalloc(width * vc->vc_font.height, GFP_ATOMIC); + + if (!tmp) { + kfree(mask); + return; + } + + kfree(ops->cursor_state.mask); + ops->cursor_state.mask = mask; + + p->cursor_shape = vc->vc_cursor_type; + cursor.set |= FB_CUR_SETSHAPE; + + switch (p->cursor_shape & CUR_HWMASK) { + case CUR_NONE: + cur_height = 0; + break; + case CUR_UNDERLINE: + cur_height = (vc->vc_font.height < 10) ? 1 : 2; + break; + case CUR_LOWER_THIRD: + cur_height = vc->vc_font.height/3; + break; + case CUR_LOWER_HALF: + cur_height = vc->vc_font.height >> 1; + break; + case CUR_TWO_THIRDS: + cur_height = (vc->vc_font.height << 1)/3; + break; + case CUR_BLOCK: + default: + cur_height = vc->vc_font.height; + break; + } + + size = (vc->vc_font.height - cur_height) * width; + while (size--) + tmp[i++] = 0; + size = cur_height * width; + while (size--) + tmp[i++] = 0xff; + memset(mask, 0, w * vc->vc_font.width); + rotate_ccw(tmp, mask, vc->vc_font.width, vc->vc_font.height); + kfree(tmp); + } + + switch (mode) { + case CM_ERASE: + ops->cursor_state.enable = 0; + break; + case CM_DRAW: + case CM_MOVE: + default: + ops->cursor_state.enable = (use_sw) ? 0 : 1; + break; + } + + cursor.image.data = src; + cursor.image.fg_color = ops->cursor_state.image.fg_color; + cursor.image.bg_color = ops->cursor_state.image.bg_color; + cursor.image.dx = ops->cursor_state.image.dx; + cursor.image.dy = ops->cursor_state.image.dy; + cursor.image.height = ops->cursor_state.image.height; + cursor.image.width = ops->cursor_state.image.width; + cursor.hot.x = ops->cursor_state.hot.x; + cursor.hot.y = ops->cursor_state.hot.y; + cursor.mask = ops->cursor_state.mask; + cursor.enable = ops->cursor_state.enable; + cursor.image.depth = 1; + cursor.rop = ROP_XOR; + + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); + + ops->cursor_reset = 0; +} + +int ccw_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + u32 yoffset; + u32 vyres = GETVYRES(ops->p->scrollmode, info); + int err; + + yoffset = (vyres - info->var.yres) - ops->var.xoffset; + ops->var.xoffset = ops->var.yoffset; + ops->var.yoffset = yoffset; + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + +void fbcon_rotate_ccw(struct fbcon_ops *ops) +{ + ops->bmove = ccw_bmove; + ops->clear = ccw_clear; + ops->putcs = ccw_putcs; + ops->clear_margins = ccw_clear_margins; + ops->cursor = ccw_cursor; + ops->update_start = ccw_update_start; +} +EXPORT_SYMBOL(fbcon_rotate_ccw); + +MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); +MODULE_DESCRIPTION("Console Rotation (270 degrees) Support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c new file mode 100644 index 00000000000..6d92b845620 --- /dev/null +++ b/drivers/video/console/fbcon_cw.c @@ -0,0 +1,410 @@ +/* + * linux/drivers/video/console/fbcon_ud.c -- Software Rotation - 90 degrees + * + * Copyright (C) 2005 Antonino Daplas <adaplas @pol.net> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/fb.h> +#include <linux/vt_kern.h> +#include <linux/console.h> +#include <asm/types.h> +#include "fbcon.h" +#include "fbcon_rotate.h" + +/* + * Rotation 90 degrees + */ + +static inline void cw_update_attr(u8 *dst, u8 *src, int attribute, + struct vc_data *vc) +{ + int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; + int width = (vc->vc_font.height + 7) >> 3; + u8 c, t = 0, msk = ~(0xff >> offset); + + for (i = 0; i < vc->vc_font.width; i++) { + for (j = 0; j < width; j++) { + c = *src; + if (attribute & FBCON_ATTRIBUTE_UNDERLINE && !j) + c |= msk; + if (attribute & FBCON_ATTRIBUTE_BOLD && i) + c |= *(src-width); + if (attribute & FBCON_ATTRIBUTE_REVERSE) + c = ~c; + src++; + *dst++ = c; + t = c; + } + } +} + + +static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int dy, int dx, int height, int width) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct fb_copyarea area; + u32 vxres = GETVXRES(ops->p->scrollmode, info); + + area.sx = vxres - ((sy + height) * vc->vc_font.height); + area.sy = sx * vc->vc_font.width; + area.dx = vxres - ((dy + height) * vc->vc_font.height); + area.dy = dx * vc->vc_font.width; + area.width = height * vc->vc_font.height; + area.height = width * vc->vc_font.width; + + info->fbops->fb_copyarea(info, &area); +} + +static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int height, int width) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vxres = GETVXRES(ops->p->scrollmode, info); + + region.color = attr_bgcol_ec(bgshift,vc); + region.dx = vxres - ((sy + height) * vc->vc_font.height); + region.dy = sx * vc->vc_font.width; + region.height = width * vc->vc_font.width; + region.width = height * vc->vc_font.height; + region.rop = ROP_COPY; + + info->fbops->fb_fillrect(info, ®ion); +} + +static inline void cw_putcs_aligned(struct vc_data *vc, struct fb_info *info, + const u16 *s, u32 attr, u32 cnt, + u32 d_pitch, u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, u8 *dst) +{ + struct fbcon_ops *ops = info->fbcon_par; + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + u32 idx = (vc->vc_font.height + 7) >> 3; + u8 *src; + + while (cnt--) { + src = ops->fontbuffer + (scr_readw(s++) & charmask)*cellsize; + + if (attr) { + cw_update_attr(buf, src, attr, vc); + src = buf; + } + + if (likely(idx == 1)) + __fb_pad_aligned_buffer(dst, d_pitch, src, idx, + vc->vc_font.width); + else + fb_pad_aligned_buffer(dst, d_pitch, src, idx, + vc->vc_font.width); + + dst += d_pitch * vc->vc_font.width; + } + + info->fbops->fb_imageblit(info, image); +} + +static void cw_putcs(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx, + int fg, int bg) +{ + struct fb_image image; + struct fbcon_ops *ops = info->fbcon_par; + u32 width = (vc->vc_font.height + 7)/8; + u32 cellsize = width * vc->vc_font.width; + u32 maxcnt = info->pixmap.size/cellsize; + u32 scan_align = info->pixmap.scan_align - 1; + u32 buf_align = info->pixmap.buf_align - 1; + u32 cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; + u32 vxres = GETVXRES(ops->p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + image.fg_color = fg; + image.bg_color = bg; + image.dx = vxres - ((yy + 1) * vc->vc_font.height); + image.dy = xx * vc->vc_font.width; + image.width = vc->vc_font.height; + image.depth = 1; + + if (attribute) { + buf = kmalloc(cellsize, GFP_KERNEL); + if (!buf) + return; + } + + while (count) { + if (count > maxcnt) + cnt = maxcnt; + else + cnt = count; + + image.height = vc->vc_font.width * cnt; + pitch = ((image.width + 7) >> 3) + scan_align; + pitch &= ~scan_align; + size = pitch * image.height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + image.data = dst; + cw_putcs_aligned(vc, info, s, attribute, cnt, pitch, + width, cellsize, &image, buf, dst); + image.dy += image.height; + count -= cnt; + s += cnt; + } + + /* buf is always NULL except when in monochrome mode, so in this case + it's a gain to check buf against NULL even though kfree() handles + NULL pointers just fine */ + if (unlikely(buf)) + kfree(buf); + +} + +static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, + int bottom_only) +{ + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.yres - (vc->vc_cols*cw); + unsigned int bh = info->var.xres - (vc->vc_rows*ch); + unsigned int rs = info->var.yres - rw; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + + region.color = attr_bgcol_ec(bgshift,vc); + region.rop = ROP_COPY; + + if (rw && !bottom_only) { + region.dx = 0; + region.dy = info->var.yoffset + rs; + region.height = rw; + region.width = info->var.xres_virtual; + info->fbops->fb_fillrect(info, ®ion); + } + + if (bh) { + region.dx = info->var.xoffset; + region.dy = info->var.yoffset; + region.height = info->var.yres; + region.width = bh; + info->fbops->fb_fillrect(info, ®ion); + } +} + +static void cw_cursor(struct vc_data *vc, struct fb_info *info, + struct display *p, int mode, int softback_lines, + int fg, int bg) +{ + struct fb_cursor cursor; + struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + int w = (vc->vc_font.height + 7) >> 3, c; + int y = real_y(p, vc->vc_y); + int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1, dx, dy; + char *src; + u32 vxres = GETVXRES(p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + cursor.set = 0; + + if (softback_lines) { + if (y + softback_lines >= vc->vc_rows) { + mode = CM_ERASE; + ops->cursor_flash = 0; + return; + } else + y += softback_lines; + } + + c = scr_readw((u16 *) vc->vc_pos); + attribute = get_attribute(info, c); + src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + + if (ops->cursor_state.image.data != src || + ops->cursor_reset) { + ops->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; + } + + if (attribute) { + u8 *dst; + + dst = kmalloc(w * vc->vc_font.width, GFP_ATOMIC); + if (!dst) + return; + kfree(ops->cursor_data); + ops->cursor_data = dst; + cw_update_attr(dst, src, attribute, vc); + src = dst; + } + + if (ops->cursor_state.image.fg_color != fg || + ops->cursor_state.image.bg_color != bg || + ops->cursor_reset) { + ops->cursor_state.image.fg_color = fg; + ops->cursor_state.image.bg_color = bg; + cursor.set |= FB_CUR_SETCMAP; + } + + if (ops->cursor_state.image.height != vc->vc_font.width || + ops->cursor_state.image.width != vc->vc_font.height || + ops->cursor_reset) { + ops->cursor_state.image.height = vc->vc_font.width; + ops->cursor_state.image.width = vc->vc_font.height; + cursor.set |= FB_CUR_SETSIZE; + } + + dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height); + dy = vc->vc_x * vc->vc_font.width; + + if (ops->cursor_state.image.dx != dx || + ops->cursor_state.image.dy != dy || + ops->cursor_reset) { + ops->cursor_state.image.dx = dx; + ops->cursor_state.image.dy = dy; + cursor.set |= FB_CUR_SETPOS; + } + + if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || + ops->cursor_reset) { + ops->cursor_state.hot.x = cursor.hot.y = 0; + cursor.set |= FB_CUR_SETHOT; + } + + if (cursor.set & FB_CUR_SETSIZE || + vc->vc_cursor_type != p->cursor_shape || + ops->cursor_state.mask == NULL || + ops->cursor_reset) { + char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC); + int cur_height, size, i = 0; + int width = (vc->vc_font.width + 7)/8; + + if (!mask) + return; + + tmp = kmalloc(width * vc->vc_font.height, GFP_ATOMIC); + + if (!tmp) { + kfree(mask); + return; + } + + kfree(ops->cursor_state.mask); + ops->cursor_state.mask = mask; + + p->cursor_shape = vc->vc_cursor_type; + cursor.set |= FB_CUR_SETSHAPE; + + switch (p->cursor_shape & CUR_HWMASK) { + case CUR_NONE: + cur_height = 0; + break; + case CUR_UNDERLINE: + cur_height = (vc->vc_font.height < 10) ? 1 : 2; + break; + case CUR_LOWER_THIRD: + cur_height = vc->vc_font.height/3; + break; + case CUR_LOWER_HALF: + cur_height = vc->vc_font.height >> 1; + break; + case CUR_TWO_THIRDS: + cur_height = (vc->vc_font.height << 1)/3; + break; + case CUR_BLOCK: + default: + cur_height = vc->vc_font.height; + break; + } + + size = (vc->vc_font.height - cur_height) * width; + while (size--) + tmp[i++] = 0; + size = cur_height * width; + while (size--) + tmp[i++] = 0xff; + memset(mask, 0, w * vc->vc_font.width); + rotate_cw(tmp, mask, vc->vc_font.width, vc->vc_font.height); + kfree(tmp); + } + + switch (mode) { + case CM_ERASE: + ops->cursor_state.enable = 0; + break; + case CM_DRAW: + case CM_MOVE: + default: + ops->cursor_state.enable = (use_sw) ? 0 : 1; + break; + } + + cursor.image.data = src; + cursor.image.fg_color = ops->cursor_state.image.fg_color; + cursor.image.bg_color = ops->cursor_state.image.bg_color; + cursor.image.dx = ops->cursor_state.image.dx; + cursor.image.dy = ops->cursor_state.image.dy; + cursor.image.height = ops->cursor_state.image.height; + cursor.image.width = ops->cursor_state.image.width; + cursor.hot.x = ops->cursor_state.hot.x; + cursor.hot.y = ops->cursor_state.hot.y; + cursor.mask = ops->cursor_state.mask; + cursor.enable = ops->cursor_state.enable; + cursor.image.depth = 1; + cursor.rop = ROP_XOR; + + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); + + ops->cursor_reset = 0; +} + +int cw_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + u32 vxres = GETVXRES(ops->p->scrollmode, info); + u32 xoffset; + int err; + + xoffset = vxres - (info->var.xres + ops->var.yoffset); + ops->var.yoffset = ops->var.xoffset; + ops->var.xoffset = xoffset; + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + +void fbcon_rotate_cw(struct fbcon_ops *ops) +{ + ops->bmove = cw_bmove; + ops->clear = cw_clear; + ops->putcs = cw_putcs; + ops->clear_margins = cw_clear_margins; + ops->cursor = cw_cursor; + ops->update_start = cw_update_start; +} +EXPORT_SYMBOL(fbcon_rotate_cw); + +MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); +MODULE_DESCRIPTION("Console Rotation (90 degrees) Support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c new file mode 100644 index 00000000000..ec0dd8fe241 --- /dev/null +++ b/drivers/video/console/fbcon_rotate.c @@ -0,0 +1,117 @@ +/* + * linux/drivers/video/console/fbcon_rotate.c -- Software Rotation + * + * Copyright (C) 2005 Antonino Daplas <adaplas @pol.net> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/fb.h> +#include <linux/vt_kern.h> +#include <linux/console.h> +#include <asm/types.h> +#include "fbcon.h" +#include "fbcon_rotate.h" + +static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc, + struct display *p) +{ + struct fbcon_ops *ops = info->fbcon_par; + int len, err = 0; + int s_cellsize, d_cellsize, i; + const u8 *src; + u8 *dst; + + if (vc->vc_font.data == ops->fontdata && + p->con_rotate == ops->cur_rotate) + goto finished; + + src = ops->fontdata = vc->vc_font.data; + ops->cur_rotate = p->con_rotate; + len = (!p->userfont) ? 256 : FNTCHARCNT(src); + s_cellsize = ((vc->vc_font.width + 7)/8) * + vc->vc_font.height; + d_cellsize = s_cellsize; + + if (ops->rotate == FB_ROTATE_CW || + ops->rotate == FB_ROTATE_CCW) + d_cellsize = ((vc->vc_font.height + 7)/8) * + vc->vc_font.width; + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + if (ops->fd_size < d_cellsize * len) { + dst = kmalloc(d_cellsize * len, GFP_KERNEL); + + if (dst == NULL) { + err = -ENOMEM; + goto finished; + } + + ops->fd_size = d_cellsize * len; + kfree(ops->fontbuffer); + ops->fontbuffer = dst; + } + + dst = ops->fontbuffer; + memset(dst, 0, ops->fd_size); + + switch (ops->rotate) { + case FB_ROTATE_UD: + for (i = len; i--; ) { + rotate_ud(src, dst, vc->vc_font.width, + vc->vc_font.height); + + src += s_cellsize; + dst += d_cellsize; + } + break; + case FB_ROTATE_CW: + for (i = len; i--; ) { + rotate_cw(src, dst, vc->vc_font.width, + vc->vc_font.height); + src += s_cellsize; + dst += d_cellsize; + } + break; + case FB_ROTATE_CCW: + for (i = len; i--; ) { + rotate_ccw(src, dst, vc->vc_font.width, + vc->vc_font.height); + src += s_cellsize; + dst += d_cellsize; + } + break; + } + +finished: + return err; +} + +void fbcon_set_rotate(struct fbcon_ops *ops) +{ + ops->rotate_font = fbcon_rotate_font; + + switch(ops->rotate) { + case FB_ROTATE_CW: + fbcon_rotate_cw(ops); + break; + case FB_ROTATE_UD: + fbcon_rotate_ud(ops); + break; + case FB_ROTATE_CCW: + fbcon_rotate_ccw(ops); + break; + } +} +EXPORT_SYMBOL(fbcon_set_rotate); + +MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); +MODULE_DESCRIPTION("Console Rotation Support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h new file mode 100644 index 00000000000..1b8f92fdc6a --- /dev/null +++ b/drivers/video/console/fbcon_rotate.h @@ -0,0 +1,98 @@ +/* + * linux/drivers/video/console/fbcon_rotate.h -- Software Display Rotation + * + * Copyright (C) 2005 Antonino Daplas <adaplas@pol.net> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#ifndef _FBCON_ROTATE_H +#define _FBCON_ROTATE_H + +#define FNTCHARCNT(fd) (((int *)(fd))[-3]) + +#define GETVYRES(s,i) ({ \ + (s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \ + (i)->var.yres : (i)->var.yres_virtual; }) + +#define GETVXRES(s,i) ({ \ + (s == SCROLL_REDRAW || s == SCROLL_MOVE || !(i)->fix.xpanstep) ? \ + (i)->var.xres : (i)->var.xres_virtual; }) + + +static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat) +{ + u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8; + + pat +=index; + return (*pat) & (0x80 >> bit); +} + +static inline void pattern_set_bit(u32 x, u32 y, u32 pitch, char *pat) +{ + u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8; + + pat += index; + + (*pat) |= 0x80 >> bit; +} + +static inline void rotate_ud(const char *in, char *out, u32 width, u32 height) +{ + int i, j; + int shift = (8 - (width % 8)) & 7; + + width = (width + 7) & ~7; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + if (pattern_test_bit(j, i, width, in)) + pattern_set_bit(width - (1 + j + shift), + height - (1 + i), + width, out); + } + + } +} + +static inline void rotate_cw(const char *in, char *out, u32 width, u32 height) +{ + int i, j, h = height, w = width; + int shift = (8 - (height % 8)) & 7; + + width = (width + 7) & ~7; + height = (height + 7) & ~7; + + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + if (pattern_test_bit(j, i, width, in)) + pattern_set_bit(height - 1 - i - shift, j, + height, out); + + } + } +} + +static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height) +{ + int i, j, h = height, w = width; + int shift = (8 - (width % 8)) & 7; + + width = (width + 7) & ~7; + height = (height + 7) & ~7; + + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + if (pattern_test_bit(j, i, width, in)) + pattern_set_bit(i, width - 1 - j - shift, + height, out); + } + } +} + +extern void fbcon_rotate_cw(struct fbcon_ops *ops); +extern void fbcon_rotate_ud(struct fbcon_ops *ops); +extern void fbcon_rotate_ccw(struct fbcon_ops *ops); +#endif diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c new file mode 100644 index 00000000000..c4d7c89212b --- /dev/null +++ b/drivers/video/console/fbcon_ud.c @@ -0,0 +1,452 @@ +/* + * linux/drivers/video/console/fbcon_ud.c -- Software Rotation - 180 degrees + * + * Copyright (C) 2005 Antonino Daplas <adaplas @pol.net> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/fb.h> +#include <linux/vt_kern.h> +#include <linux/console.h> +#include <asm/types.h> +#include "fbcon.h" +#include "fbcon_rotate.h" + +/* + * Rotation 180 degrees + */ + +static inline void ud_update_attr(u8 *dst, u8 *src, int attribute, + struct vc_data *vc) +{ + int i, offset = (vc->vc_font.height < 10) ? 1 : 2; + int width = (vc->vc_font.width + 7) >> 3; + unsigned int cellsize = vc->vc_font.height * width; + u8 c; + + offset = offset * width; + + for (i = 0; i < cellsize; i++) { + c = src[i]; + if (attribute & FBCON_ATTRIBUTE_UNDERLINE && i < offset) + c = 0xff; + if (attribute & FBCON_ATTRIBUTE_BOLD) + c |= c << 1; + if (attribute & FBCON_ATTRIBUTE_REVERSE) + c = ~c; + dst[i] = c; + } +} + + +static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int dy, int dx, int height, int width) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct fb_copyarea area; + u32 vyres = GETVYRES(ops->p->scrollmode, info); + u32 vxres = GETVXRES(ops->p->scrollmode, info); + + area.sy = vyres - ((sy + height) * vc->vc_font.height); + area.sx = vxres - ((sx + width) * vc->vc_font.width); + area.dy = vyres - ((dy + height) * vc->vc_font.height); + area.dx = vxres - ((dx + width) * vc->vc_font.width); + area.height = height * vc->vc_font.height; + area.width = width * vc->vc_font.width; + + info->fbops->fb_copyarea(info, &area); +} + +static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int height, int width) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vyres = GETVYRES(ops->p->scrollmode, info); + u32 vxres = GETVXRES(ops->p->scrollmode, info); + + region.color = attr_bgcol_ec(bgshift,vc); + region.dy = vyres - ((sy + height) * vc->vc_font.height); + region.dx = vxres - ((sx + width) * vc->vc_font.width); + region.width = width * vc->vc_font.width; + region.height = height * vc->vc_font.height; + region.rop = ROP_COPY; + + info->fbops->fb_fillrect(info, ®ion); +} + +static inline void ud_putcs_aligned(struct vc_data *vc, struct fb_info *info, + const u16 *s, u32 attr, u32 cnt, + u32 d_pitch, u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, u8 *dst) +{ + struct fbcon_ops *ops = info->fbcon_par; + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + u32 idx = vc->vc_font.width >> 3; + u8 *src; + + while (cnt--) { + src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; + + if (attr) { + ud_update_attr(buf, src, attr, vc); + src = buf; + } + + if (likely(idx == 1)) + __fb_pad_aligned_buffer(dst, d_pitch, src, idx, + image->height); + else + fb_pad_aligned_buffer(dst, d_pitch, src, idx, + image->height); + + dst += s_pitch; + } + + info->fbops->fb_imageblit(info, image); +} + +static inline void ud_putcs_unaligned(struct vc_data *vc, + struct fb_info *info, const u16 *s, + u32 attr, u32 cnt, u32 d_pitch, + u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, + u8 *dst) +{ + struct fbcon_ops *ops = info->fbcon_par; + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + u32 shift_low = 0, mod = vc->vc_font.width % 8; + u32 shift_high = 8; + u32 idx = vc->vc_font.width >> 3; + u8 *src; + + while (cnt--) { + src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; + + if (attr) { + ud_update_attr(buf, src, attr, vc); + src = buf; + } + + fb_pad_unaligned_buffer(dst, d_pitch, src, idx, + image->height, shift_high, + shift_low, mod); + shift_low += mod; + dst += (shift_low >= 8) ? s_pitch : s_pitch - 1; + shift_low &= 7; + shift_high = 8 - shift_low; + } + + info->fbops->fb_imageblit(info, image); + +} + +static void ud_putcs(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx, + int fg, int bg) +{ + struct fb_image image; + struct fbcon_ops *ops = info->fbcon_par; + u32 width = (vc->vc_font.width + 7)/8; + u32 cellsize = width * vc->vc_font.height; + u32 maxcnt = info->pixmap.size/cellsize; + u32 scan_align = info->pixmap.scan_align - 1; + u32 buf_align = info->pixmap.buf_align - 1; + u32 mod = vc->vc_font.width % 8, cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; + u32 vyres = GETVYRES(ops->p->scrollmode, info); + u32 vxres = GETVXRES(ops->p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + image.fg_color = fg; + image.bg_color = bg; + image.dy = vyres - ((yy * vc->vc_font.height) + vc->vc_font.height); + image.dx = vxres - ((xx + count) * vc->vc_font.width); + image.height = vc->vc_font.height; + image.depth = 1; + + if (attribute) { + buf = kmalloc(cellsize, GFP_KERNEL); + if (!buf) + return; + } + + s += count - 1; + + while (count) { + if (count > maxcnt) + cnt = maxcnt; + else + cnt = count; + + image.width = vc->vc_font.width * cnt; + pitch = ((image.width + 7) >> 3) + scan_align; + pitch &= ~scan_align; + size = pitch * image.height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + image.data = dst; + + if (!mod) + ud_putcs_aligned(vc, info, s, attribute, cnt, pitch, + width, cellsize, &image, buf, dst); + else + ud_putcs_unaligned(vc, info, s, attribute, cnt, pitch, + width, cellsize, &image, + buf, dst); + + image.dx += image.width; + count -= cnt; + s -= cnt; + xx += cnt; + } + + /* buf is always NULL except when in monochrome mode, so in this case + it's a gain to check buf against NULL even though kfree() handles + NULL pointers just fine */ + if (unlikely(buf)) + kfree(buf); + +} + +static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, + int bottom_only) +{ + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.xres - (vc->vc_cols*cw); + unsigned int bh = info->var.yres - (vc->vc_rows*ch); + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + + region.color = attr_bgcol_ec(bgshift,vc); + region.rop = ROP_COPY; + + if (rw && !bottom_only) { + region.dy = 0; + region.dx = info->var.xoffset; + region.width = rw; + region.height = info->var.yres_virtual; + info->fbops->fb_fillrect(info, ®ion); + } + + if (bh) { + region.dy = info->var.yoffset; + region.dx = info->var.xoffset; + region.height = bh; + region.width = info->var.xres; + info->fbops->fb_fillrect(info, ®ion); + } +} + +static void ud_cursor(struct vc_data *vc, struct fb_info *info, + struct display *p, int mode, int softback_lines, + int fg, int bg) +{ + struct fb_cursor cursor; + struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + int w = (vc->vc_font.width + 7) >> 3, c; + int y = real_y(p, vc->vc_y); + int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1, dx, dy; + char *src; + u32 vyres = GETVYRES(p->scrollmode, info); + u32 vxres = GETVXRES(p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + cursor.set = 0; + + if (softback_lines) { + if (y + softback_lines >= vc->vc_rows) { + mode = CM_ERASE; + ops->cursor_flash = 0; + return; + } else + y += softback_lines; + } + + c = scr_readw((u16 *) vc->vc_pos); + attribute = get_attribute(info, c); + src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height)); + + if (ops->cursor_state.image.data != src || + ops->cursor_reset) { + ops->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; + } + + if (attribute) { + u8 *dst; + + dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC); + if (!dst) + return; + kfree(ops->cursor_data); + ops->cursor_data = dst; + ud_update_attr(dst, src, attribute, vc); + src = dst; + } + + if (ops->cursor_state.image.fg_color != fg || + ops->cursor_state.image.bg_color != bg || + ops->cursor_reset) { + ops->cursor_state.image.fg_color = fg; + ops->cursor_state.image.bg_color = bg; + cursor.set |= FB_CUR_SETCMAP; + } + + if (ops->cursor_state.image.height != vc->vc_font.height || + ops->cursor_state.image.width != vc->vc_font.width || + ops->cursor_reset) { + ops->cursor_state.image.height = vc->vc_font.height; + ops->cursor_state.image.width = vc->vc_font.width; + cursor.set |= FB_CUR_SETSIZE; + } + + dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height); + dx = vxres - ((vc->vc_x * vc->vc_font.width) + vc->vc_font.width); + + if (ops->cursor_state.image.dx != dx || + ops->cursor_state.image.dy != dy || + ops->cursor_reset) { + ops->cursor_state.image.dx = dx; + ops->cursor_state.image.dy = dy; + cursor.set |= FB_CUR_SETPOS; + } + + if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || + ops->cursor_reset) { + ops->cursor_state.hot.x = cursor.hot.y = 0; + cursor.set |= FB_CUR_SETHOT; + } + + if (cursor.set & FB_CUR_SETSIZE || + vc->vc_cursor_type != p->cursor_shape || + ops->cursor_state.mask == NULL || + ops->cursor_reset) { + char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC); + int cur_height, size, i = 0; + u8 msk = 0xff; + + if (!mask) + return; + + kfree(ops->cursor_state.mask); + ops->cursor_state.mask = mask; + + p->cursor_shape = vc->vc_cursor_type; + cursor.set |= FB_CUR_SETSHAPE; + + switch (p->cursor_shape & CUR_HWMASK) { + case CUR_NONE: + cur_height = 0; + break; + case CUR_UNDERLINE: + cur_height = (vc->vc_font.height < 10) ? 1 : 2; + break; + case CUR_LOWER_THIRD: + cur_height = vc->vc_font.height/3; + break; + case CUR_LOWER_HALF: + cur_height = vc->vc_font.height >> 1; + break; + case CUR_TWO_THIRDS: + cur_height = (vc->vc_font.height << 1)/3; + break; + case CUR_BLOCK: + default: + cur_height = vc->vc_font.height; + break; + } + + size = cur_height * w; + + while (size--) + mask[i++] = msk; + + size = (vc->vc_font.height - cur_height) * w; + + while (size--) + mask[i++] = ~msk; + } + + switch (mode) { + case CM_ERASE: + ops->cursor_state.enable = 0; + break; + case CM_DRAW: + case CM_MOVE: + default: + ops->cursor_state.enable = (use_sw) ? 0 : 1; + break; + } + + cursor.image.data = src; + cursor.image.fg_color = ops->cursor_state.image.fg_color; + cursor.image.bg_color = ops->cursor_state.image.bg_color; + cursor.image.dx = ops->cursor_state.image.dx; + cursor.image.dy = ops->cursor_state.image.dy; + cursor.image.height = ops->cursor_state.image.height; + cursor.image.width = ops->cursor_state.image.width; + cursor.hot.x = ops->cursor_state.hot.x; + cursor.hot.y = ops->cursor_state.hot.y; + cursor.mask = ops->cursor_state.mask; + cursor.enable = ops->cursor_state.enable; + cursor.image.depth = 1; + cursor.rop = ROP_XOR; + + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); + + ops->cursor_reset = 0; +} + +int ud_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + u32 xoffset, yoffset; + u32 vyres = GETVYRES(ops->p->scrollmode, info); + u32 vxres = GETVXRES(ops->p->scrollmode, info); + int err; + + xoffset = (vxres - info->var.xres) - ops->var.xoffset; + yoffset = (vyres - info->var.yres) - ops->var.yoffset; + ops->var.xoffset = xoffset; + ops->var.yoffset = yoffset; + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + +void fbcon_rotate_ud(struct fbcon_ops *ops) +{ + ops->bmove = ud_bmove; + ops->clear = ud_clear; + ops->putcs = ud_putcs; + ops->clear_margins = ud_clear_margins; + ops->cursor = ud_cursor; + ops->update_start = ud_update_start; +} +EXPORT_SYMBOL(fbcon_rotate_ud); + +MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); +MODULE_DESCRIPTION("Console Rotation (180 degrees) Support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index e793ffd39db..762c7a59314 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -32,7 +32,6 @@ #include <linux/font.h> -extern struct font_desc font_vga_8x16; extern unsigned long sgi_gfxaddr; #define FONT_DATA ((unsigned char *)font_vga_8x16.data) diff --git a/drivers/video/softcursor.c b/drivers/video/console/softcursor.c index 229c4bc3507..8529bf08db2 100644 --- a/drivers/video/softcursor.c +++ b/drivers/video/console/softcursor.c @@ -1,7 +1,7 @@ /* * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices * - * Created 14 Nov 2002 by James Simmons + * Created 14 Nov 2002 by James Simmons * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive @@ -55,9 +55,9 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) src[i] = image->data[i] & cursor->mask[i]; break; } - } else + } else memcpy(src, image->data, dsize); - + fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); image->data = dst; info->fbops->fb_imageblit(info, image); @@ -66,7 +66,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) } EXPORT_SYMBOL(soft_cursor); - + MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); MODULE_DESCRIPTION("Generic software cursor"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index d940f605acb..a7bcd17112c 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -511,12 +511,12 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) struct sti_cooked_font *cooked_font; if (!fbfont_name || !strlen(fbfont_name)) - return NULL; + return NULL; fbfont = find_font(fbfont_name); if (!fbfont) - fbfont = get_default_font(1024,768); + fbfont = get_default_font(1024,768); if (!fbfont) - return NULL; + return NULL; DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n", fbfont->width, fbfont->height, fbfont->name)); @@ -527,7 +527,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) nf = kmalloc(size, GFP_KERNEL); if (!nf) - return NULL; + return NULL; memset(nf, 0, size); nf->first_char = 0; @@ -546,8 +546,8 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL); if (!cooked_font) { - kfree(nf); - return NULL; + kfree(nf); + return NULL; } cooked_font->raw = nf; @@ -595,7 +595,7 @@ sti_select_font(struct sti_cooked_rom *rom, static void __init sti_dump_rom(struct sti_rom *rom) { - printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n", + printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n", rom->graphics_id[0], rom->graphics_id[1], rom->revno[0] >> 4, @@ -651,15 +651,16 @@ sti_search_font(struct sti_cooked_rom *rom, int height, int width) struct sti_cooked_font *font; int i = 0; - for(font = rom->font_start; font; font = font->next_font, i++) { - if((font->raw->width == width) && (font->raw->height == height)) + for (font = rom->font_start; font; font = font->next_font, i++) { + if ((font->raw->width == width) && + (font->raw->height == height)) return i; } return 0; } -#define BMODE_RELOCATE(offset) offset = (offset) / 4; -#define BMODE_LAST_ADDR_OFFS 0x50 +#define BMODE_RELOCATE(offset) offset = (offset) / 4; +#define BMODE_LAST_ADDR_OFFS 0x50 static void * __init sti_bmode_font_raw(struct sti_cooked_font *f) @@ -700,35 +701,35 @@ sti_get_bmode_rom (unsigned long address) { struct sti_rom *raw; u32 size; - struct sti_rom_font *raw_font, *font_start; - + struct sti_rom_font *raw_font, *font_start; + sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size); - - size = (size+3) / 4; + + size = (size+3) / 4; raw = kmalloc(size, GFP_KERNEL); if (raw) { - sti_bmode_rom_copy(address, size, raw); - memmove (&raw->res004, &raw->type[0], 0x3c); - raw->type[3] = raw->res004; + sti_bmode_rom_copy(address, size, raw); + memmove (&raw->res004, &raw->type[0], 0x3c); + raw->type[3] = raw->res004; - BMODE_RELOCATE (raw->region_list); - BMODE_RELOCATE (raw->font_start); + BMODE_RELOCATE (raw->region_list); + BMODE_RELOCATE (raw->font_start); - BMODE_RELOCATE (raw->init_graph); - BMODE_RELOCATE (raw->state_mgmt); - BMODE_RELOCATE (raw->font_unpmv); - BMODE_RELOCATE (raw->block_move); - BMODE_RELOCATE (raw->inq_conf); + BMODE_RELOCATE (raw->init_graph); + BMODE_RELOCATE (raw->state_mgmt); + BMODE_RELOCATE (raw->font_unpmv); + BMODE_RELOCATE (raw->block_move); + BMODE_RELOCATE (raw->inq_conf); - raw_font = ((void *)raw) + raw->font_start; - font_start = raw_font; + raw_font = ((void *)raw) + raw->font_start; + font_start = raw_font; - while (raw_font->next_font) { - BMODE_RELOCATE (raw_font->next_font); - raw_font = ((void *)font_start) + raw_font->next_font; - } + while (raw_font->next_font) { + BMODE_RELOCATE (raw_font->next_font); + raw_font = ((void *)font_start) + raw_font->next_font; + } } - return raw; + return raw; } struct sti_rom * __init @@ -736,15 +737,15 @@ sti_get_wmode_rom (unsigned long address) { struct sti_rom *raw; unsigned long size; - + /* read the ROM size directly from the struct in ROM */ size = gsc_readl(address + offsetof(struct sti_rom,last_addr)); raw = kmalloc(size, GFP_KERNEL); - if(raw) - sti_rom_copy(address, size, raw); + if (raw) + sti_rom_copy(address, size, raw); - return raw; + return raw; } int __init @@ -757,14 +758,14 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address) if (!cooked) goto out_err; - if (wordmode) - raw = sti_get_wmode_rom (address); - else - raw = sti_get_bmode_rom (address); + if (wordmode) + raw = sti_get_wmode_rom (address); + else + raw = sti_get_bmode_rom (address); + + if (!raw) + goto out_err; - if (!raw) - goto out_err; - if (!sti_cook_fonts(cooked, raw)) { printk(KERN_ERR "No font found for STI at %08lx\n", address); goto out_err; @@ -787,7 +788,7 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address) sti->font_width = sti->font->raw->width; sti->font_height = sti->font->raw->height; if (!wordmode) - sti->font->raw = sti_bmode_font_raw(sti->font); + sti->font->raw = sti_bmode_font_raw(sti->font); sti->sti_mem_request = raw->sti_mem_req; sti->graphics_id[0] = raw->graphics_id[0]; @@ -811,16 +812,16 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd u32 sig; if (num_sti_roms >= MAX_STI_ROMS) { - printk(KERN_WARNING "maximum number of STI ROMS reached !\n"); - return NULL; + printk(KERN_WARNING "maximum number of STI ROMS reached !\n"); + return NULL; } sti = kmalloc(sizeof(*sti), GFP_KERNEL); if (!sti) { - printk(KERN_ERR "Not enough memory !\n"); - return NULL; + printk(KERN_ERR "Not enough memory !\n"); + return NULL; } - + memset(sti, 0, sizeof(*sti)); spin_lock_init(&sti->lock); @@ -932,28 +933,21 @@ static void __init sticore_check_for_default_sti(struct sti_struct *sti, char *p */ static int __init sticore_pa_init(struct parisc_device *dev) { - unsigned long rom = 0; char pa_path[21]; struct sti_struct *sti = NULL; - - if(dev->num_addrs) { - rom = dev->addr[0]; - } - if (!rom) { - rom = dev->hpa; - DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa)); - sti = sti_try_rom_generic(rom, dev->hpa, NULL); - rom = PAGE0->proc_sti; - } - if (!sti) { - DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa)); - sti = sti_try_rom_generic(rom, dev->hpa, NULL); - } + int hpa = dev->hpa.start; + + if (dev->num_addrs && dev->addr[0]) + sti = sti_try_rom_generic(dev->addr[0], hpa, NULL); + if (!sti) + sti = sti_try_rom_generic(hpa, hpa, NULL); + if (!sti) + sti = sti_try_rom_generic(PAGE0->proc_sti, hpa, NULL); if (!sti) return 1; - + print_pa_hwpath(dev, pa_path); - sticore_check_for_default_sti (sti, pa_path); + sticore_check_for_default_sti(sti, pa_path); return 0; } diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index 7f76e2c6a4a..cb25324a563 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c @@ -118,6 +118,18 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, info->tileops->fb_tilecursor(info, &cursor); } +static int tile_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + int err; + + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, struct display *p, struct fbcon_ops *ops) { @@ -128,6 +140,7 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, ops->putcs = tile_putcs; ops->clear_margins = tile_clear_margins; ops->cursor = tile_cursor; + ops->update_start = tile_update_start; if (p) { map.width = vc->vc_font.width; diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 6ef6f7760e4..167de397e4b 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -448,7 +448,8 @@ static void vgacon_cursor(struct vc_data *c, int mode) vgacon_scrolldelta(c, 0); switch (mode) { case CM_ERASE: - write_vga(14, (vga_vram_end - vga_vram_base - 1) / 2); + write_vga(14, (c->vc_pos - vga_vram_base) / 2); + vgacon_set_cursor_size(c->vc_x, 31, 30); break; case CM_MOVE: @@ -565,7 +566,11 @@ static int vgacon_switch(struct vc_data *c) scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size); - vgacon_doresize(c, c->vc_cols, c->vc_rows); + if (!(vga_video_num_columns % 2) && + vga_video_num_columns <= ORIG_VIDEO_COLS && + vga_video_num_lines <= (ORIG_VIDEO_LINES * + vga_default_font_height) / c->vc_font.height) + vgacon_doresize(c, c->vc_cols, c->vc_rows); } return 0; /* Redrawing not needed */ @@ -575,6 +580,7 @@ static void vga_set_palette(struct vc_data *vc, unsigned char *table) { int i, j; + vga_w(state.vgabase, VGA_PEL_MSK, 0xff); for (i = j = 0; i < 16; i++) { vga_w(state.vgabase, VGA_PEL_IW, table[i]); vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2); @@ -717,6 +723,7 @@ static void vga_pal_blank(struct vgastate *state) { int i; + vga_w(state->vgabase, VGA_PEL_MSK, 0xff); for (i = 0; i < 16; i++) { vga_w(state->vgabase, VGA_PEL_IW, i); vga_w(state->vgabase, VGA_PEL_D, 0); @@ -959,6 +966,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight) outb_p(0x12, vga_video_port_reg); /* Vertical display limit */ outb_p(vde, vga_video_port_val); spin_unlock_irq(&vga_lock); + vga_video_font_height = fontheight; for (i = 0; i < MAX_NR_CONSOLES; i++) { struct vc_data *c = vc_cons[i].d; @@ -1023,7 +1031,8 @@ static int vgacon_resize(struct vc_data *c, unsigned int width, if (width % 2 || width > ORIG_VIDEO_COLS || height > (ORIG_VIDEO_LINES * vga_default_font_height)/ c->vc_font.height) - return -EINVAL; + /* let svgatextmode tinker with video timings */ + return 0; if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */ vgacon_doresize(c, width, height); diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 989e700159e..403d17377f8 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -176,7 +176,6 @@ static struct fb_ops controlfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 3894b2a501d..c589d23e7f9 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1064,7 +1064,6 @@ static struct fb_ops cyber2000fb_ops = { .fb_fillrect = cyber2000fb_fillrect, .fb_copyarea = cyber2000fb_copyarea, .fb_imageblit = cyber2000fb_imageblit, - .fb_cursor = soft_cursor, .fb_sync = cyber2000fb_sync, }; diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c index ae2762cb560..03fbe83d71a 100644 --- a/drivers/video/cyblafb.c +++ b/drivers/video/cyblafb.c @@ -410,20 +410,21 @@ static void cyblafb_imageblit(struct fb_info *info, out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1)); while(index < index_end) { + const char *p = image->data + index; for(i=0;i<width_dds;i++) { - out32(GE9C,*((u32*) ((u32)image->data + index))); + out32(GE9C,*(u32*)p); + p+=4; index+=4; } switch(width_dbs) { case 0: break; - case 8: out32(GE9C,*((u8*)((u32)image->data+index))); + case 8: out32(GE9C,*(u8*)p); index+=1; break; - case 16: out32(GE9C,*((u16*)((u32)image->data+index))); + case 16: out32(GE9C,*(u16*)p); index+=2; break; - case 24: out32(GE9C,(u32)(*((u16*)((u32)image->data+index))) | - (u32)(*((u8*)((u32)image->data+index+2)))<<16); + case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16); index+=3; break; } @@ -967,7 +968,6 @@ static struct fb_ops cyblafb_ops __devinitdata = { .fb_fillrect = cyblafb_fillrect, .fb_copyarea= cyblafb_copyarea, .fb_imageblit = cyblafb_imageblit, - .fb_cursor = soft_cursor, }; //========================================================================== diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c index 1dbb82dca40..5abd3cb0067 100644 --- a/drivers/video/dnfb.c +++ b/drivers/video/dnfb.c @@ -6,6 +6,8 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> + #include <asm/setup.h> #include <asm/system.h> #include <asm/irq.h> @@ -114,7 +116,6 @@ static struct fb_ops dn_fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = dnfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; struct fb_var_screeninfo dnfb_var __devinitdata = { @@ -226,9 +227,8 @@ void dnfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) * Initialization */ -static int __devinit dnfb_probe(struct device *device) +static int __devinit dnfb_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(device); struct fb_info *info; int err = 0; @@ -256,7 +256,7 @@ static int __devinit dnfb_probe(struct device *device) framebuffer_release(info); return err; } - dev_set_drvdata(&dev->dev, info); + platform_set_drvdata(dev, info); /* now we have registered we can safely setup the hardware */ out_8(AP_CONTROL_3A, RESET_CREG); @@ -270,10 +270,11 @@ static int __devinit dnfb_probe(struct device *device) return err; } -static struct device_driver dnfb_driver = { - .name = "dnfb", - .bus = &platform_bus_type, +static struct platform_driver dnfb_driver = { .probe = dnfb_probe, + .driver = { + .name = "dnfb", + }, }; static struct platform_device dnfb_device = { @@ -287,12 +288,12 @@ int __init dnfb_init(void) if (fb_get_options("dnfb", NULL)) return -ENODEV; - ret = driver_register(&dnfb_driver); + ret = platform_driver_register(&dnfb_driver); if (!ret) { ret = platform_device_register(&dnfb_device); if (ret) - driver_unregister(&dnfb_driver); + platform_driver_unregister(&dnfb_driver); } return ret; } diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 116e808d71c..3b0e7138344 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -54,6 +54,8 @@ #include <linux/fb.h> #include <linux/init.h> #include <linux/ioport.h> +#include <linux/platform_device.h> + #include <asm/types.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -482,7 +484,6 @@ static struct fb_ops epson1355fb_fbops = { .fb_imageblit = cfb_imageblit, .fb_read = epson1355fb_read, .fb_write = epson1355fb_write, - .fb_cursor = soft_cursor, }; /* ------------------------------------------------------------------------- */ @@ -608,9 +609,9 @@ static void epson1355fb_platform_release(struct device *device) { } -static int epson1355fb_remove(struct device *device) +static int epson1355fb_remove(struct platform_device *dev) { - struct fb_info *info = dev_get_drvdata(device); + struct fb_info *info = platform_get_drvdata(dev); struct epson1355_par *par = info->par; backlight_enable(0); @@ -631,9 +632,8 @@ static int epson1355fb_remove(struct device *device) return 0; } -int __init epson1355fb_probe(struct device *device) +int __init epson1355fb_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(device); struct epson1355_par *default_par; struct fb_info *info; u8 revision; @@ -712,7 +712,7 @@ int __init epson1355fb_probe(struct device *device) /* * Our driver data. */ - dev_set_drvdata(&dev->dev, info); + platform_set_drvdata(dev, info); printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); @@ -720,15 +720,16 @@ int __init epson1355fb_probe(struct device *device) return 0; bail: - epson1355fb_remove(device); + epson1355fb_remove(dev); return rc; } -static struct device_driver epson1355fb_driver = { - .name = "epson1355fb", - .bus = &platform_bus_type, +static struct platform_driver epson1355fb_driver = { .probe = epson1355fb_probe, .remove = epson1355fb_remove, + .driver = { + .name = "epson1355fb", + }, }; static struct platform_device epson1355fb_device = { @@ -746,11 +747,11 @@ int __init epson1355fb_init(void) if (fb_get_options("epson1355fb", NULL)) return -ENODEV; - ret = driver_register(&epson1355fb_driver); + ret = platform_driver_register(&epson1355fb_driver); if (!ret) { ret = platform_device_register(&epson1355fb_device); if (ret) - driver_unregister(&epson1355fb_driver); + platform_driver_unregister(&epson1355fb_driver); } return ret; } @@ -761,7 +762,7 @@ module_init(epson1355fb_init); static void __exit epson1355fb_exit(void) { platform_device_unregister(&epson1355fb_device); - driver_unregister(&epson1355fb_driver); + platform_driver_unregister(&epson1355fb_driver); } /* ------------------------------------------------------------------------- */ diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 70be7009f8a..6240aedb415 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -14,6 +14,7 @@ #include <linux/config.h> #include <linux/module.h> +#include <linux/compat.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/sched.h> @@ -323,9 +324,103 @@ static struct logo_data { const struct linux_logo *logo; } fb_logo; -int fb_prepare_logo(struct fb_info *info) +static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) +{ + u32 size = width * height, i; + + out += size - 1; + + for (i = size; i--; ) + *out-- = *in++; +} + +static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, w = width - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * j + w - i] = *in++; +} + +static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, w = width - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * (w - j) + i] = *in++; +} + +static void fb_rotate_logo(struct fb_info *info, u8 *dst, + struct fb_image *image, int rotate) +{ + u32 tmp; + + if (rotate == FB_ROTATE_UD) { + image->dx = info->var.xres - image->width; + image->dy = info->var.yres - image->height; + fb_rotate_logo_ud(image->data, dst, image->width, + image->height); + } else if (rotate == FB_ROTATE_CW) { + tmp = image->width; + image->width = image->height; + image->height = tmp; + image->dx = info->var.xres - image->height; + fb_rotate_logo_cw(image->data, dst, image->width, + image->height); + } else if (rotate == FB_ROTATE_CCW) { + tmp = image->width; + image->width = image->height; + image->height = tmp; + image->dy = info->var.yres - image->width; + fb_rotate_logo_ccw(image->data, dst, image->width, + image->height); + } + + image->data = dst; +} + +static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, + int rotate) +{ + int x; + + if (rotate == FB_ROTATE_UR) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.xres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dx += fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_UD) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.xres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dx -= fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_CW) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.yres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dy += fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_CCW) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.yres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dy -= fb_logo.logo->width + 8; + } + } +} + +int fb_prepare_logo(struct fb_info *info, int rotate) { int depth = fb_get_color_depth(&info->var, &info->fix); + int yres; memset(&fb_logo, 0, sizeof(struct logo_data)); @@ -357,11 +452,21 @@ int fb_prepare_logo(struct fb_info *info) /* Return if no suitable logo was found */ fb_logo.logo = fb_find_logo(depth); + + if (!fb_logo.logo) { + return 0; + } - if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) { + if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) + yres = info->var.yres; + else + yres = info->var.xres; + + if (fb_logo.logo->height > yres) { fb_logo.logo = NULL; return 0; } + /* What depth we asked for might be different from what we get */ if (fb_logo.logo->type == LINUX_LOGO_CLUT224) fb_logo.depth = 8; @@ -372,12 +477,11 @@ int fb_prepare_logo(struct fb_info *info) return fb_logo.logo->height; } -int fb_show_logo(struct fb_info *info) +int fb_show_logo(struct fb_info *info, int rotate) { u32 *palette = NULL, *saved_pseudo_palette = NULL; - unsigned char *logo_new = NULL; + unsigned char *logo_new = NULL, *logo_rotate = NULL; struct fb_image image; - int x; /* Return if the frame buffer is not mapped or suspended */ if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) @@ -417,25 +521,30 @@ int fb_show_logo(struct fb_info *info) fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth); } + image.dx = 0; + image.dy = 0; image.width = fb_logo.logo->width; image.height = fb_logo.logo->height; - image.dy = 0; - for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) && - x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) { - image.dx = x; - info->fbops->fb_imageblit(info, &image); + if (rotate) { + logo_rotate = kmalloc(fb_logo.logo->width * + fb_logo.logo->height, GFP_KERNEL); + if (logo_rotate) + fb_rotate_logo(info, logo_rotate, &image, rotate); } - + + fb_do_show_logo(info, &image, rotate); + kfree(palette); if (saved_pseudo_palette != NULL) info->pseudo_palette = saved_pseudo_palette; kfree(logo_new); + kfree(logo_rotate); return fb_logo.logo->height; } #else -int fb_prepare_logo(struct fb_info *info) { return 0; } -int fb_show_logo(struct fb_info *info) { return 0; } +int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } +int fb_show_logo(struct fb_info *info, int rotate) { return 0; } #endif /* CONFIG_LOGO */ static int fbmem_read_proc(char *buf, char **start, off_t offset, @@ -829,18 +938,154 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } #ifdef CONFIG_COMPAT +struct fb_fix_screeninfo32 { + char id[16]; + compat_caddr_t smem_start; + u32 smem_len; + u32 type; + u32 type_aux; + u32 visual; + u16 xpanstep; + u16 ypanstep; + u16 ywrapstep; + u32 line_length; + compat_caddr_t mmio_start; + u32 mmio_len; + u32 accel; + u16 reserved[3]; +}; + +struct fb_cmap32 { + u32 start; + u32 len; + compat_caddr_t red; + compat_caddr_t green; + compat_caddr_t blue; + compat_caddr_t transp; +}; + +static int fb_getput_cmap(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct fb_cmap_user __user *cmap; + struct fb_cmap32 __user *cmap32; + __u32 data; + int err; + + cmap = compat_alloc_user_space(sizeof(*cmap)); + cmap32 = compat_ptr(arg); + + if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32))) + return -EFAULT; + + if (get_user(data, &cmap32->red) || + put_user(compat_ptr(data), &cmap->red) || + get_user(data, &cmap32->green) || + put_user(compat_ptr(data), &cmap->green) || + get_user(data, &cmap32->blue) || + put_user(compat_ptr(data), &cmap->blue) || + get_user(data, &cmap32->transp) || + put_user(compat_ptr(data), &cmap->transp)) + return -EFAULT; + + err = fb_ioctl(inode, file, cmd, (unsigned long) cmap); + + if (!err) { + if (copy_in_user(&cmap32->start, + &cmap->start, + 2 * sizeof(__u32))) + err = -EFAULT; + } + return err; +} + +static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, + struct fb_fix_screeninfo32 __user *fix32) +{ + __u32 data; + int err; + + err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id)); + + data = (__u32) (unsigned long) fix->smem_start; + err |= put_user(data, &fix32->smem_start); + + err |= put_user(fix->smem_len, &fix32->smem_len); + err |= put_user(fix->type, &fix32->type); + err |= put_user(fix->type_aux, &fix32->type_aux); + err |= put_user(fix->visual, &fix32->visual); + err |= put_user(fix->xpanstep, &fix32->xpanstep); + err |= put_user(fix->ypanstep, &fix32->ypanstep); + err |= put_user(fix->ywrapstep, &fix32->ywrapstep); + err |= put_user(fix->line_length, &fix32->line_length); + + data = (__u32) (unsigned long) fix->mmio_start; + err |= put_user(data, &fix32->mmio_start); + + err |= put_user(fix->mmio_len, &fix32->mmio_len); + err |= put_user(fix->accel, &fix32->accel); + err |= copy_to_user(fix32->reserved, fix->reserved, + sizeof(fix->reserved)); + + return err; +} + +static int fb_get_fscreeninfo(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs; + struct fb_fix_screeninfo fix; + struct fb_fix_screeninfo32 __user *fix32; + int err; + + fix32 = compat_ptr(arg); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = fb_ioctl(inode, file, cmd, (unsigned long) &fix); + set_fs(old_fs); + + if (!err) + err = do_fscreeninfo_to_user(&fix, fix32); + + return err; +} + static long fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int fbidx = iminor(file->f_dentry->d_inode); + struct inode *inode = file->f_dentry->d_inode; + int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; - long ret; + long ret = -ENOIOCTLCMD; - if (fb->fb_compat_ioctl == NULL) - return -ENOIOCTLCMD; lock_kernel(); - ret = fb->fb_compat_ioctl(file, cmd, arg, info); + switch(cmd) { + case FBIOGET_VSCREENINFO: + case FBIOPUT_VSCREENINFO: + case FBIOPAN_DISPLAY: + case FBIOGET_CON2FBMAP: + case FBIOPUT_CON2FBMAP: + arg = (unsigned long) compat_ptr(arg); + case FBIOBLANK: + ret = fb_ioctl(inode, file, cmd, arg); + break; + + case FBIOGET_FSCREENINFO: + ret = fb_get_fscreeninfo(inode, file, cmd, arg); + break; + + case FBIOGETCMAP: + case FBIOPUTCMAP: + ret = fb_getput_cmap(inode, file, cmd, arg); + break; + + default: + if (fb->fb_compat_ioctl) + ret = fb->fb_compat_ioctl(file, cmd, arg, info); + break; + } unlock_kernel(); return ret; } @@ -918,7 +1163,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) } #endif #elif defined(__powerpc__) - vma->vm_page_prot = phys_mem_access_prot(file, off, + vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); #elif defined(__alpha__) @@ -1031,7 +1276,7 @@ register_framebuffer(struct fb_info *fb_info) break; fb_info->node = i; - fb_info->class_device = class_device_create(fb_class, MKDEV(FB_MAJOR, i), + fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i), fb_info->device, "fb%d", i); if (IS_ERR(fb_info->class_device)) { /* Not fatal */ @@ -1215,6 +1460,28 @@ int fb_new_modelist(struct fb_info *info) return err; } +/** + * fb_con_duit - user<->fbcon passthrough + * @info: struct fb_info + * @event: notification event to be passed to fbcon + * @data: private data + * + * DESCRIPTION + * This function is an fbcon-user event passing channel + * which bypasses fbdev. This is hopefully temporary + * until a user interface for fbcon is created + */ +int fb_con_duit(struct fb_info *info, int event, void *data) +{ + struct fb_event evnt; + + evnt.info = info; + evnt.data = data; + + return notifier_call_chain(&fb_notifier_list, event, &evnt); +} +EXPORT_SYMBOL(fb_con_duit); + static char *video_options[FB_MAX]; static int ofonly; diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 713226cdf3c..fc7965b6677 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -538,25 +538,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) *dbsize = 0; - DPRINTK(" Supported VESA Modes\n"); - block = edid + ESTABLISHED_TIMING_1; - num += get_est_timing(block, &mode[num]); - - DPRINTK(" Standard Timings\n"); - block = edid + STD_TIMING_DESCRIPTIONS_START; - for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) - num += get_std_timing(block, &mode[num]); - DPRINTK(" Detailed Timings\n"); block = edid + DETAILED_TIMING_DESCRIPTIONS_START; for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { int first = 1; - if (block[0] == 0x00 && block[1] == 0x00) { - if (block[3] == 0xfa) { - num += get_dst_timing(block + 5, &mode[num]); - } - } else { + if (!(block[0] == 0x00 && block[1] == 0x00)) { get_detailed_timing(block, &mode[num]); if (first) { mode[num].flag |= FB_MODE_IS_FIRST; @@ -565,6 +552,21 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) num++; } } + + DPRINTK(" Supported VESA Modes\n"); + block = edid + ESTABLISHED_TIMING_1; + num += get_est_timing(block, &mode[num]); + + DPRINTK(" Standard Timings\n"); + block = edid + STD_TIMING_DESCRIPTIONS_START; + for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) + num += get_std_timing(block, &mode[num]); + + block = edid + DETAILED_TIMING_DESCRIPTIONS_START; + for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { + if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) + num += get_dst_timing(block + 5, &mode[num]); + } /* Yikes, EDID data is totally useless */ if (!num) { @@ -827,7 +829,7 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) { unsigned char *block; - int i; + int i, found = 0; if (edid == NULL) return; @@ -869,6 +871,22 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) get_monspecs(edid, specs); specs->modedb = fb_create_modedb(edid, &specs->modedb_len); + + /* + * Workaround for buggy EDIDs that sets that the first + * detailed timing is preferred but has not detailed + * timing specified + */ + for (i = 0; i < specs->modedb_len; i++) { + if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) { + found = 1; + break; + } + } + + if (!found) + specs->misc &= ~FB_MISC_1ST_DETAIL; + DPRINTK("========================================\n"); } diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 1147b899f00..08dac9580d1 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -213,6 +213,70 @@ static ssize_t show_bpp(struct class_device *class_device, char *buf) return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel); } +static ssize_t store_rotate(struct class_device *class_device, const char *buf, + size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_var_screeninfo var; + char **last = NULL; + int err; + + var = fb_info->var; + var.rotate = simple_strtoul(buf, last, 0); + + if ((err = activate(fb_info, &var))) + return err; + + return count; +} + + +static ssize_t show_rotate(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + + return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate); +} + +static ssize_t store_con_rotate(struct class_device *class_device, + const char *buf, size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + char **last = NULL; + + acquire_console_sem(); + rotate = simple_strtoul(buf, last, 0); + fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE, &rotate); + release_console_sem(); + return count; +} + +static ssize_t store_con_rotate_all(struct class_device *class_device, + const char *buf, size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + char **last = NULL; + + acquire_console_sem(); + rotate = simple_strtoul(buf, last, 0); + fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE_ALL, &rotate); + release_console_sem(); + return count; +} + +static ssize_t show_con_rotate(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + + acquire_console_sem(); + rotate = fb_con_duit(fb_info, FB_EVENT_GET_CON_ROTATE, NULL); + release_console_sem(); + return snprintf(buf, PAGE_SIZE, "%d\n", rotate); +} + static ssize_t store_virtual(struct class_device *class_device, const char * buf, size_t count) { @@ -242,6 +306,13 @@ static ssize_t show_virtual(struct class_device *class_device, char *buf) fb_info->var.yres_virtual); } +static ssize_t show_stride(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = + (struct fb_info *)class_get_devdata(class_device); + return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length); +} + /* Format for cmap is "%02x%c%4x%4x%4x\n" */ /* %02x entry %c transp %4x red %4x blue %4x green \n */ /* 256 rows at 16 chars equals 4096, the normal page size */ @@ -432,6 +503,10 @@ static struct class_device_attribute class_device_attrs[] = { __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan), __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), __ATTR(name, S_IRUGO, show_name, NULL), + __ATTR(stride, S_IRUGO, show_stride, NULL), + __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), + __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), + __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), }; int fb_init_class_device(struct fb_info *fb_info) diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 10cd05059fe..2584daec7bb 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -57,9 +57,9 @@ static struct fb_ops ffb_ops = { .fb_sync = ffb_sync, .fb_mmap = ffb_mmap, .fb_ioctl = ffb_ioctl, - - /* XXX Use FFB hw cursor once fb cursor API is better understood... */ - .fb_cursor = soft_cursor, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sbusfb_compat_ioctl, +#endif }; /* Register layout and definitions */ diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index a0763283d77..998374cfae6 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -172,7 +172,6 @@ static struct fb_ops fm2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index d3c1922cb13..d744c51807b 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -11,7 +11,7 @@ #include <linux/config.h> #include <linux/delay.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/errno.h> #include <linux/fb.h> @@ -1038,7 +1038,6 @@ static struct fb_ops gbefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* @@ -1106,12 +1105,11 @@ int __init gbefb_setup(char *options) return 0; } -static int __init gbefb_probe(struct device *dev) +static int __init gbefb_probe(struct platform_device *p_dev) { int i, ret = 0; struct fb_info *info; struct gbefb_par *par; - struct platform_device *p_dev = to_platform_device(dev); #ifndef MODULE char *options = NULL; #endif @@ -1126,7 +1124,7 @@ static int __init gbefb_probe(struct device *dev) gbefb_setup(options); #endif - if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { + if (!request_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { printk(KERN_ERR "gbefb: couldn't reserve mmio region\n"); ret = -EBUSY; goto out_release_framebuffer; @@ -1152,12 +1150,24 @@ static int __init gbefb_probe(struct device *dev) if (gbe_mem_phys) { /* memory was allocated at boot time */ gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size); + if (!gbe_mem) { + printk(KERN_ERR "gbefb: couldn't map framebuffer\n"); + ret = -ENOMEM; + goto out_tiles_free; + } + gbe_dma_addr = 0; } else { /* try to allocate memory with the classical allocator * this has high chance to fail on low memory machines */ gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr, GFP_KERNEL); + if (!gbe_mem) { + printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n"); + ret = -ENOMEM; + goto out_tiles_free; + } + gbe_mem_phys = (unsigned long) gbe_dma_addr; } @@ -1165,12 +1175,6 @@ static int __init gbefb_probe(struct device *dev) mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1); #endif - if (!gbe_mem) { - printk(KERN_ERR "gbefb: couldn't map framebuffer\n"); - ret = -ENXIO; - goto out_tiles_free; - } - /* map framebuffer memory into tiles table */ for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++) gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i; @@ -1199,8 +1203,8 @@ static int __init gbefb_probe(struct device *dev) goto out_gbe_unmap; } - dev_set_drvdata(&p_dev->dev, info); - gbefb_create_sysfs(dev); + platform_set_drvdata(p_dev, info); + gbefb_create_sysfs(&p_dev->dev); printk(KERN_INFO "fb%d: %s rev %d @ 0x%08x using %dkB memory\n", info->node, info->fix.id, gbe_revision, (unsigned) GBE_BASE, @@ -1226,10 +1230,9 @@ out_release_framebuffer: return ret; } -static int __devexit gbefb_remove(struct device* dev) +static int __devexit gbefb_remove(struct platform_device* p_dev) { - struct platform_device *p_dev = to_platform_device(dev); - struct fb_info *info = dev_get_drvdata(&p_dev->dev); + struct fb_info *info = platform_get_drvdata(p_dev); unregister_framebuffer(info); gbe_turn_off(); @@ -1247,31 +1250,38 @@ static int __devexit gbefb_remove(struct device* dev) return 0; } -static struct device_driver gbefb_driver = { - .name = "gbefb", - .bus = &platform_bus_type, +static struct platform_driver gbefb_driver = { .probe = gbefb_probe, .remove = __devexit_p(gbefb_remove), + .driver = { + .name = "gbefb", + }, }; -static struct platform_device gbefb_device = { - .name = "gbefb", -}; +static struct platform_device *gbefb_device; int __init gbefb_init(void) { - int ret = driver_register(&gbefb_driver); + int ret = platform_driver_register(&gbefb_driver); if (!ret) { - ret = platform_device_register(&gbefb_device); - if (ret) - driver_unregister(&gbefb_driver); + gbefb_device = platform_device_alloc("gbefb", 0); + if (gbefb_device) { + ret = platform_device_add(gbefb_device); + } else { + ret = -ENOMEM; + } + if (ret) { + platform_device_put(gbefb_device); + platform_driver_unregister(&gbefb_driver); + } } return ret; } void __exit gbefb_exit(void) { - driver_unregister(&gbefb_driver); + platform_device_unregister(gbefb_device); + platform_driver_unregister(&gbefb_driver); } module_init(gbefb_init); diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 5a9b89c3831..42fb9a89a79 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -14,7 +14,6 @@ config FB_GEODE_GX1 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Framebuffer driver for the display controller integrated into the AMD Geode GX1 processor. diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c index 74a5fca86b8..8e8da743399 100644 --- a/drivers/video/geode/gx1fb_core.c +++ b/drivers/video/geode/gx1fb_core.c @@ -275,7 +275,6 @@ static struct fb_ops gx1fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev) diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 0d376ba5481..f04ca721f94 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -262,7 +262,6 @@ static struct fb_ops hitfb_ops = { .fb_fillrect = hitfb_fillrect, .fb_copyarea = hitfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; int __init hitfb_init(void) diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index e97fe8481d5..bebdac59d23 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -193,7 +193,6 @@ static struct fb_ops hpfb_ops = { .fb_fillrect = hpfb_fillrect, .fb_copyarea = hpfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_sync = hpfb_sync, }; diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index fda53aac1fc..c61bad0da20 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c @@ -44,94 +44,47 @@ static void i810i2c_setscl(void *data, int state) { struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; - i810_writel(mmio, GPIOB, (state ? SCL_VAL_OUT : 0) | SCL_DIR | + i810_writel(mmio, chan->ddc_base, (state ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK); - i810_readl(mmio, GPIOB); /* flush posted write */ + i810_readl(mmio, chan->ddc_base); /* flush posted write */ } static void i810i2c_setsda(void *data, int state) { - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; + struct i810fb_i2c_chan *chan = data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; - i810_writel(mmio, GPIOB, (state ? SDA_VAL_OUT : 0) | SDA_DIR | + i810_writel(mmio, chan->ddc_base, (state ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK); - i810_readl(mmio, GPIOB); /* flush posted write */ + i810_readl(mmio, chan->ddc_base); /* flush posted write */ } static int i810i2c_getscl(void *data) { - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; + struct i810fb_i2c_chan *chan = data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; - i810_writel(mmio, GPIOB, SCL_DIR_MASK); - i810_writel(mmio, GPIOB, 0); - return (0 != (i810_readl(mmio, GPIOB) & SCL_VAL_IN)); + i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK); + i810_writel(mmio, chan->ddc_base, 0); + return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0); } static int i810i2c_getsda(void *data) { - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; - struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; - - i810_writel(mmio, GPIOB, SDA_DIR_MASK); - i810_writel(mmio, GPIOB, 0); - return (0 != (i810_readl(mmio, GPIOB) & SDA_VAL_IN)); -} - -static void i810ddc_setscl(void *data, int state) -{ - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; - struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; - - i810_writel(mmio, GPIOA, (state ? SCL_VAL_OUT : 0) | SCL_DIR | - SCL_DIR_MASK | SCL_VAL_MASK); - i810_readl(mmio, GPIOA); /* flush posted write */ -} - -static void i810ddc_setsda(void *data, int state) -{ - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; - struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; - - i810_writel(mmio, GPIOA, (state ? SDA_VAL_OUT : 0) | SDA_DIR | - SDA_DIR_MASK | SDA_VAL_MASK); - i810_readl(mmio, GPIOA); /* flush posted write */ -} - -static int i810ddc_getscl(void *data) -{ - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; - struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; - - i810_writel(mmio, GPIOA, SCL_DIR_MASK); - i810_writel(mmio, GPIOA, 0); - return (0 != (i810_readl(mmio, GPIOA) & SCL_VAL_IN)); -} - -static int i810ddc_getsda(void *data) -{ - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; + struct i810fb_i2c_chan *chan = data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; - i810_writel(mmio, GPIOA, SDA_DIR_MASK); - i810_writel(mmio, GPIOA, 0); - return (0 != (i810_readl(mmio, GPIOA) & SDA_VAL_IN)); + i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK); + i810_writel(mmio, chan->ddc_base, 0); + return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0); } -#define I2C_ALGO_DDC_I810 0x0e0000 -#define I2C_ALGO_I2C_I810 0x0f0000 -static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, - int conn) +static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) { int rc; @@ -139,22 +92,11 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, chan->adapter.owner = THIS_MODULE; chan->adapter.algo_data = &chan->algo; chan->adapter.dev.parent = &chan->par->dev->dev; - switch (conn) { - case 1: - chan->adapter.id = I2C_ALGO_DDC_I810; - chan->algo.setsda = i810ddc_setsda; - chan->algo.setscl = i810ddc_setscl; - chan->algo.getsda = i810ddc_getsda; - chan->algo.getscl = i810ddc_getscl; - break; - case 2: - chan->adapter.id = I2C_ALGO_I2C_I810; - chan->algo.setsda = i810i2c_setsda; - chan->algo.setscl = i810i2c_setscl; - chan->algo.getsda = i810i2c_getsda; - chan->algo.getscl = i810i2c_getscl; - break; - } + chan->adapter.id = I2C_HW_B_I810; + chan->algo.setsda = i810i2c_setsda; + chan->algo.setscl = i810i2c_setscl; + chan->algo.getsda = i810i2c_getsda; + chan->algo.getscl = i810i2c_getscl; chan->algo.udelay = 10; chan->algo.mdelay = 10; chan->algo.timeout = (HZ/2); @@ -168,11 +110,15 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, udelay(20); rc = i2c_bit_add_bus(&chan->adapter); + if (rc == 0) dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name); - else + else { dev_warn(&chan->par->dev->dev, "Failed to register I2C bus " "%s.\n", name); + chan->par = NULL; + } + return rc; } @@ -180,8 +126,14 @@ void i810_create_i2c_busses(struct i810fb_par *par) { par->chan[0].par = par; par->chan[1].par = par; - i810_setup_i2c_bus(&par->chan[0], "I810-DDC", 1); - i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 2); + par->chan[2].par = par; + + par->chan[0].ddc_base = GPIOA; + i810_setup_i2c_bus(&par->chan[0], "I810-DDC"); + par->chan[1].ddc_base = GPIOB; + i810_setup_i2c_bus(&par->chan[1], "I810-I2C"); + par->chan[2].ddc_base = GPIOC; + i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC"); } void i810_delete_i2c_busses(struct i810fb_par *par) @@ -189,9 +141,14 @@ void i810_delete_i2c_busses(struct i810fb_par *par) if (par->chan[0].par) i2c_bit_del_bus(&par->chan[0].adapter); par->chan[0].par = NULL; + if (par->chan[1].par) i2c_bit_del_bus(&par->chan[1].adapter); par->chan[1].par = NULL; + + if (par->chan[2].par) + i2c_bit_del_bus(&par->chan[2].adapter); + par->chan[2].par = NULL; } static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan) @@ -221,6 +178,7 @@ static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan) DPRINTK("i810-i2c: I2C Transfer successful\n"); return buf; } + DPRINTK("i810-i2c: Unable to read EDID block.\n"); kfree(buf); return NULL; @@ -233,7 +191,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) int i; DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn); - if (conn < 3) { + if (conn < 4) { for (i = 0; i < 3; i++) { /* Do the real work */ edid = i810_do_probe_i2c_edid(&par->chan[conn-1]); @@ -241,11 +199,14 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) break; } } else { - DPRINTK("i810-i2c: Getting EDID from BIOS\n"); - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, fb_firmware_edid(info->device), - EDID_LENGTH); + const u8 *e = fb_firmware_edid(info->device); + + if (e != NULL) { + DPRINTK("i810-i2c: Getting EDID from BIOS\n"); + edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (edid) + memcpy(edid, e, EDID_LENGTH); + } } if (out_edid) @@ -253,5 +214,3 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) return (edid) ? 0 : 1; } - - diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h index d48949ceaac..6c187d5fe95 100644 --- a/drivers/video/i810/i810.h +++ b/drivers/video/i810/i810.h @@ -249,6 +249,7 @@ struct i810fb_i2c_chan { struct i810fb_par *par; struct i2c_adapter adapter; struct i2c_algo_bit_data algo; + unsigned long ddc_base; }; struct i810fb_par { @@ -262,7 +263,7 @@ struct i810fb_par { struct heap_data iring; struct heap_data cursor_heap; struct vgastate state; - struct i810fb_i2c_chan chan[2]; + struct i810fb_i2c_chan chan[3]; atomic_t use_count; u32 pseudo_palette[17]; unsigned long mmio_start_phys; diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 0dbc9ddb676..c0c974b1afa 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1854,7 +1854,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info) #ifdef CONFIG_FB_I810_I2C i810_create_i2c_busses(par); - for (i = 0; i < 3; i++) { + for (i = 0; i < 4; i++) { err = i810_probe_i2c_connector(info, &par->edid, i+1); if (!err) break; @@ -1871,27 +1871,18 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info) fb_videomode_to_modelist(specs->modedb, specs->modedb_len, &info->modelist); if (specs->modedb != NULL) { - if (xres && yres) { - struct fb_videomode *m; + struct fb_videomode *m; + if (xres && yres) { if ((m = fb_find_best_mode(&var, &info->modelist))) { mode = *m; found = 1; } } - if (!found && specs->misc & FB_MISC_1ST_DETAIL) { - for (i = 0; i < specs->modedb_len; i++) { - if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { - mode = specs->modedb[i]; - found = 1; - break; - } - } - } - if (!found) { - mode = specs->modedb[0]; + m = fb_find_best_display(&info->monspecs, &info->modelist); + mode = *m; found = 1; } @@ -2066,8 +2057,7 @@ static void i810fb_release_resource(struct fb_info *info, iounmap(par->mmio_start_virtual); if (par->aperture.virtual) iounmap(par->aperture.virtual); - if (par->edid) - kfree(par->edid); + kfree(par->edid); if (par->res_flags & FRAMEBUFFER_REQ) release_mem_region(par->aperture.physical, par->aperture.size); diff --git a/drivers/video/i810/i810_regs.h b/drivers/video/i810/i810_regs.h index 6e4b9afa4d9..91c6bd9d0d0 100644 --- a/drivers/video/i810/i810_regs.h +++ b/drivers/video/i810/i810_regs.h @@ -70,6 +70,7 @@ #define HVSYNC 0x05000 #define GPIOA 0x05010 #define GPIOB 0x05014 +#define GPIOC 0x0501C /* Clock Control and Power Management Registers (06000h 06FFFh) */ #define DCLK_0D 0x06000 diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 7b9bf45ab6f..7fbe24206b1 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1344,7 +1344,6 @@ static struct fb_ops imsttfb_ops = { .fb_fillrect = imsttfb_fillrect, .fb_copyarea = imsttfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = imsttfb_ioctl, }; diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 6c2244cf0e7..5924cc225c9 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -31,12 +31,11 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/cpufreq.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <asm/hardware.h> #include <asm/io.h> -#include <asm/mach-types.h> #include <asm/uaccess.h> #include <asm/arch/imxfb.h> @@ -299,7 +298,6 @@ static struct fb_ops imxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = imxfb_blank, - .fb_cursor = soft_cursor, /* FIXME: i.MX can do hardware cursor */ }; /* @@ -425,23 +423,21 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi) * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level) +static int imxfb_suspend(struct platform_device *dev, pm_message_t state) { - struct imxfb_info *fbi = dev_get_drvdata(dev); + struct imxfb_info *fbi = platform_get_drvdata(dev); pr_debug("%s\n",__FUNCTION__); - if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) - imxfb_disable_controller(fbi); + imxfb_disable_controller(fbi); return 0; } -static int imxfb_resume(struct device *dev, u32 level) +static int imxfb_resume(struct platform_device *dev) { - struct imxfb_info *fbi = dev_get_drvdata(dev); + struct imxfb_info *fbi = platform_get_drvdata(dev); pr_debug("%s\n",__FUNCTION__); - if (level == RESUME_ENABLE) - imxfb_enable_controller(fbi); + imxfb_enable_controller(fbi); return 0; } #else @@ -542,9 +538,8 @@ static int __init imxfb_map_video_memory(struct fb_info *info) return fbi->map_cpu ? 0 : -ENOMEM; } -static int __init imxfb_probe(struct device *dev) +static int __init imxfb_probe(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); struct imxfb_info *fbi; struct fb_info *info; struct imxfb_mach_info *inf; @@ -557,21 +552,21 @@ static int __init imxfb_probe(struct device *dev) if(!res) return -ENODEV; - inf = dev->platform_data; + inf = pdev->dev.platform_data; if(!inf) { dev_err(dev,"No platform_data available\n"); return -ENOMEM; } - info = framebuffer_alloc(sizeof(struct imxfb_info), dev); + info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev); if(!info) return -ENOMEM; fbi = info->par; - dev_set_drvdata(dev, info); + platform_set_drvdata(pdev, info); - ret = imxfb_init_fbinfo(dev); + ret = imxfb_init_fbinfo(&pdev->dev); if( ret < 0 ) goto failed_init; @@ -625,22 +620,21 @@ failed_register: fb_dealloc_cmap(&info->cmap); failed_cmap: if (!inf->fixed_screen_cpu) - dma_free_writecombine(dev,fbi->map_size,fbi->map_cpu, + dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu, fbi->map_dma); failed_map: kfree(info->pseudo_palette); failed_regs: release_mem_region(res->start, res->end - res->start); failed_init: - dev_set_drvdata(dev, NULL); + platform_set_drvdata(pdev, NULL); framebuffer_release(info); return ret; } -static int imxfb_remove(struct device *dev) +static int imxfb_remove(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); - struct fb_info *info = dev_get_drvdata(dev); + struct fb_info *info = platform_get_drvdata(pdev); struct imxfb_info *fbi = info->par; struct resource *res; @@ -655,36 +649,37 @@ static int imxfb_remove(struct device *dev) framebuffer_release(info); release_mem_region(res->start, res->end - res->start + 1); - dev_set_drvdata(dev, NULL); + platform_set_drvdata(pdev, NULL); return 0; } -void imxfb_shutdown(struct device * dev) +void imxfb_shutdown(struct platform_device * dev) { - struct fb_info *info = dev_get_drvdata(dev); + struct fb_info *info = platform_get_drvdata(dev); struct imxfb_info *fbi = info->par; imxfb_disable_controller(fbi); } -static struct device_driver imxfb_driver = { - .name = "imx-fb", - .bus = &platform_bus_type, +static struct platform_driver imxfb_driver = { .probe = imxfb_probe, .suspend = imxfb_suspend, .resume = imxfb_resume, .remove = imxfb_remove, .shutdown = imxfb_shutdown, + .driver = { + .name = "imx-fb", + }, }; int __init imxfb_init(void) { - return driver_register(&imxfb_driver); + return platform_driver_register(&imxfb_driver); } static void __exit imxfb_cleanup(void) { - driver_unregister(&imxfb_driver); + platform_driver_unregister(&imxfb_driver); } module_init(imxfb_init); diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h index 011e1162655..f077ca34fab 100644 --- a/drivers/video/intelfb/intelfb.h +++ b/drivers/video/intelfb/intelfb.h @@ -10,7 +10,7 @@ /*** Version/name ***/ #define INTELFB_VERSION "0.9.2" #define INTELFB_MODULE_NAME "intelfb" -#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G" +#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM" /*** Debug/feature defines ***/ @@ -47,6 +47,7 @@ #define PCI_DEVICE_ID_INTEL_85XGM 0x3582 #define PCI_DEVICE_ID_INTEL_865G 0x2572 #define PCI_DEVICE_ID_INTEL_915G 0x2582 +#define PCI_DEVICE_ID_INTEL_915GM 0x2592 /* Size of MMIO region */ #define INTEL_REG_SIZE 0x80000 @@ -119,7 +120,8 @@ enum intel_chips { INTEL_855GM, INTEL_855GME, INTEL_865G, - INTEL_915G + INTEL_915G, + INTEL_915GM }; struct intelfb_hwstate { diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index bf62e6ed038..427689e584d 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -1,7 +1,7 @@ /* * intelfb * - * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G + * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM * integrated graphics chips. * * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org> @@ -122,7 +122,6 @@ #include <linux/pci.h> #include <linux/vmalloc.h> #include <linux/pagemap.h> -#include <linux/version.h> #include <asm/io.h> @@ -186,6 +185,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM }, { 0, } }; @@ -226,7 +226,7 @@ MODULE_DEVICE_TABLE(pci, intelfb_pci_table); static int accel = 1; static int vram = 4; -static int hwcursor = 1; +static int hwcursor = 0; static int mtrr = 1; static int fixed = 0; static int noinit = 0; @@ -549,10 +549,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Set base addresses. */ - if (ent->device == PCI_DEVICE_ID_INTEL_915G) { + if ((ent->device == PCI_DEVICE_ID_INTEL_915G) || + (ent->device == PCI_DEVICE_ID_INTEL_915GM)) { aperture_bar = 2; mmio_bar = 0; - /* Disable HW cursor on 915G (not implemented yet) */ + /* Disable HW cursor on 915G/M (not implemented yet) */ hwcursor = 0; } dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar); @@ -609,15 +610,9 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) dinfo->accel = 0; } - if (MB(voffset) < stolen_size) - offset = (stolen_size >> 12); - else - offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE; - /* Framebuffer parameters - Use all the stolen memory if >= vram */ - if (ROUND_UP_TO_PAGE(stolen_size) >= ((offset << 12) + MB(vram))) { + if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) { dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size); - dinfo->fb.offset = 0; dinfo->fbmem_gart = 0; } else { dinfo->fb.size = MB(vram); @@ -648,6 +643,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } + if (MB(voffset) < stolen_size) + offset = (stolen_size >> 12); + else + offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE; + /* set the mem offsets - set them after the already used pages */ if (dinfo->accel) { dinfo->ring.offset = offset + gtt_info.current_memory; @@ -662,10 +662,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) + (dinfo->cursor.size >> 12); } + /* Allocate memories (which aren't stolen) */ /* Map the fb and MMIO regions */ /* ioremap only up to the end of used aperture */ dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache - (dinfo->aperture.physical, (dinfo->fb.offset << 12) + (dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12) + dinfo->fb.size); if (!dinfo->aperture.virtual) { ERR_MSG("Cannot remap FB region.\n"); @@ -682,7 +683,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - /* Allocate memories (which aren't stolen) */ if (dinfo->accel) { if (!(dinfo->gtt_ring_mem = agp_allocate_memory(bridge, dinfo->ring.size >> 12, @@ -1484,7 +1484,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) #endif if (!dinfo->hwcursor) - return -ENXIO; + return -ENODEV; intelfbhw_cursor_hide(dinfo); diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 5bafc3c54db..624c4bc96f0 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -34,7 +34,6 @@ #include <linux/pci.h> #include <linux/vmalloc.h> #include <linux/pagemap.h> -#include <linux/version.h> #include <asm/io.h> @@ -99,6 +98,11 @@ intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset, *chipset = INTEL_915G; *mobile = 0; return 0; + case PCI_DEVICE_ID_INTEL_915GM: + *name = "Intel(R) 915GM"; + *chipset = INTEL_915GM; + *mobile = 1; + return 0; default: return 1; } diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index d8bac9e9784..5eb4d5c177b 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -669,7 +669,6 @@ static struct fb_ops kyrofb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __devinit kyrofb_probe(struct pci_dev *pdev, diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 7e1e7fb168b..376d4a171ec 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -51,7 +51,9 @@ static struct fb_ops leo_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = leo_mmap, .fb_ioctl = leo_ioctl, - .fb_cursor = soft_cursor, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sbusfb_compat_ioctl, +#endif }; #define LEO_OFF_LC_SS0_KRN 0x00200000UL diff --git a/drivers/video/logo/.gitignore b/drivers/video/logo/.gitignore new file mode 100644 index 00000000000..e48355f538f --- /dev/null +++ b/drivers/video/logo/.gitignore @@ -0,0 +1,7 @@ +# +# Generated files +# +*_mono.c +*_vga16.c +*_clut224.c +*_gray256.c diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig index 3e9ccf370ab..8cb7fb4db44 100644 --- a/drivers/video/logo/Kconfig +++ b/drivers/video/logo/Kconfig @@ -7,6 +7,8 @@ menu "Logo configuration" config LOGO bool "Bootup logo" depends on FB || SGI_NEWPORT_CONSOLE + help + Enable and select frame buffer bootup logos. config LOGO_LINUX_MONO bool "Standard black and white Linux logo" diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 4945a4c0220..cfc748e9427 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -589,7 +589,6 @@ static struct fb_ops macfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; void __init macfb_setup(char *options) diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 149680f8bcf..0fbd9b5149f 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -657,7 +657,6 @@ static int MGA1064_preinit(WPMINFO2) { /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ ACCESS_FBINFO(capable.text) = 1; ACCESS_FBINFO(capable.vxres) = vxres_mystique; - ACCESS_FBINFO(features.accel.has_cacheflush) = 1; ACCESS_FBINFO(outputs[0]).output = &m1064; ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; @@ -842,7 +841,6 @@ static int MGAG100_preinit(WPMINFO2) { /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ ACCESS_FBINFO(capable.text) = 1; ACCESS_FBINFO(capable.vxres) = vxres_g100; - ACCESS_FBINFO(features.accel.has_cacheflush) = 1; ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100 ? ACCESS_FBINFO(devflags.sgram) : 1; @@ -980,7 +978,7 @@ static void MGAG100_reset(WPMINFO2) { hw->MXoptionReg |= 0x40; /* FIXME... */ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); } - mga_setr(M_EXTVGA_INDEX, 0x06, 0x50); + mga_setr(M_EXTVGA_INDEX, 0x06, 0x00); } } if (ACCESS_FBINFO(devflags.g450dac)) { diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c index c7f3e132122..a5c825d9946 100644 --- a/drivers/video/matrox/matroxfb_accel.c +++ b/drivers/video/matrox/matroxfb_accel.c @@ -122,7 +122,7 @@ void matrox_cfbX_init(WPMINFO2) { ACCESS_FBINFO(fbops).fb_copyarea = cfb_copyarea; ACCESS_FBINFO(fbops).fb_fillrect = cfb_fillrect; ACCESS_FBINFO(fbops).fb_imageblit = cfb_imageblit; - ACCESS_FBINFO(fbops).fb_cursor = soft_cursor; + ACCESS_FBINFO(fbops).fb_cursor = NULL; accel = (ACCESS_FBINFO(fbcon).var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index e02da41f1b2..1e74f4cca53 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -264,7 +264,6 @@ static void matroxfb_disable_irq(WPMINFO2) { } int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) { - wait_queue_t __wait; struct matrox_vsync *vs; unsigned int cnt; int ret; @@ -286,7 +285,6 @@ int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) { if (ret) { return ret; } - init_waitqueue_entry(&__wait, current); cnt = vs->cnt; ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10); @@ -500,10 +498,6 @@ static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) { } else { xres_new = matroxfb_test_and_set_rounding(PMINFO xres, bpp); } - if (!xres_new) return 0; - if (xres != xres_new) { - printk(KERN_INFO "matroxfb: cannot set xres to %d, rounded up to %d\n", xres, xres_new); - } return xres_new; } @@ -1285,7 +1279,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi vaddr_t vm; unsigned int offs; unsigned int offs2; - unsigned char store, orig; + unsigned char orig; unsigned char bytes[32]; unsigned char* tmp; @@ -1301,16 +1295,12 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi orig = mga_inb(M_EXTVGA_DATA); mga_outb(M_EXTVGA_DATA, orig | 0x80); - store = mga_readb(vm, 0x1234); tmp = bytes; for (offs = 0x100000; offs < maxSize; offs += 0x200000) *tmp++ = mga_readb(vm, offs); for (offs = 0x100000; offs < maxSize; offs += 0x200000) mga_writeb(vm, offs, 0x02); - if (ACCESS_FBINFO(features.accel.has_cacheflush)) - mga_outb(M_CACHEFLUSH, 0x00); - else - mga_writeb(vm, 0x1234, 0x99); + mga_outb(M_CACHEFLUSH, 0x00); for (offs = 0x100000; offs < maxSize; offs += 0x200000) { if (mga_readb(vm, offs) != 0x02) break; @@ -1321,7 +1311,6 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi tmp = bytes; for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000) mga_writeb(vm, offs2, *tmp++); - mga_writeb(vm, 0x1234, store); mga_outb(M_EXTVGA_INDEX, 0x03); mga_outb(M_EXTVGA_DATA, orig); @@ -1430,6 +1419,20 @@ static struct board { MGA_1164, &vbMystique, "Mystique 220 (PCI)"}, + {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0x02, + 0, 0, + DEVF_VIDEO64BIT | DEVF_CROSS4MB, + 180000, + MGA_1064, + &vbMystique, + "Mystique (AGP)"}, + {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0xFF, + 0, 0, + DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + 220000, + MGA_1164, + &vbMystique, + "Mystique 220 (AGP)"}, #endif #ifdef CONFIG_FB_MATROX_G {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF, diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 85a0b255845..a8c47ad2cdb 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -272,10 +272,6 @@ struct matrox_DAC1064_features { u_int8_t xmiscctrl; }; -struct matrox_accel_features { - int has_cacheflush; -}; - /* current hardware status */ struct mavenregs { u_int8_t regs[256]; @@ -440,7 +436,6 @@ struct matrox_fb_info { struct { struct matrox_pll_features pll; struct matrox_DAC1064_features DAC1064; - struct matrox_accel_features accel; } features; struct { spinlock_t DAC; diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 429047ac615..d52d7d825c4 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -576,7 +576,6 @@ static struct fb_ops matroxfb_dh_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_var_screeninfo matroxfb_dh_defined = { diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c index f192d995d03..743e7ad26ac 100644 --- a/drivers/video/maxinefb.c +++ b/drivers/video/maxinefb.c @@ -113,7 +113,6 @@ static struct fb_ops maxinefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; int __init maxinefb_init(void) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 47516c44a39..1da2f84bdc2 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -251,6 +251,10 @@ static const struct fb_videomode modedb[] = { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */ + NULL, 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }, }; @@ -676,6 +680,8 @@ void fb_var_to_videomode(struct fb_videomode *mode, mode->sync = var->sync; mode->vmode = var->vmode & FB_VMODE_MASK; mode->flag = FB_MODE_IS_FROM_VAR; + mode->refresh = 0; + if (!var->pixclock) return; @@ -785,39 +791,39 @@ struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var, } /** - * fb_find_nearest_mode - find mode closest video mode + * fb_find_nearest_mode - find closest videomode * - * @var: pointer to struct fb_var_screeninfo + * @mode: pointer to struct fb_videomode * @head: pointer to modelist * * Finds best matching videomode, smaller or greater in dimension. * If more than 1 videomode is found, will return the videomode with - * the closest refresh rate + * the closest refresh rate. */ -struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var, +struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, struct list_head *head) { struct list_head *pos; struct fb_modelist *modelist; - struct fb_videomode *mode, *best = NULL; + struct fb_videomode *cmode, *best = NULL; u32 diff = -1, diff_refresh = -1; list_for_each(pos, head) { u32 d; modelist = list_entry(pos, struct fb_modelist, list); - mode = &modelist->mode; + cmode = &modelist->mode; - d = abs(mode->xres - var->xres) + - abs(mode->yres - var->yres); + d = abs(cmode->xres - mode->xres) + + abs(cmode->yres - mode->yres); if (diff > d) { diff = d; - best = mode; + best = cmode; } else if (diff == d) { - d = abs(mode->refresh - best->refresh); + d = abs(cmode->refresh - mode->refresh); if (diff_refresh > d) { diff_refresh = d; - best = mode; + best = cmode; } } } @@ -942,6 +948,66 @@ void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, } } +struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs, + struct list_head *head) +{ + struct list_head *pos; + struct fb_modelist *modelist; + struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL; + int first = 0; + + if (!head->prev || !head->next || list_empty(head)) + goto finished; + + /* get the first detailed mode and the very first mode */ + list_for_each(pos, head) { + modelist = list_entry(pos, struct fb_modelist, list); + m = &modelist->mode; + + if (!first) { + m1 = m; + first = 1; + } + + if (m->flag & FB_MODE_IS_FIRST) { + md = m; + break; + } + } + + /* first detailed timing is preferred */ + if (specs->misc & FB_MISC_1ST_DETAIL) { + best = md; + goto finished; + } + + /* find best mode based on display width and height */ + if (specs->max_x && specs->max_y) { + struct fb_var_screeninfo var; + + memset(&var, 0, sizeof(struct fb_var_screeninfo)); + var.xres = (specs->max_x * 7200)/254; + var.yres = (specs->max_y * 7200)/254; + m = fb_find_best_mode(&var, head); + if (m) { + best = m; + goto finished; + } + } + + /* use first detailed mode */ + if (md) { + best = md; + goto finished; + } + + /* last resort, use the very first mode */ + best = m1; +finished: + return best; +} +EXPORT_SYMBOL(fb_find_best_display); + EXPORT_SYMBOL(fb_videomode_to_var); EXPORT_SYMBOL(fb_var_to_videomode); EXPORT_SYMBOL(fb_mode_is_equal); diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 5d424a30270..8486e77872d 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1665,7 +1665,6 @@ static struct fb_ops neofb_ops = { .fb_fillrect = neofb_fillrect, .fb_copyarea = neofb_copyarea, .fb_imageblit = neofb_imageblit, - .fb_cursor = soft_cursor, }; /* --------------------------------------------------------------------- */ diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h index afee284fc73..4243d7fae97 100644 --- a/drivers/video/nvidia/nv_local.h +++ b/drivers/video/nvidia/nv_local.h @@ -105,7 +105,7 @@ do { \ *a = byte_rev[*a]; \ } while(0) #else -#define reverse_order(l) +#define reverse_order(l) do { } while(0) #endif /* __LITTLE_ENDIAN */ #endif /* __NV_LOCAL_H__ */ diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c index 4fa2cf9a8af..7a03d040b1a 100644 --- a/drivers/video/nvidia/nv_of.c +++ b/drivers/video/nvidia/nv_of.c @@ -27,34 +27,60 @@ #include "nv_local.h" #include "nv_proto.h" -void nvidia_create_i2c_busses(struct nvidia_par *par) {} -void nvidia_delete_i2c_busses(struct nvidia_par *par) {} +#include "../edid.h" -int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) +int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) { struct nvidia_par *par = info->par; - struct device_node *dp; + struct device_node *parent, *dp; unsigned char *pedid = NULL; - unsigned char *disptype = NULL; static char *propnames[] = { - "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL }; + "DFP,EDID", "LCD,EDID", "EDID", "EDID1", + "EDID,B", "EDID,A", NULL }; int i; - dp = pci_device_to_OF_node(par->pci_dev); - for (; dp != NULL; dp = dp->child) { - disptype = (unsigned char *)get_property(dp, "display-type", NULL); - if (disptype == NULL) - continue; - if (strncmp(disptype, "LCD", 3) != 0) - continue; + parent = pci_device_to_OF_node(par->pci_dev); + if (parent == NULL) + return -1; + if (par->twoHeads) { + char *pname; + int len; + + for (dp = NULL; + (dp = of_get_next_child(parent, dp)) != NULL;) { + pname = (char *)get_property(dp, "name", NULL); + if (!pname) + continue; + len = strlen(pname); + if ((pname[len-1] == 'A' && conn == 1) || + (pname[len-1] == 'B' && conn == 2)) { + for (i = 0; propnames[i] != NULL; ++i) { + pedid = (unsigned char *) + get_property(dp, propnames[i], + NULL); + if (pedid != NULL) + break; + } + of_node_put(dp); + break; + } + } + } + if (pedid == NULL) { for (i = 0; propnames[i] != NULL; ++i) { pedid = (unsigned char *) - get_property(dp, propnames[i], NULL); - if (pedid != NULL) { - *out_edid = pedid; - return 0; - } + get_property(parent, propnames[i], NULL); + if (pedid != NULL) + break; } } - return 1; + if (pedid) { + *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (*out_edid == NULL) + return -1; + memcpy(*out_edid, pedid, EDID_LENGTH); + printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn); + return 0; + } + return -1; } diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index cac44fc7f58..3353103e8b0 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h @@ -31,7 +31,7 @@ int NVShowHideCursor(struct nvidia_par *par, int); void NVLockUnlock(struct nvidia_par *par, int); /* in nvidia-i2c.c */ -#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF) +#ifdef CONFIG_FB_NVIDIA_I2C void nvidia_create_i2c_busses(struct nvidia_par *par); void nvidia_delete_i2c_busses(struct nvidia_par *par); int nvidia_probe_i2c_connector(struct fb_info *info, int conn, @@ -39,10 +39,18 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, #else #define nvidia_create_i2c_busses(...) #define nvidia_delete_i2c_busses(...) -#define nvidia_probe_i2c_connector(p, c, edid) \ -do { \ - *(edid) = NULL; \ -} while(0) +#define nvidia_probe_i2c_connector(p, c, edid) (-1) +#endif + +#ifdef CONFIG_PPC_OF +int nvidia_probe_of_connector(struct fb_info *info, int conn, + u8 ** out_edid); +#else +static inline int nvidia_probe_of_connector(struct fb_info *info, int conn, + u8 ** out_edid) +{ + return -1; +} #endif /* in nv_accel.c */ diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index 11c84178f42..1f06a9f1bd0 100644 --- a/drivers/video/nvidia/nv_setup.c +++ b/drivers/video/nvidia/nv_setup.c @@ -190,9 +190,9 @@ static int NVIsConnected(struct nvidia_par *par, int output) present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0; if (present) - printk("nvidiafb: CRTC%i found\n", output); + printk("nvidiafb: CRTC%i analog found\n", output); else - printk("nvidiafb: CRTC%i not found\n", output); + printk("nvidiafb: CRTC%i analog not found\n", output); NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) & 0x0000EFFF); @@ -305,6 +305,9 @@ void NVCommonSetup(struct fb_info *info) int FlatPanel = -1; /* really means the CRTC is slaved */ int Television = 0; + memset(&monitorA, 0, sizeof(struct fb_monspecs)); + memset(&monitorB, 0, sizeof(struct fb_monspecs)); + par->PRAMIN = par->REGS + (0x00710000 / 4); par->PCRTC0 = par->REGS + (0x00600000 / 4); par->PRAMDAC0 = par->REGS + (0x00680000 / 4); @@ -401,7 +404,8 @@ void NVCommonSetup(struct fb_info *info) nvidia_create_i2c_busses(par); if (!par->twoHeads) { par->CRTCnumber = 0; - nvidia_probe_i2c_connector(info, 1, &edidA); + if (nvidia_probe_i2c_connector(info, 1, &edidA)) + nvidia_probe_of_connector(info, 1, &edidA); if (edidA && !fb_parse_edid(edidA, &var)) { printk("nvidiafb: EDID found from BUS1\n"); monA = &monitorA; @@ -488,14 +492,16 @@ void NVCommonSetup(struct fb_info *info) oldhead = NV_RD32(par->PCRTC0, 0x00000860); NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010); - nvidia_probe_i2c_connector(info, 1, &edidA); + if (nvidia_probe_i2c_connector(info, 1, &edidA)) + nvidia_probe_of_connector(info, 1, &edidA); if (edidA && !fb_parse_edid(edidA, &var)) { printk("nvidiafb: EDID found from BUS1\n"); monA = &monitorA; fb_edid_to_monspecs(edidA, monA); } - nvidia_probe_i2c_connector(info, 2, &edidB); + if (nvidia_probe_i2c_connector(info, 2, &edidB)) + nvidia_probe_of_connector(info, 2, &edidB); if (edidB && !fb_parse_edid(edidB, &var)) { printk("nvidiafb: EDID found from BUS2\n"); monB = &monitorB; diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index a7f020ada63..bee09c6e48f 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -384,6 +384,14 @@ static struct pci_device_id nvidiafb_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x021d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x021e, @@ -403,6 +411,7 @@ MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl); /* command line data, set in nvidiafb_setup() */ static int flatpanel __devinitdata = -1; /* Autodetect later */ +static int fpdither __devinitdata = -1; static int forceCRTC __devinitdata = -1; static int hwcur __devinitdata = 0; static int noaccel __devinitdata = 0; @@ -619,41 +628,85 @@ static void nvidia_save_vga(struct nvidia_par *par, NVTRACE_LEAVE(); } +#undef DUMP_REG + static void nvidia_write_regs(struct nvidia_par *par) { struct _riva_hw_state *state = &par->ModeReg; int i; NVTRACE_ENTER(); - NVWriteCrtc(par, 0x11, 0x00); - - NVLockUnlock(par, 0); NVLoadStateExt(par, state); NVWriteMiscOut(par, state->misc_output); + for (i = 1; i < NUM_SEQ_REGS; i++) { +#ifdef DUMP_REG + printk(" SEQ[%02x] = %08x\n", i, state->seq[i]); +#endif + NVWriteSeq(par, i, state->seq[i]); + } + + /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */ + NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80); + for (i = 0; i < NUM_CRT_REGS; i++) { switch (i) { case 0x19: case 0x20 ... 0x40: break; default: +#ifdef DUMP_REG + printk("CRTC[%02x] = %08x\n", i, state->crtc[i]); +#endif NVWriteCrtc(par, i, state->crtc[i]); } } - for (i = 0; i < NUM_ATC_REGS; i++) - NVWriteAttr(par, i, state->attr[i]); - - for (i = 0; i < NUM_GRC_REGS; i++) + for (i = 0; i < NUM_GRC_REGS; i++) { +#ifdef DUMP_REG + printk(" GRA[%02x] = %08x\n", i, state->gra[i]); +#endif NVWriteGr(par, i, state->gra[i]); + } + + for (i = 0; i < NUM_ATC_REGS; i++) { +#ifdef DUMP_REG + printk("ATTR[%02x] = %08x\n", i, state->attr[i]); +#endif + NVWriteAttr(par, i, state->attr[i]); + } - for (i = 0; i < NUM_SEQ_REGS; i++) - NVWriteSeq(par, i, state->seq[i]); NVTRACE_LEAVE(); } +static void nvidia_vga_protect(struct nvidia_par *par, int on) +{ + unsigned char tmp; + + if (on) { + /* + * Turn off screen and disable sequencer. + */ + tmp = NVReadSeq(par, 0x01); + + NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ + NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ + } else { + /* + * Reenable sequencer, then turn on screen. + */ + + tmp = NVReadSeq(par, 0x01); + + NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ + NVWriteSeq(par, 0x00, 0x03); /* End Reset */ + } +} + + + static int nvidia_calc_regs(struct fb_info *info) { struct nvidia_par *par = info->par; @@ -860,7 +913,7 @@ static void nvidia_init_vga(struct fb_info *info) for (i = 0; i < 0x10; i++) state->attr[i] = i; state->attr[0x10] = 0x41; - state->attr[0x11] = 0x01; + state->attr[0x11] = 0xff; state->attr[0x12] = 0x0f; state->attr[0x13] = 0x00; state->attr[0x14] = 0x00; @@ -974,16 +1027,24 @@ static int nvidiafb_set_par(struct fb_info *info) NVTRACE_ENTER(); NVLockUnlock(par, 1); - if (!par->FlatPanel || (info->var.bits_per_pixel != 24) || - !par->twoHeads) + if (!par->FlatPanel || !par->twoHeads) par->FPDither = 0; + if (par->FPDither < 0) { + if ((par->Chipset & 0x0ff0) == 0x0110) + par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x0528) + & 0x00010000); + else + par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1); + printk(KERN_INFO PFX "Flat panel dithering %s\n", + par->FPDither ? "enabled" : "disabled"); + } + info->fix.visual = (info->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; nvidia_init_vga(info); nvidia_calc_regs(info); - nvidia_write_regs(par); NVLockUnlock(par, 0); if (par->twoHeads) { @@ -992,7 +1053,22 @@ static int nvidiafb_set_par(struct fb_info *info) NVLockUnlock(par, 0); } - NVWriteCrtc(par, 0x11, 0x00); + nvidia_vga_protect(par, 1); + + nvidia_write_regs(par); + +#if defined (__BIG_ENDIAN) + /* turn on LFB swapping */ + { + unsigned char tmp; + + VGA_WR08(par->PCIO, 0x3d4, 0x46); + tmp = VGA_RD08(par->PCIO, 0x3d5); + tmp |= (1 << 7); + VGA_WR08(par->PCIO, 0x3d5, tmp); + } +#endif + info->fix.line_length = (info->var.xres_virtual * info->var.bits_per_pixel) >> 3; if (info->var.accel_flags) { @@ -1014,7 +1090,7 @@ static int nvidiafb_set_par(struct fb_info *info) par->cursor_reset = 1; - NVWriteCrtc(par, 0x11, 0xff); + nvidia_vga_protect(par, 0); NVTRACE_LEAVE(); return 0; @@ -1225,7 +1301,7 @@ static int nvidiafb_pan_display(struct fb_var_screeninfo *var, struct nvidia_par *par = info->par; u32 total; - total = info->var.yoffset * info->fix.line_length + info->var.xoffset; + total = var->yoffset * info->fix.line_length + var->xoffset; NVSetStartAddress(par, total); @@ -1307,22 +1383,10 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) fb_var_to_videomode(&modedb, &nvidiafb_default_var); if (specs->modedb != NULL) { - /* get preferred timing */ - if (specs->misc & FB_MISC_1ST_DETAIL) { - int i; - - for (i = 0; i < specs->modedb_len; i++) { - if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { - modedb = specs->modedb[i]; - break; - } - } - } else { - /* otherwise, get first mode in database */ - modedb = specs->modedb[0]; - } + struct fb_videomode *modedb; - fb_videomode_to_var(&nvidiafb_default_var, &modedb); + modedb = fb_find_best_display(specs, &info->modelist); + fb_videomode_to_var(&nvidiafb_default_var, modedb); nvidiafb_default_var.bits_per_pixel = 8; } else if (par->fpWidth && par->fpHeight) { char buf[16]; @@ -1357,7 +1421,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) info->pixmap.flags = FB_PIXMAP_SYSTEM; if (!hwcur) - info->fbops->fb_cursor = soft_cursor; + info->fbops->fb_cursor = NULL; info->var.accel_flags = (!noaccel); @@ -1482,9 +1546,9 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4); par->FlatPanel = flatpanel; - if (flatpanel == 1) printk(KERN_INFO PFX "flatpanel support enabled\n"); + par->FPDither = fpdither; par->CRTCnumber = forceCRTC; par->FpScale = (!noscale); @@ -1663,6 +1727,8 @@ static int __devinit nvidiafb_setup(char *options) } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1; #endif + } else if (!strncmp(this_opt, "fpdither:", 9)) { + fpdither = simple_strtol(this_opt+9, NULL, 0); } else mode_option = this_opt; } @@ -1709,7 +1775,11 @@ module_exit(nvidiafb_exit); module_param(flatpanel, int, 0); MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. " - "(0 or 1=enabled) (default=0)"); + "(0=disabled, 1=enabled, -1=autodetect) (default=-1)"); +module_param(fpdither, int, 0); +MODULE_PARM_DESC(fpdither, + "Enables dithering of flat panel for 6 bits panels. " + "(0=disabled, 1=enabled, -1=autodetect) (default=-1)"); module_param(hwcur, int, 0); MODULE_PARM_DESC(hwcur, "Enables hardware cursor implementation. (0 or 1=enabled) " diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 611922c0b22..00d87f5bb7b 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -26,6 +26,7 @@ #include <linux/fb.h> #include <linux/init.h> #include <linux/ioport.h> +#include <linux/pci.h> #include <asm/io.h> #include <asm/prom.h> @@ -85,7 +86,6 @@ static struct fb_ops offb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* @@ -326,8 +326,8 @@ static void __init offb_init_nodriver(struct device_node *dp) int *pp, i; unsigned int len; int width = 640, height = 480, depth = 8, pitch; - unsigned *up; - unsigned long address; + unsigned int rsize, *up; + unsigned long address = 0; if ((pp = (int *) get_property(dp, "depth", &len)) != NULL && len == sizeof(int)) @@ -345,10 +345,40 @@ static void __init offb_init_nodriver(struct device_node *dp) pitch = 0x1000; } else pitch = width; - if ((up = (unsigned *) get_property(dp, "address", &len)) != NULL - && len == sizeof(unsigned)) + + rsize = (unsigned long)pitch * (unsigned long)height * + (unsigned long)(depth / 8); + + /* Try to match device to a PCI device in order to get a properly + * translated address rather then trying to decode the open firmware + * stuff in various incorrect ways + */ +#ifdef CONFIG_PCI + /* First try to locate the PCI device if any */ + { + struct pci_dev *pdev = NULL; + + for_each_pci_dev(pdev) { + if (dp == pci_device_to_OF_node(pdev)) + break; + } + if (pdev) { + for (i = 0; i < 6 && address == 0; i++) { + if ((pci_resource_flags(pdev, i) & + IORESOURCE_MEM) && + (pci_resource_len(pdev, i) >= rsize)) + address = pci_resource_start(pdev, i); + } + pci_dev_put(pdev); + } + } +#endif /* CONFIG_PCI */ + + if (address == 0 && + (up = (unsigned *) get_property(dp, "address", &len)) != NULL && + len == sizeof(unsigned)) address = (u_long) * up; - else { + if (address == 0) { for (i = 0; i < dp->n_addrs; ++i) if (dp->addrs[i].size >= pitch * height * depth / 8) diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 7808a01493a..18bcda23d2c 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -48,7 +48,9 @@ static struct fb_ops p9100_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = p9100_mmap, .fb_ioctl = p9100_ioctl, - .fb_cursor = soft_cursor, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sbusfb_compat_ioctl, +#endif }; /* P9100 control registers */ @@ -288,6 +290,9 @@ static void p9100_init_one(struct sbus_dev *sdev) all->par.physbase = sdev->reg_addrs[2].phys_addr; sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); + all->info.var.red.length = 8; + all->info.var.green.length = 8; + all->info.var.blue.length = 8; linebytes = prom_getintdefault(sdev->prom_node, "linebytes", all->info.var.xres); @@ -323,6 +328,7 @@ static void p9100_init_one(struct sbus_dev *sdev) kfree(all); return; } + fb_set_cmap(&all->info.cmap, &all->info); list_add(&all->list, &p9100_list); diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index b00887e9851..ca4082ae5a1 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -109,7 +109,6 @@ static struct fb_ops platinumfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 42c17efa9fb..0277ce031e5 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1034,7 +1034,6 @@ static struct fb_ops pm2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* @@ -1121,6 +1120,22 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, default_par->mem_control, default_par->boot_address, default_par->mem_config); + if(default_par->mem_control == 0 && + default_par->boot_address == 0x31 && + default_par->mem_config == 0x259fffff && + pdev->subsystem_vendor == 0x1048 && + pdev->subsystem_device == 0x0a31) { + DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n", + pdev->subsystem_vendor, pdev->subsystem_device); + DPRINTK("We have not been initialized by VGA BIOS " + "and are running on an Elsa Winner 2000 Office\n"); + DPRINTK("Initializing card timings manually...\n"); + default_par->mem_control=0; + default_par->boot_address=0x20; + default_par->mem_config=0xe6002021; + default_par->memclock=100000; + } + /* Now work out how big lfb is going to be. */ switch(default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) { case PM2F_MEM_BANKS_1: diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index c98f1c8d7dc..f3927b6cda9 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -128,7 +128,6 @@ static struct fb_ops pmagbafb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index a483b13e117..25148de5fe6 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -132,7 +132,6 @@ static struct fb_ops pmagbbfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 31c547fd383..ec4bacf9dd2 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -230,7 +230,6 @@ static struct fb_ops pvr2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_videomode pvr2_modedb[] __initdata = { diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 34d4dcc0320..7b4cd250bec 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -36,7 +36,7 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/cpufreq.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <asm/hardware.h> @@ -260,9 +260,9 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) } #ifdef CONFIG_CPU_FREQ - DPRINTK("dma period = %d ps, clock = %d kHz\n", - pxafb_display_dma_period(var), - get_clk_frequency_khz(0)); + pr_debug("pxafb: dma period = %d ps, clock = %d kHz\n", + pxafb_display_dma_period(var), + get_clk_frequency_khz(0)); #endif return 0; @@ -270,7 +270,7 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static inline void pxafb_set_truecolor(u_int is_true_color) { - DPRINTK("true_color = %d\n", is_true_color); + pr_debug("pxafb: true_color = %d\n", is_true_color); // do your machine-specific setup if needed } @@ -284,7 +284,7 @@ static int pxafb_set_par(struct fb_info *info) struct fb_var_screeninfo *var = &info->var; unsigned long palette_mem_size; - DPRINTK("set_par\n"); + pr_debug("pxafb: set_par\n"); if (var->bits_per_pixel == 16) fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; @@ -308,7 +308,7 @@ static int pxafb_set_par(struct fb_info *info) palette_mem_size = fbi->palette_size * sizeof(u16); - DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); + pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size); fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; @@ -369,7 +369,7 @@ static int pxafb_blank(int blank, struct fb_info *info) struct pxafb_info *fbi = (struct pxafb_info *)info; int i; - DPRINTK("pxafb_blank: blank=%d\n", blank); + pr_debug("pxafb: blank=%d\n", blank); switch (blank) { case FB_BLANK_POWERDOWN: @@ -418,7 +418,6 @@ static struct fb_ops pxafb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = pxafb_blank, - .fb_cursor = soft_cursor, .fb_mmap = pxafb_mmap, }; @@ -508,15 +507,15 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * u_long flags; u_int lines_per_panel, pcd = get_pcd(var->pixclock); - DPRINTK("Configuring PXA LCD\n"); + pr_debug("pxafb: Configuring PXA LCD\n"); - DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n", - var->xres, var->hsync_len, - var->left_margin, var->right_margin); - DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n", - var->yres, var->vsync_len, - var->upper_margin, var->lower_margin); - DPRINTK("var: pixclock=%d pcd=%d\n", var->pixclock, pcd); + pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n", + var->xres, var->hsync_len, + var->left_margin, var->right_margin); + pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n", + var->yres, var->vsync_len, + var->upper_margin, var->lower_margin); + pr_debug("var: pixclock=%d pcd=%d\n", var->pixclock, pcd); #if DEBUG_VAR if (var->xres < 16 || var->xres > 1024) @@ -589,10 +588,10 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * if (pcd) new_regs.lccr3 |= LCCR3_PixClkDiv(pcd); - DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0); - DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1); - DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2); - DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3); + pr_debug("nlccr0 = 0x%08x\n", new_regs.lccr0); + pr_debug("nlccr1 = 0x%08x\n", new_regs.lccr1); + pr_debug("nlccr2 = 0x%08x\n", new_regs.lccr2); + pr_debug("nlccr3 = 0x%08x\n", new_regs.lccr3); /* Update shadow copy atomically */ local_irq_save(flags); @@ -637,24 +636,24 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * } #if 0 - DPRINTK("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu); - DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu); - DPRINTK("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu); - DPRINTK("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma); - DPRINTK("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma); - DPRINTK("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma); - - DPRINTK("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr); - DPRINTK("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr); - DPRINTK("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr); - - DPRINTK("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr); - DPRINTK("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr); - DPRINTK("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr); - - DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd); - DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd); - DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd); + pr_debug("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu); + pr_debug("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu); + pr_debug("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu); + pr_debug("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma); + pr_debug("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma); + pr_debug("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma); + + pr_debug("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr); + pr_debug("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr); + pr_debug("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr); + + pr_debug("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr); + pr_debug("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr); + pr_debug("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr); + + pr_debug("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd); + pr_debug("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd); + pr_debug("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd); #endif fbi->reg_lccr0 = new_regs.lccr0; @@ -684,7 +683,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * */ static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on) { - DPRINTK("backlight o%s\n", on ? "n" : "ff"); + pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff"); if (pxafb_backlight_power) pxafb_backlight_power(on); @@ -692,7 +691,7 @@ static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on) static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on) { - DPRINTK("LCD power o%s\n", on ? "n" : "ff"); + pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff"); if (pxafb_lcd_power) pxafb_lcd_power(on); @@ -740,13 +739,13 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi) static void pxafb_enable_controller(struct pxafb_info *fbi) { - DPRINTK("Enabling LCD controller\n"); - DPRINTK("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0); - DPRINTK("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1); - DPRINTK("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0); - DPRINTK("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1); - DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); - DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); + pr_debug("pxafb: Enabling LCD controller\n"); + pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0); + pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1); + pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0); + pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1); + pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); + pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); /* enable LCD controller clock */ pxa_set_cken(CKEN16_LCD, 1); @@ -761,19 +760,19 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) FDADR1 = fbi->fdadr1; LCCR0 |= LCCR0_ENB; - DPRINTK("FDADR0 0x%08x\n", (unsigned int) FDADR0); - DPRINTK("FDADR1 0x%08x\n", (unsigned int) FDADR1); - DPRINTK("LCCR0 0x%08x\n", (unsigned int) LCCR0); - DPRINTK("LCCR1 0x%08x\n", (unsigned int) LCCR1); - DPRINTK("LCCR2 0x%08x\n", (unsigned int) LCCR2); - DPRINTK("LCCR3 0x%08x\n", (unsigned int) LCCR3); + pr_debug("FDADR0 0x%08x\n", (unsigned int) FDADR0); + pr_debug("FDADR1 0x%08x\n", (unsigned int) FDADR1); + pr_debug("LCCR0 0x%08x\n", (unsigned int) LCCR0); + pr_debug("LCCR1 0x%08x\n", (unsigned int) LCCR1); + pr_debug("LCCR2 0x%08x\n", (unsigned int) LCCR2); + pr_debug("LCCR3 0x%08x\n", (unsigned int) LCCR3); } static void pxafb_disable_controller(struct pxafb_info *fbi) { DECLARE_WAITQUEUE(wait, current); - DPRINTK("Disabling LCD controller\n"); + pr_debug("pxafb: disabling LCD controller\n"); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&fbi->ctrlr_wait, &wait); @@ -981,21 +980,19 @@ pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data) * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int pxafb_suspend(struct device *dev, pm_message_t state, u32 level) +static int pxafb_suspend(struct platform_device *dev, pm_message_t state) { - struct pxafb_info *fbi = dev_get_drvdata(dev); + struct pxafb_info *fbi = platform_get_drvdata(dev); - if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) - set_ctrlr_state(fbi, C_DISABLE_PM); + set_ctrlr_state(fbi, C_DISABLE_PM); return 0; } -static int pxafb_resume(struct device *dev, u32 level) +static int pxafb_resume(struct platform_device *dev) { - struct pxafb_info *fbi = dev_get_drvdata(dev); + struct pxafb_info *fbi = platform_get_drvdata(dev); - if (level == RESUME_ENABLE) - set_ctrlr_state(fbi, C_ENABLE_PM); + set_ctrlr_state(fbi, C_ENABLE_PM); return 0; } #else @@ -1039,7 +1036,7 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi) fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16; palette_mem_size = fbi->palette_size * sizeof(u16); - DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); + pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size); fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; @@ -1271,7 +1268,7 @@ static int __init pxafb_parse_options(struct device *dev, char *options) } #endif -int __init pxafb_probe(struct device *dev) +int __init pxafb_probe(struct platform_device *dev) { struct pxafb_info *fbi; struct pxafb_mach_info *inf; @@ -1279,14 +1276,14 @@ int __init pxafb_probe(struct device *dev) dev_dbg(dev, "pxafb_probe\n"); - inf = dev->platform_data; + inf = dev->dev.platform_data; ret = -ENOMEM; fbi = NULL; if (!inf) goto failed; #ifdef CONFIG_FB_PXA_PARAMETERS - ret = pxafb_parse_options(dev, g_options); + ret = pxafb_parse_options(&dev->dev, g_options); if (ret < 0) goto failed; #endif @@ -1296,36 +1293,36 @@ int __init pxafb_probe(struct device *dev) * a warning is given. */ if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK) - dev_warn(dev, "machine LCCR0 setting contains illegal bits: %08x\n", + dev_warn(&dev->dev, "machine LCCR0 setting contains illegal bits: %08x\n", inf->lccr0 & LCCR0_INVALID_CONFIG_MASK); if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK) - dev_warn(dev, "machine LCCR3 setting contains illegal bits: %08x\n", + dev_warn(&dev->dev, "machine LCCR3 setting contains illegal bits: %08x\n", inf->lccr3 & LCCR3_INVALID_CONFIG_MASK); if (inf->lccr0 & LCCR0_DPD && ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas || (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl || (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono)) - dev_warn(dev, "Double Pixel Data (DPD) mode is only valid in passive mono" + dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is only valid in passive mono" " single panel mode\n"); if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act && (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual) - dev_warn(dev, "Dual panel only valid in passive mode\n"); + dev_warn(&dev->dev, "Dual panel only valid in passive mode\n"); if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas && (inf->upper_margin || inf->lower_margin)) - dev_warn(dev, "Upper and lower margins must be 0 in passive mode\n"); + dev_warn(&dev->dev, "Upper and lower margins must be 0 in passive mode\n"); #endif - dev_dbg(dev, "got a %dx%dx%d LCD\n",inf->xres, inf->yres, inf->bpp); + dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",inf->xres, inf->yres, inf->bpp); if (inf->xres == 0 || inf->yres == 0 || inf->bpp == 0) { - dev_err(dev, "Invalid resolution or bit depth\n"); + dev_err(&dev->dev, "Invalid resolution or bit depth\n"); ret = -EINVAL; goto failed; } pxafb_backlight_power = inf->pxafb_backlight_power; pxafb_lcd_power = inf->pxafb_lcd_power; - fbi = pxafb_init_fbinfo(dev); + fbi = pxafb_init_fbinfo(&dev->dev); if (!fbi) { - dev_err(dev, "Failed to initialize framebuffer device\n"); + dev_err(&dev->dev, "Failed to initialize framebuffer device\n"); ret = -ENOMEM; // only reason for pxafb_init_fbinfo to fail is kmalloc goto failed; } @@ -1333,14 +1330,14 @@ int __init pxafb_probe(struct device *dev) /* Initialize video memory */ ret = pxafb_map_video_memory(fbi); if (ret) { - dev_err(dev, "Failed to allocate video RAM: %d\n", ret); + dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret); ret = -ENOMEM; goto failed; } ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi); if (ret) { - dev_err(dev, "request_irq failed: %d\n", ret); + dev_err(&dev->dev, "request_irq failed: %d\n", ret); ret = -EBUSY; goto failed; } @@ -1352,11 +1349,11 @@ int __init pxafb_probe(struct device *dev) pxafb_check_var(&fbi->fb.var, &fbi->fb); pxafb_set_par(&fbi->fb); - dev_set_drvdata(dev, fbi); + platform_set_drvdata(dev, fbi); ret = register_framebuffer(&fbi->fb); if (ret < 0) { - dev_err(dev, "Failed to register framebuffer device: %d\n", ret); + dev_err(&dev->dev, "Failed to register framebuffer device: %d\n", ret); goto failed; } @@ -1379,19 +1376,20 @@ int __init pxafb_probe(struct device *dev) return 0; failed: - dev_set_drvdata(dev, NULL); + platform_set_drvdata(dev, NULL); kfree(fbi); return ret; } -static struct device_driver pxafb_driver = { - .name = "pxa2xx-fb", - .bus = &platform_bus_type, +static struct platform_driver pxafb_driver = { .probe = pxafb_probe, #ifdef CONFIG_PM .suspend = pxafb_suspend, .resume = pxafb_resume, #endif + .driver = { + .name = "pxa2xx-fb", + }, }; #ifndef MODULE @@ -1418,7 +1416,7 @@ int __devinit pxafb_init(void) return -ENODEV; pxafb_setup(option); #endif - return driver_register(&pxafb_driver); + return platform_driver_register(&pxafb_driver); } module_init(pxafb_init); diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h index 22c00be786a..47f41f70db7 100644 --- a/drivers/video/pxafb.h +++ b/drivers/video/pxafb.h @@ -114,15 +114,6 @@ struct pxafb_info { #define PXA_NAME "PXA" /* - * Debug macros - */ -#if DEBUG -# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -/* * Minimum X and Y resolutions */ #define MIN_XRES 64 diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 162012bb926..fc91dbf896d 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c @@ -18,6 +18,7 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> #include <asm/uaccess.h> #include <asm/setup.h> @@ -83,12 +84,10 @@ static struct fb_ops q40fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; -static int __init q40fb_probe(struct device *device) +static int __init q40fb_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(device); struct fb_info *info; if (!MACH_IS_Q40) @@ -128,10 +127,11 @@ static int __init q40fb_probe(struct device *device) return 0; } -static struct device_driver q40fb_driver = { - .name = "q40fb", - .bus = &platform_bus_type, +static struct platform_driver q40fb_driver = { .probe = q40fb_probe, + .driver = { + .name = "q40fb", + }, }; static struct platform_device q40fb_device = { @@ -145,12 +145,12 @@ int __init q40fb_init(void) if (fb_get_options("q40fb", NULL)) return -ENODEV; - ret = driver_register(&q40fb_driver); + ret = platform_driver_register(&q40fb_driver); if (!ret) { ret = platform_device_register(&q40fb_device); if (ret) - driver_unregister(&q40fb_driver); + platform_driver_unregister(&q40fb_driver); } return ret; } diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index a78b9bd8f89..600318f708f 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -2218,7 +2218,6 @@ static struct fb_ops radeonfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index fa98d91c42e..e5d0f92eeae 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -30,7 +30,7 @@ #include <linux/config.h> #include <linux/module.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/delay.h> #include <linux/types.h> @@ -388,7 +388,6 @@ static struct fb_ops s1d13xxxfb_fbops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor }; static int s1d13xxxfb_width_tab[2][4] __devinitdata = { @@ -504,10 +503,9 @@ s1d13xxxfb_fetch_hw_state(struct fb_info *info) static int -s1d13xxxfb_remove(struct device *dev) +s1d13xxxfb_remove(struct platform_device *pdev) { - struct fb_info *info = dev_get_drvdata(dev); - struct platform_device *pdev = to_platform_device(dev); + struct fb_info *info = platform_get_drvdata(pdev); struct s1d13xxxfb_par *par = NULL; if (info) { @@ -535,9 +533,8 @@ s1d13xxxfb_remove(struct device *dev) } static int __devinit -s1d13xxxfb_probe(struct device *dev) +s1d13xxxfb_probe(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); struct s1d13xxxfb_par *default_par; struct fb_info *info; struct s1d13xxxfb_pdata *pdata = NULL; @@ -549,8 +546,8 @@ s1d13xxxfb_probe(struct device *dev) printk(KERN_INFO "Epson S1D13XXX FB Driver\n"); /* enable platform-dependent hardware glue, if any */ - if (dev->platform_data) - pdata = dev->platform_data; + if (pdev->dev.platform_data) + pdata = pdev->dev.platform_data; if (pdata && pdata->platform_init_video) pdata->platform_init_video(); @@ -573,14 +570,14 @@ s1d13xxxfb_probe(struct device *dev) if (!request_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start +1, "s1d13xxxfb mem")) { - dev_dbg(dev, "request_mem_region failed\n"); + dev_dbg(&pdev->dev, "request_mem_region failed\n"); ret = -EBUSY; goto bail; } if (!request_mem_region(pdev->resource[1].start, pdev->resource[1].end - pdev->resource[1].start +1, "s1d13xxxfb regs")) { - dev_dbg(dev, "request_mem_region failed\n"); + dev_dbg(&pdev->dev, "request_mem_region failed\n"); ret = -EBUSY; goto bail; } @@ -641,7 +638,7 @@ s1d13xxxfb_probe(struct device *dev) goto bail; } - dev_set_drvdata(&pdev->dev, info); + platform_set_drvdata(pdev, info); printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); @@ -649,15 +646,15 @@ s1d13xxxfb_probe(struct device *dev) return 0; bail: - s1d13xxxfb_remove(dev); + s1d13xxxfb_remove(pdev); return ret; } #ifdef CONFIG_PM -static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state, u32 level) +static int s1d13xxxfb_suspend(struct platform_device *dev, pm_message_t state) { - struct fb_info *info = dev_get_drvdata(dev); + struct fb_info *info = platform_get_drvdata(dev); struct s1d13xxxfb_par *s1dfb = info->par; struct s1d13xxxfb_pdata *pdata = NULL; @@ -665,8 +662,8 @@ static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state, u32 level) lcd_enable(s1dfb, 0); crt_enable(s1dfb, 0); - if (dev->platform_data) - pdata = dev->platform_data; + if (dev->dev.platform_data) + pdata = dev->dev.platform_data; #if 0 if (!s1dfb->disp_save) @@ -702,15 +699,12 @@ static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state, u32 level) return 0; } -static int s1d13xxxfb_resume(struct device *dev, u32 level) +static int s1d13xxxfb_resume(struct platform_device *dev) { - struct fb_info *info = dev_get_drvdata(dev); + struct fb_info *info = platform_get_drvdata(dev); struct s1d13xxxfb_par *s1dfb = info->par; struct s1d13xxxfb_pdata *pdata = NULL; - if (level != RESUME_ENABLE) - return 0; - /* awaken the chip */ s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10); @@ -718,8 +712,8 @@ static int s1d13xxxfb_resume(struct device *dev, u32 level) while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01)) udelay(10); - if (dev->platform_data) - pdata = dev->platform_data; + if (dev->dev.platform_data) + pdata = dev->dev.platform_data; if (s1dfb->regs_save) { /* will write RO regs, *should* get away with it :) */ @@ -745,15 +739,16 @@ static int s1d13xxxfb_resume(struct device *dev, u32 level) } #endif /* CONFIG_PM */ -static struct device_driver s1d13xxxfb_driver = { - .name = S1D_DEVICENAME, - .bus = &platform_bus_type, +static struct platform_driver s1d13xxxfb_driver = { .probe = s1d13xxxfb_probe, .remove = s1d13xxxfb_remove, #ifdef CONFIG_PM .suspend = s1d13xxxfb_suspend, - .resume = s1d13xxxfb_resume + .resume = s1d13xxxfb_resume, #endif + .driver = { + .name = S1D_DEVICENAME, + }, }; @@ -763,14 +758,14 @@ s1d13xxxfb_init(void) if (fb_get_options("s1d13xxxfb", NULL)) return -ENODEV; - return driver_register(&s1d13xxxfb_driver); + return platform_driver_register(&s1d13xxxfb_driver); } static void __exit s1d13xxxfb_exit(void) { - driver_unregister(&s1d13xxxfb_driver); + platform_driver_unregister(&s1d13xxxfb_driver); } module_init(s1d13xxxfb_init); diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 00c0223a352..ce6e749db3a 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -86,6 +86,7 @@ #include <linux/interrupt.h> #include <linux/workqueue.h> #include <linux/wait.h> +#include <linux/platform_device.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -228,8 +229,8 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, * information */ -static int s3c2410fb_activate_var(struct s3c2410fb_info *fbi, - struct fb_var_screeninfo *var) +static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi, + struct fb_var_screeninfo *var) { fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK; @@ -494,7 +495,6 @@ static struct fb_ops s3c2410fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; @@ -634,19 +634,18 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r) static char driver_name[]="s3c2410fb"; -int __init s3c2410fb_probe(struct device *dev) +int __init s3c2410fb_probe(struct platform_device *pdev) { struct s3c2410fb_info *info; struct fb_info *fbinfo; - struct platform_device *pdev = to_platform_device(dev); struct s3c2410fb_hw *mregs; int ret; int irq; int i; - mach_info = dev->platform_data; + mach_info = pdev->dev.platform_data; if (mach_info == NULL) { - dev_err(dev,"no platform data for lcd, cannot attach\n"); + dev_err(&pdev->dev,"no platform data for lcd, cannot attach\n"); return -EINVAL; } @@ -654,11 +653,11 @@ int __init s3c2410fb_probe(struct device *dev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "no irq for device\n"); + dev_err(&pdev->dev, "no irq for device\n"); return -ENOENT; } - fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), dev); + fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev); if (!fbinfo) { return -ENOMEM; } @@ -666,7 +665,7 @@ int __init s3c2410fb_probe(struct device *dev) info = fbinfo->par; info->fb = fbinfo; - dev_set_drvdata(dev, fbinfo); + platform_set_drvdata(pdev, fbinfo); s3c2410fb_init_registers(info); @@ -676,7 +675,7 @@ int __init s3c2410fb_probe(struct device *dev) memcpy(&info->regs, &mach_info->regs, sizeof(info->regs)); - info->mach_info = dev->platform_data; + info->mach_info = pdev->dev.platform_data; fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; fbinfo->fix.type_aux = 0; @@ -735,7 +734,7 @@ int __init s3c2410fb_probe(struct device *dev) ret = request_irq(irq, s3c2410fb_irq, SA_INTERRUPT, pdev->name, info); if (ret) { - dev_err(dev, "cannot get irq %d - err %d\n", irq, ret); + dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); ret = -EBUSY; goto release_mem; } @@ -773,7 +772,7 @@ int __init s3c2410fb_probe(struct device *dev) } /* create device files */ - device_create_file(dev, &dev_attr_debug); + device_create_file(&pdev->dev, &dev_attr_debug); printk(KERN_INFO "fb%d: %s frame buffer device\n", fbinfo->node, fbinfo->fix.id); @@ -816,10 +815,9 @@ static void s3c2410fb_stop_lcd(void) /* * Cleanup */ -static int s3c2410fb_remove(struct device *dev) +static int s3c2410fb_remove(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); - struct fb_info *fbinfo = dev_get_drvdata(dev); + struct fb_info *fbinfo = platform_get_drvdata(pdev); struct s3c2410fb_info *info = fbinfo->par; int irq; @@ -847,37 +845,32 @@ static int s3c2410fb_remove(struct device *dev) /* suspend and resume support for the lcd controller */ -static int s3c2410fb_suspend(struct device *dev, pm_message_t state, u32 level) +static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state) { - struct fb_info *fbinfo = dev_get_drvdata(dev); + struct fb_info *fbinfo = platform_get_drvdata(dev); struct s3c2410fb_info *info = fbinfo->par; - if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) { - s3c2410fb_stop_lcd(); + s3c2410fb_stop_lcd(); - /* sleep before disabling the clock, we need to ensure - * the LCD DMA engine is not going to get back on the bus - * before the clock goes off again (bjd) */ + /* sleep before disabling the clock, we need to ensure + * the LCD DMA engine is not going to get back on the bus + * before the clock goes off again (bjd) */ - msleep(1); - clk_disable(info->clk); - } + msleep(1); + clk_disable(info->clk); return 0; } -static int s3c2410fb_resume(struct device *dev, u32 level) +static int s3c2410fb_resume(struct platform_device *dev) { - struct fb_info *fbinfo = dev_get_drvdata(dev); + struct fb_info *fbinfo = platform_get_drvdata(dev); struct s3c2410fb_info *info = fbinfo->par; - if (level == RESUME_ENABLE) { - clk_enable(info->clk); - msleep(1); - - s3c2410fb_init_registers(info); + clk_enable(info->clk); + msleep(1); - } + s3c2410fb_init_registers(info); return 0; } @@ -887,23 +880,25 @@ static int s3c2410fb_resume(struct device *dev, u32 level) #define s3c2410fb_resume NULL #endif -static struct device_driver s3c2410fb_driver = { - .name = "s3c2410-lcd", - .bus = &platform_bus_type, +static struct platform_driver s3c2410fb_driver = { .probe = s3c2410fb_probe, + .remove = s3c2410fb_remove, .suspend = s3c2410fb_suspend, .resume = s3c2410fb_resume, - .remove = s3c2410fb_remove + .driver = { + .name = "s3c2410-lcd", + .owner = THIS_MODULE, + }, }; int __devinit s3c2410fb_init(void) { - return driver_register(&s3c2410fb_driver); + return platform_driver_register(&s3c2410fb_driver); } static void __exit s3c2410fb_cleanup(void) { - driver_unregister(&s3c2410fb_driver); + platform_driver_unregister(&s3c2410fb_driver); } diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index beeec7b5142..2ea1354e439 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -173,7 +173,7 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/cpufreq.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <asm/hardware.h> @@ -592,6 +592,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, return ret; } +#ifdef CONFIG_CPU_FREQ /* * sa1100fb_display_dma_period() * Calculate the minimum period (in picoseconds) between two DMA @@ -606,6 +607,7 @@ static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo */ return var->pixclock * 8 * 16 / var->bits_per_pixel; } +#endif /* * sa1100fb_check_var(): @@ -851,7 +853,6 @@ static struct fb_ops sa1100fb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = sa1100fb_blank, - .fb_cursor = soft_cursor, .fb_mmap = sa1100fb_mmap, }; @@ -1307,21 +1308,19 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val, * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int sa1100fb_suspend(struct device *dev, pm_message_t state, u32 level) +static int sa1100fb_suspend(struct platform_device *dev, pm_message_t state) { - struct sa1100fb_info *fbi = dev_get_drvdata(dev); + struct sa1100fb_info *fbi = platform_get_drvdata(dev); - if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) - set_ctrlr_state(fbi, C_DISABLE_PM); + set_ctrlr_state(fbi, C_DISABLE_PM); return 0; } -static int sa1100fb_resume(struct device *dev, u32 level) +static int sa1100fb_resume(struct platform_device *dev) { - struct sa1100fb_info *fbi = dev_get_drvdata(dev); + struct sa1100fb_info *fbi = platform_get_drvdata(dev); - if (level == RESUME_ENABLE) - set_ctrlr_state(fbi, C_ENABLE_PM); + set_ctrlr_state(fbi, C_ENABLE_PM); return 0; } #else @@ -1453,7 +1452,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) return fbi; } -static int __init sa1100fb_probe(struct device *dev) +static int __init sa1100fb_probe(struct platform_device *pdev) { struct sa1100fb_info *fbi; int ret; @@ -1461,7 +1460,7 @@ static int __init sa1100fb_probe(struct device *dev) if (!request_mem_region(0xb0100000, 0x10000, "LCD")) return -EBUSY; - fbi = sa1100fb_init_fbinfo(dev); + fbi = sa1100fb_init_fbinfo(&pdev->dev); ret = -ENOMEM; if (!fbi) goto failed; @@ -1489,7 +1488,7 @@ static int __init sa1100fb_probe(struct device *dev) */ sa1100fb_check_var(&fbi->fb.var, &fbi->fb); - dev_set_drvdata(dev, fbi); + platform_set_drvdata(pdev, fbi); ret = register_framebuffer(&fbi->fb); if (ret < 0) @@ -1506,18 +1505,19 @@ static int __init sa1100fb_probe(struct device *dev) return 0; failed: - dev_set_drvdata(dev, NULL); + platform_set_drvdata(pdev, NULL); kfree(fbi); release_mem_region(0xb0100000, 0x10000); return ret; } -static struct device_driver sa1100fb_driver = { - .name = "sa11x0-fb", - .bus = &platform_bus_type, +static struct platform_driver sa1100fb_driver = { .probe = sa1100fb_probe, .suspend = sa1100fb_suspend, .resume = sa1100fb_resume, + .driver = { + .name = "sa11x0-fb", + }, }; int __init sa1100fb_init(void) @@ -1525,7 +1525,7 @@ int __init sa1100fb_init(void) if (fb_get_options("sa1100fb", NULL)) return -ENODEV; - return driver_register(&sa1100fb_driver); + return platform_driver_register(&sa1100fb_driver); } int __init sa1100fb_setup(char *options) diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h index ea17f7e0482..58cfdfb4183 100644 --- a/drivers/video/savage/savagefb.h +++ b/drivers/video/savage/savagefb.h @@ -169,6 +169,7 @@ struct savagefb_par { struct savagefb_i2c_chan chan; unsigned char *edid; u32 pseudo_palette[16]; + int paletteEnabled; int pm_state; int display_type; int dvi; @@ -244,105 +245,150 @@ struct savagefb_par { /* IO functions */ +static inline u8 savage_in8(u32 addr, struct savagefb_par *par) +{ + return readb(par->mmio.vbase + addr); +} + +static inline u16 savage_in16(u32 addr, struct savagefb_par *par) +{ + return readw(par->mmio.vbase + addr); +} + +static inline u32 savage_in32(u32 addr, struct savagefb_par *par) +{ + return readl(par->mmio.vbase + addr); +} + +static inline void savage_out8(u32 addr, u8 val, struct savagefb_par *par) +{ + writeb(val, par->mmio.vbase + addr); +} + +static inline void savage_out16(u32 addr, u16 val, struct savagefb_par *par) +{ + writew(val, par->mmio.vbase + addr); +} + +static inline void savage_out32(u32 addr, u32 val, struct savagefb_par *par) +{ + writel(val, par->mmio.vbase + addr); +} + +static inline u8 vga_in8(int addr, struct savagefb_par *par) +{ + return savage_in8(0x8000 + addr, par); +} + +static inline u16 vga_in16(int addr, struct savagefb_par *par) +{ + return savage_in16(0x8000 + addr, par); +} + +static inline u8 vga_in32(int addr, struct savagefb_par *par) +{ + return savage_in32(0x8000 + addr, par); +} + +static inline void vga_out8(int addr, u8 val, struct savagefb_par *par) +{ + savage_out8(0x8000 + addr, val, par); +} + +static inline void vga_out16(int addr, u16 val, struct savagefb_par *par) +{ + savage_out16(0x8000 + addr, val, par); +} + +static inline void vga_out32(int addr, u32 val, struct savagefb_par *par) +{ + savage_out32(0x8000 + addr, val, par); +} -#define vga_in8(addr) (inb (addr)) -#define vga_in16(addr) (inw (addr)) -#define vga_in32(addr) (inl (addr)) +static inline u8 VGArCR (u8 index, struct savagefb_par *par) +{ + vga_out8(0x3d4, index, par); + return vga_in8(0x3d5, par); +} + +static inline u8 VGArGR (u8 index, struct savagefb_par *par) +{ + vga_out8(0x3ce, index, par); + return vga_in8(0x3cf, par); +} + +static inline u8 VGArSEQ (u8 index, struct savagefb_par *par) +{ + vga_out8(0x3c4, index, par); + return vga_in8(0x3c5, par); +} -#define vga_out8(addr,val) (outb ((val), (addr))) -#define vga_out16(addr,val) (outw ((val), (addr))) -#define vga_out32(addr,val) (outl ((val), (addr))) +static inline void VGAwCR(u8 index, u8 val, struct savagefb_par *par) +{ + vga_out8(0x3d4, index, par); + vga_out8(0x3d5, val, par); +} -#define savage_in16(addr) readw(par->mmio.vbase + (addr)) -#define savage_in32(addr) readl(par->mmio.vbase + (addr)) +static inline void VGAwGR(u8 index, u8 val, struct savagefb_par *par) +{ + vga_out8(0x3ce, index, par); + vga_out8(0x3cf, val, par); +} -#define savage_out16(addr,val) writew((val), par->mmio.vbase + (addr)) -#define savage_out32(addr,val) writel((val), par->mmio.vbase + (addr)) +static inline void VGAwSEQ(u8 index, u8 val, struct savagefb_par *par) +{ + vga_out8(0x3c4, index, par); + vga_out8 (0x3c5, val, par); +} -static inline u8 VGArCR (u8 index) +static inline void VGAenablePalette(struct savagefb_par *par) { - outb (index, 0x3d4); - return inb (0x3d5); + u8 tmp; + + tmp = vga_in8(0x3da, par); + vga_out8(0x3c0, 0x00, par); + par->paletteEnabled = 1; } -static inline u8 VGArGR (u8 index) +static inline void VGAdisablePalette(struct savagefb_par *par) { - outb (index, 0x3ce); - return inb (0x3cf); + u8 tmp; + + tmp = vga_in8(0x3da, par); + vga_out8(0x3c0, 0x20, par); + par->paletteEnabled = 0; } -static inline u8 VGArSEQ (u8 index) +static inline void VGAwATTR(u8 index, u8 value, struct savagefb_par *par) { - outb (index, 0x3c4); - return inb (0x3c5); + u8 tmp; + + if (par->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + tmp = vga_in8(0x3da, par); + vga_out8(0x3c0, index, par); + vga_out8 (0x3c0, value, par); } -#define VGAwCR(index, val) \ -do { \ - vga_out8 (0x3d4, index); \ - vga_out8 (0x3d5, val); \ -} while (0) - -#define VGAwGR(index, val) \ -do { \ - vga_out8 (0x3ce, index); \ - vga_out8 (0x3cf, val); \ -} while (0) - -#define VGAwSEQ(index, val) \ -do { \ - vga_out8 (0x3c4, index); \ - vga_out8 (0x3c5, val); \ -} while (0) - -#define VGAenablePalette() \ -do { \ - u8 tmp; \ - \ - tmp = vga_in8 (0x3da); \ - vga_out8 (0x3c0, 0x00); \ - paletteEnabled = 1; \ -} while (0) - -#define VGAdisablePalette() \ -do { \ - u8 tmp; \ - \ - tmp = vga_in8 (0x3da); \ - vga_out8 (0x3c0, 0x20); \ - paletteEnabled = 0; \ -} while (0) - -#define VGAwATTR(index, value) \ -do { \ - u8 tmp; \ - \ - if (paletteEnabled) \ - index &= ~0x20; \ - else \ - index |= 0x20; \ - \ - tmp = vga_in8 (0x3da); \ - vga_out8 (0x3c0, index); \ - vga_out8 (0x3c0, value); \ -} while (0) - -#define VGAwMISC(value) \ -do { \ - vga_out8 (0x3c2, value); \ -} while (0) +static inline void VGAwMISC(u8 value, struct savagefb_par *par) +{ + vga_out8(0x3c2, value, par); +} #ifndef CONFIG_FB_SAVAGE_ACCEL #define savagefb_set_clip(x) #endif -#define VerticalRetraceWait() \ -{ \ - vga_out8 (0x3d4, 0x17); \ - if (vga_in8 (0x3d5) & 0x80) { \ - while ((vga_in8(0x3da) & 0x08) == 0x08) ; \ - while ((vga_in8(0x3da) & 0x08) == 0x00) ; \ - } \ +static inline void VerticalRetraceWait(struct savagefb_par *par) +{ + vga_out8(0x3d4, 0x17, par); + if (vga_in8(0x3d5, par) & 0x80) { + while ((vga_in8(0x3da, par) & 0x08) == 0x08); + while ((vga_in8(0x3da, par) & 0x08) == 0x00); + } } extern int savagefb_probe_i2c_connector(struct fb_info *info, diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 7c285455c92..09e2f284190 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -74,7 +74,6 @@ static char *mode_option __initdata = NULL; -static int paletteEnabled = 0; #ifdef MODULE @@ -90,9 +89,9 @@ MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips"); static void vgaHWSeqReset (struct savagefb_par *par, int start) { if (start) - VGAwSEQ (0x00, 0x01); /* Synchronous Reset */ + VGAwSEQ (0x00, 0x01, par); /* Synchronous Reset */ else - VGAwSEQ (0x00, 0x03); /* End Reset */ + VGAwSEQ (0x00, 0x03, par); /* End Reset */ } static void vgaHWProtect (struct savagefb_par *par, int on) @@ -103,23 +102,23 @@ static void vgaHWProtect (struct savagefb_par *par, int on) /* * Turn off screen and disable sequencer. */ - tmp = VGArSEQ (0x01); + tmp = VGArSEQ (0x01, par); vgaHWSeqReset (par, 1); /* start synchronous reset */ - VGAwSEQ (0x01, tmp | 0x20); /* disable the display */ + VGAwSEQ (0x01, tmp | 0x20, par);/* disable the display */ - VGAenablePalette(); + VGAenablePalette(par); } else { /* * Reenable sequencer, then turn on screen. */ - tmp = VGArSEQ (0x01); + tmp = VGArSEQ (0x01, par); - VGAwSEQ (0x01, tmp & ~0x20); /* reenable display */ + VGAwSEQ (0x01, tmp & ~0x20, par);/* reenable display */ vgaHWSeqReset (par, 0); /* clear synchronous reset */ - VGAdisablePalette(); + VGAdisablePalette(par); } } @@ -127,27 +126,27 @@ static void vgaHWRestore (struct savagefb_par *par) { int i; - VGAwMISC (par->MiscOutReg); + VGAwMISC (par->MiscOutReg, par); for (i = 1; i < 5; i++) - VGAwSEQ (i, par->Sequencer[i]); + VGAwSEQ (i, par->Sequencer[i], par); /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */ - VGAwCR (17, par->CRTC[17] & ~0x80); + VGAwCR (17, par->CRTC[17] & ~0x80, par); for (i = 0; i < 25; i++) - VGAwCR (i, par->CRTC[i]); + VGAwCR (i, par->CRTC[i], par); for (i = 0; i < 9; i++) - VGAwGR (i, par->Graphics[i]); + VGAwGR (i, par->Graphics[i], par); - VGAenablePalette(); + VGAenablePalette(par); for (i = 0; i < 21; i++) - VGAwATTR (i, par->Attribute[i]); + VGAwATTR (i, par->Attribute[i], par); - VGAdisablePalette(); + VGAdisablePalette(par); } static void vgaHWInit (struct fb_var_screeninfo *var, @@ -267,7 +266,7 @@ savage3D_waitfifo(struct savagefb_par *par, int space) { int slots = MAXFIFO - space; - while ((savage_in32(0x48C00) & 0x0000ffff) > slots); + while ((savage_in32(0x48C00, par) & 0x0000ffff) > slots); } static void @@ -275,7 +274,7 @@ savage4_waitfifo(struct savagefb_par *par, int space) { int slots = MAXFIFO - space; - while ((savage_in32(0x48C60) & 0x001fffff) > slots); + while ((savage_in32(0x48C60, par) & 0x001fffff) > slots); } static void @@ -283,26 +282,26 @@ savage2000_waitfifo(struct savagefb_par *par, int space) { int slots = MAXFIFO - space; - while ((savage_in32(0x48C60) & 0x0000ffff) > slots); + while ((savage_in32(0x48C60, par) & 0x0000ffff) > slots); } /* Wait for idle accelerator */ static void savage3D_waitidle(struct savagefb_par *par) { - while ((savage_in32(0x48C00) & 0x0008ffff) != 0x80000); + while ((savage_in32(0x48C00, par) & 0x0008ffff) != 0x80000); } static void savage4_waitidle(struct savagefb_par *par) { - while ((savage_in32(0x48C60) & 0x00a00000) != 0x00a00000); + while ((savage_in32(0x48C60, par) & 0x00a00000) != 0x00a00000); } static void savage2000_waitidle(struct savagefb_par *par) { - while ((savage_in32(0x48C60) & 0x009fffff)); + while ((savage_in32(0x48C60, par) & 0x009fffff)); } @@ -319,59 +318,64 @@ SavageSetup2DEngine (struct savagefb_par *par) case S3_SAVAGE3D: case S3_SAVAGE_MX: /* Disable BCI */ - savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0); + savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par); /* Setup BCI command overflow buffer */ - savage_out32(0x48C14, (par->cob_offset >> 11) | (par->cob_index << 29)); + savage_out32(0x48C14, + (par->cob_offset >> 11) | (par->cob_index << 29), + par); /* Program shadow status update. */ - savage_out32(0x48C10, 0x78207220); - savage_out32(0x48C0C, 0); + savage_out32(0x48C10, 0x78207220, par); + savage_out32(0x48C0C, 0, par); /* Enable BCI and command overflow buffer */ - savage_out32(0x48C18, savage_in32(0x48C18) | 0x0C); + savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par); break; case S3_SAVAGE4: case S3_PROSAVAGE: case S3_SUPERSAVAGE: /* Disable BCI */ - savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0); + savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par); /* Program shadow status update */ - savage_out32(0x48C10, 0x00700040); - savage_out32(0x48C0C, 0); + savage_out32(0x48C10, 0x00700040, par); + savage_out32(0x48C0C, 0, par); /* Enable BCI without the COB */ - savage_out32(0x48C18, savage_in32(0x48C18) | 0x08); + savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x08, par); break; case S3_SAVAGE2000: /* Disable BCI */ - savage_out32(0x48C18, 0); + savage_out32(0x48C18, 0, par); /* Setup BCI command overflow buffer */ - savage_out32(0x48C18, (par->cob_offset >> 7) | (par->cob_index)); + savage_out32(0x48C18, + (par->cob_offset >> 7) | (par->cob_index), + par); /* Disable shadow status update */ - savage_out32(0x48A30, 0); + savage_out32(0x48A30, 0, par); /* Enable BCI and command overflow buffer */ - savage_out32(0x48C18, savage_in32(0x48C18) | 0x00280000 ); + savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x00280000, + par); break; default: break; } /* Turn on 16-bit register access. */ - vga_out8(0x3d4, 0x31); - vga_out8(0x3d5, 0x0c); + vga_out8(0x3d4, 0x31, par); + vga_out8(0x3d5, 0x0c, par); /* Set stride to use GBD. */ - vga_out8 (0x3d4, 0x50); - vga_out8 (0x3d5, vga_in8 (0x3d5 ) | 0xC1); + vga_out8 (0x3d4, 0x50, par); + vga_out8 (0x3d5, vga_in8(0x3d5, par) | 0xC1, par); /* Enable 2D engine. */ - vga_out8 (0x3d4, 0x40 ); - vga_out8 (0x3d5, 0x01 ); + vga_out8 (0x3d4, 0x40, par); + vga_out8 (0x3d5, 0x01, par); - savage_out32 (MONO_PAT_0, ~0); - savage_out32 (MONO_PAT_1, ~0); + savage_out32 (MONO_PAT_0, ~0, par); + savage_out32 (MONO_PAT_1, ~0, par); /* Setup plane masks */ - savage_out32 (0x8128, ~0 ); /* enable all write planes */ - savage_out32 (0x812C, ~0 ); /* enable all read planes */ - savage_out16 (0x8134, 0x27 ); - savage_out16 (0x8136, 0x07 ); + savage_out32 (0x8128, ~0, par); /* enable all write planes */ + savage_out32 (0x812C, ~0, par); /* enable all read planes */ + savage_out16 (0x8134, 0x27, par); + savage_out16 (0x8136, 0x07, par); /* Now set the GBD */ par->bci_ptr = 0; @@ -489,8 +493,8 @@ static void SavagePrintRegs(void) for( i = 0; i < 0x70; i++ ) { if( !(i % 16) ) printk(KERN_DEBUG "\nSR%xx ", i >> 4 ); - vga_out8( 0x3c4, i ); - printk(KERN_DEBUG " %02x", vga_in8(0x3c5) ); + vga_out8( 0x3c4, i, par); + printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par) ); } printk(KERN_DEBUG "\n\nCR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC " @@ -499,8 +503,8 @@ static void SavagePrintRegs(void) for( i = 0; i < 0xB7; i++ ) { if( !(i % 16) ) printk(KERN_DEBUG "\nCR%xx ", i >> 4 ); - vga_out8( vgaCRIndex, i ); - printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg) ); + vga_out8( vgaCRIndex, i, par); + printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par) ); } printk(KERN_DEBUG "\n\n"); @@ -513,152 +517,152 @@ static void savage_get_default_par(struct savagefb_par *par) { unsigned char cr3a, cr53, cr66; - vga_out16 (0x3d4, 0x4838); - vga_out16 (0x3d4, 0xa039); - vga_out16 (0x3c4, 0x0608); - - vga_out8 (0x3d4, 0x66); - cr66 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr66 | 0x80); - vga_out8 (0x3d4, 0x3a); - cr3a = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr3a | 0x80); - vga_out8 (0x3d4, 0x53); - cr53 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr53 & 0x7f); - - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66); - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, cr3a); - - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66); - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, cr3a); + vga_out16 (0x3d4, 0x4838, par); + vga_out16 (0x3d4, 0xa039, par); + vga_out16 (0x3c4, 0x0608, par); + + vga_out8 (0x3d4, 0x66, par); + cr66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr66 | 0x80, par); + vga_out8 (0x3d4, 0x3a, par); + cr3a = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr3a | 0x80, par); + vga_out8 (0x3d4, 0x53, par); + cr53 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr53 & 0x7f, par); + + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66, par); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, cr3a, par); + + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66, par); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, cr3a, par); /* unlock extended seq regs */ - vga_out8 (0x3c4, 0x08); - par->SR08 = vga_in8 (0x3c5); - vga_out8 (0x3c5, 0x06); + vga_out8 (0x3c4, 0x08, par); + par->SR08 = vga_in8 (0x3c5, par); + vga_out8 (0x3c5, 0x06, par); /* now save all the extended regs we need */ - vga_out8 (0x3d4, 0x31); - par->CR31 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x32); - par->CR32 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x34); - par->CR34 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x36); - par->CR36 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x3a); - par->CR3A = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x40); - par->CR40 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x42); - par->CR42 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x45); - par->CR45 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x50); - par->CR50 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x51); - par->CR51 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x53); - par->CR53 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x58); - par->CR58 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x60); - par->CR60 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x66); - par->CR66 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x67); - par->CR67 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x68); - par->CR68 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x69); - par->CR69 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x6f); - par->CR6F = vga_in8 (0x3d5); - - vga_out8 (0x3d4, 0x33); - par->CR33 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x86); - par->CR86 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x88); - par->CR88 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x90); - par->CR90 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x91); - par->CR91 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0xb0); - par->CRB0 = vga_in8 (0x3d5) | 0x80; + vga_out8 (0x3d4, 0x31, par); + par->CR31 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x32, par); + par->CR32 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x34, par); + par->CR34 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x36, par); + par->CR36 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x3a, par); + par->CR3A = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x40, par); + par->CR40 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x42, par); + par->CR42 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x45, par); + par->CR45 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x50, par); + par->CR50 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x51, par); + par->CR51 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x53, par); + par->CR53 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x58, par); + par->CR58 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x60, par); + par->CR60 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x66, par); + par->CR66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x67, par); + par->CR67 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x68, par); + par->CR68 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x69, par); + par->CR69 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x6f, par); + par->CR6F = vga_in8 (0x3d5, par); + + vga_out8 (0x3d4, 0x33, par); + par->CR33 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x86, par); + par->CR86 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x88, par); + par->CR88 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x90, par); + par->CR90 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x91, par); + par->CR91 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0xb0, par); + par->CRB0 = vga_in8 (0x3d5, par) | 0x80; /* extended mode timing regs */ - vga_out8 (0x3d4, 0x3b); - par->CR3B = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x3c); - par->CR3C = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x43); - par->CR43 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x5d); - par->CR5D = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x5e); - par->CR5E = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x65); - par->CR65 = vga_in8 (0x3d5); + vga_out8 (0x3d4, 0x3b, par); + par->CR3B = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x3c, par); + par->CR3C = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x43, par); + par->CR43 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x5d, par); + par->CR5D = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x5e, par); + par->CR5E = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x65, par); + par->CR65 = vga_in8 (0x3d5, par); /* save seq extended regs for DCLK PLL programming */ - vga_out8 (0x3c4, 0x0e); - par->SR0E = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x0f); - par->SR0F = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x10); - par->SR10 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x11); - par->SR11 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x12); - par->SR12 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x13); - par->SR13 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x29); - par->SR29 = vga_in8 (0x3c5); - - vga_out8 (0x3c4, 0x15); - par->SR15 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x30); - par->SR30 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x18); - par->SR18 = vga_in8 (0x3c5); + vga_out8 (0x3c4, 0x0e, par); + par->SR0E = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x0f, par); + par->SR0F = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x10, par); + par->SR10 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x11, par); + par->SR11 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x12, par); + par->SR12 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x13, par); + par->SR13 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x29, par); + par->SR29 = vga_in8 (0x3c5, par); + + vga_out8 (0x3c4, 0x15, par); + par->SR15 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x30, par); + par->SR30 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x18, par); + par->SR18 = vga_in8 (0x3c5, par); /* Save flat panel expansion regsters. */ if (par->chip == S3_SAVAGE_MX) { int i; for (i = 0; i < 8; i++) { - vga_out8 (0x3c4, 0x54+i); - par->SR54[i] = vga_in8 (0x3c5); + vga_out8 (0x3c4, 0x54+i, par); + par->SR54[i] = vga_in8 (0x3c5, par); } } - vga_out8 (0x3d4, 0x66); - cr66 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr66 | 0x80); - vga_out8 (0x3d4, 0x3a); - cr3a = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr3a | 0x80); + vga_out8 (0x3d4, 0x66, par); + cr66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr66 | 0x80, par); + vga_out8 (0x3d4, 0x3a, par); + cr3a = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr3a | 0x80, par); /* now save MIU regs */ if (par->chip != S3_SAVAGE_MX) { - par->MMPR0 = savage_in32(FIFO_CONTROL_REG); - par->MMPR1 = savage_in32(MIU_CONTROL_REG); - par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG); - par->MMPR3 = savage_in32(MISC_TIMEOUT_REG); + par->MMPR0 = savage_in32(FIFO_CONTROL_REG, par); + par->MMPR1 = savage_in32(MIU_CONTROL_REG, par); + par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG, par); + par->MMPR3 = savage_in32(MISC_TIMEOUT_REG, par); } - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, cr3a); - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, cr3a, par); + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66, par); } static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb) @@ -868,8 +872,8 @@ static int savagefb_decode_var (struct fb_var_screeninfo *var, * match. Fall back to traditional register-crunching. */ - vga_out8 (0x3d4, 0x3a); - tmp = vga_in8 (0x3d5); + vga_out8 (0x3d4, 0x3a, par); + tmp = vga_in8 (0x3d5, par); if (1 /*FIXME:psav->pci_burst*/) par->CR3A = (tmp & 0x7f) | 0x15; else @@ -879,16 +883,16 @@ static int savagefb_decode_var (struct fb_var_screeninfo *var, par->CR31 = 0x8c; par->CR66 = 0x89; - vga_out8 (0x3d4, 0x58); - par->CR58 = vga_in8 (0x3d5) & 0x80; + vga_out8 (0x3d4, 0x58, par); + par->CR58 = vga_in8 (0x3d5, par) & 0x80; par->CR58 |= 0x13; par->SR15 = 0x03 | 0x80; par->SR18 = 0x00; par->CR43 = par->CR45 = par->CR65 = 0x00; - vga_out8 (0x3d4, 0x40); - par->CR40 = vga_in8 (0x3d5) & ~0x01; + vga_out8 (0x3d4, 0x40, par); + par->CR40 = vga_in8 (0x3d5, par) & ~0x01; par->MMPR0 = 0x010400; par->MMPR1 = 0x00; @@ -992,19 +996,19 @@ static int savagefb_decode_var (struct fb_var_screeninfo *var, par->CR67 |= 1; - vga_out8(0x3d4, 0x36); - par->CR36 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x68); - par->CR68 = vga_in8 (0x3d5); + vga_out8(0x3d4, 0x36, par); + par->CR36 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x68, par); + par->CR68 = vga_in8 (0x3d5, par); par->CR69 = 0; - vga_out8 (0x3d4, 0x6f); - par->CR6F = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x86); - par->CR86 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x88); - par->CR88 = vga_in8 (0x3d5) | 0x08; - vga_out8 (0x3d4, 0xb0); - par->CRB0 = vga_in8 (0x3d5) | 0x80; + vga_out8 (0x3d4, 0x6f, par); + par->CR6F = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x86, par); + par->CR86 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x88, par); + par->CR88 = vga_in8 (0x3d5, par) | 0x08; + vga_out8 (0x3d4, 0xb0, par); + par->CRB0 = vga_in8 (0x3d5, par) | 0x80; return 0; } @@ -1033,11 +1037,11 @@ static int savagefb_setcolreg(unsigned regno, switch (info->var.bits_per_pixel) { case 8: - vga_out8 (0x3c8, regno); + vga_out8 (0x3c8, regno, par); - vga_out8 (0x3c9, red >> 10); - vga_out8 (0x3c9, green >> 10); - vga_out8 (0x3c9, blue >> 10); + vga_out8 (0x3c9, red >> 10, par); + vga_out8 (0x3c9, green >> 10, par); + vga_out8 (0x3c9, blue >> 10, par); break; case 16: @@ -1079,11 +1083,11 @@ static void savagefb_set_par_int (struct savagefb_par *par) par->SavageWaitIdle (par); - vga_out8 (0x3c2, 0x23); + vga_out8 (0x3c2, 0x23, par); - vga_out16 (0x3d4, 0x4838); - vga_out16 (0x3d4, 0xa539); - vga_out16 (0x3c4, 0x0608); + vga_out16 (0x3d4, 0x4838, par); + vga_out16 (0x3d4, 0xa539, par); + vga_out16 (0x3c4, 0x0608, par); vgaHWProtect (par, 1); @@ -1094,197 +1098,197 @@ static void savagefb_set_par_int (struct savagefb_par *par) * switch to mode 3 here seems to eliminate the issue. */ - VerticalRetraceWait(); - vga_out8 (0x3d4, 0x67); - cr67 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c); /* no STREAMS yet */ + VerticalRetraceWait(par); + vga_out8 (0x3d4, 0x67, par); + cr67 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */ - vga_out8 (0x3d4, 0x23); - vga_out8 (0x3d5, 0x00); - vga_out8 (0x3d4, 0x26); - vga_out8 (0x3d5, 0x00); + vga_out8 (0x3d4, 0x23, par); + vga_out8 (0x3d5, 0x00, par); + vga_out8 (0x3d4, 0x26, par); + vga_out8 (0x3d5, 0x00, par); /* restore extended regs */ - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, par->CR66); - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, par->CR3A); - vga_out8 (0x3d4, 0x31); - vga_out8 (0x3d5, par->CR31); - vga_out8 (0x3d4, 0x32); - vga_out8 (0x3d5, par->CR32); - vga_out8 (0x3d4, 0x58); - vga_out8 (0x3d5, par->CR58); - vga_out8 (0x3d4, 0x53); - vga_out8 (0x3d5, par->CR53 & 0x7f); - - vga_out16 (0x3c4, 0x0608); + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, par->CR66, par); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, par->CR3A, par); + vga_out8 (0x3d4, 0x31, par); + vga_out8 (0x3d5, par->CR31, par); + vga_out8 (0x3d4, 0x32, par); + vga_out8 (0x3d5, par->CR32, par); + vga_out8 (0x3d4, 0x58, par); + vga_out8 (0x3d5, par->CR58, par); + vga_out8 (0x3d4, 0x53, par); + vga_out8 (0x3d5, par->CR53 & 0x7f, par); + + vga_out16 (0x3c4, 0x0608, par); /* Restore DCLK registers. */ - vga_out8 (0x3c4, 0x0e); - vga_out8 (0x3c5, par->SR0E); - vga_out8 (0x3c4, 0x0f); - vga_out8 (0x3c5, par->SR0F); - vga_out8 (0x3c4, 0x29); - vga_out8 (0x3c5, par->SR29); - vga_out8 (0x3c4, 0x15); - vga_out8 (0x3c5, par->SR15); + vga_out8 (0x3c4, 0x0e, par); + vga_out8 (0x3c5, par->SR0E, par); + vga_out8 (0x3c4, 0x0f, par); + vga_out8 (0x3c5, par->SR0F, par); + vga_out8 (0x3c4, 0x29, par); + vga_out8 (0x3c5, par->SR29, par); + vga_out8 (0x3c4, 0x15, par); + vga_out8 (0x3c5, par->SR15, par); /* Restore flat panel expansion regsters. */ if( par->chip == S3_SAVAGE_MX ) { int i; for( i = 0; i < 8; i++ ) { - vga_out8 (0x3c4, 0x54+i); - vga_out8 (0x3c5, par->SR54[i]); + vga_out8 (0x3c4, 0x54+i, par); + vga_out8 (0x3c5, par->SR54[i], par); } } vgaHWRestore (par); /* extended mode timing registers */ - vga_out8 (0x3d4, 0x53); - vga_out8 (0x3d5, par->CR53); - vga_out8 (0x3d4, 0x5d); - vga_out8 (0x3d5, par->CR5D); - vga_out8 (0x3d4, 0x5e); - vga_out8 (0x3d5, par->CR5E); - vga_out8 (0x3d4, 0x3b); - vga_out8 (0x3d5, par->CR3B); - vga_out8 (0x3d4, 0x3c); - vga_out8 (0x3d5, par->CR3C); - vga_out8 (0x3d4, 0x43); - vga_out8 (0x3d5, par->CR43); - vga_out8 (0x3d4, 0x65); - vga_out8 (0x3d5, par->CR65); + vga_out8 (0x3d4, 0x53, par); + vga_out8 (0x3d5, par->CR53, par); + vga_out8 (0x3d4, 0x5d, par); + vga_out8 (0x3d5, par->CR5D, par); + vga_out8 (0x3d4, 0x5e, par); + vga_out8 (0x3d5, par->CR5E, par); + vga_out8 (0x3d4, 0x3b, par); + vga_out8 (0x3d5, par->CR3B, par); + vga_out8 (0x3d4, 0x3c, par); + vga_out8 (0x3d5, par->CR3C, par); + vga_out8 (0x3d4, 0x43, par); + vga_out8 (0x3d5, par->CR43, par); + vga_out8 (0x3d4, 0x65, par); + vga_out8 (0x3d5, par->CR65, par); /* restore the desired video mode with cr67 */ - vga_out8 (0x3d4, 0x67); + vga_out8 (0x3d4, 0x67, par); /* following part not present in X11 driver */ - cr67 = vga_in8 (0x3d5) & 0xf; - vga_out8 (0x3d5, 0x50 | cr67); + cr67 = vga_in8 (0x3d5, par) & 0xf; + vga_out8 (0x3d5, 0x50 | cr67, par); udelay (10000); - vga_out8 (0x3d4, 0x67); + vga_out8 (0x3d4, 0x67, par); /* end of part */ - vga_out8 (0x3d5, par->CR67 & ~0x0c); + vga_out8 (0x3d5, par->CR67 & ~0x0c, par); /* other mode timing and extended regs */ - vga_out8 (0x3d4, 0x34); - vga_out8 (0x3d5, par->CR34); - vga_out8 (0x3d4, 0x40); - vga_out8 (0x3d5, par->CR40); - vga_out8 (0x3d4, 0x42); - vga_out8 (0x3d5, par->CR42); - vga_out8 (0x3d4, 0x45); - vga_out8 (0x3d5, par->CR45); - vga_out8 (0x3d4, 0x50); - vga_out8 (0x3d5, par->CR50); - vga_out8 (0x3d4, 0x51); - vga_out8 (0x3d5, par->CR51); + vga_out8 (0x3d4, 0x34, par); + vga_out8 (0x3d5, par->CR34, par); + vga_out8 (0x3d4, 0x40, par); + vga_out8 (0x3d5, par->CR40, par); + vga_out8 (0x3d4, 0x42, par); + vga_out8 (0x3d5, par->CR42, par); + vga_out8 (0x3d4, 0x45, par); + vga_out8 (0x3d5, par->CR45, par); + vga_out8 (0x3d4, 0x50, par); + vga_out8 (0x3d5, par->CR50, par); + vga_out8 (0x3d4, 0x51, par); + vga_out8 (0x3d5, par->CR51, par); /* memory timings */ - vga_out8 (0x3d4, 0x36); - vga_out8 (0x3d5, par->CR36); - vga_out8 (0x3d4, 0x60); - vga_out8 (0x3d5, par->CR60); - vga_out8 (0x3d4, 0x68); - vga_out8 (0x3d5, par->CR68); - vga_out8 (0x3d4, 0x69); - vga_out8 (0x3d5, par->CR69); - vga_out8 (0x3d4, 0x6f); - vga_out8 (0x3d5, par->CR6F); - - vga_out8 (0x3d4, 0x33); - vga_out8 (0x3d5, par->CR33); - vga_out8 (0x3d4, 0x86); - vga_out8 (0x3d5, par->CR86); - vga_out8 (0x3d4, 0x88); - vga_out8 (0x3d5, par->CR88); - vga_out8 (0x3d4, 0x90); - vga_out8 (0x3d5, par->CR90); - vga_out8 (0x3d4, 0x91); - vga_out8 (0x3d5, par->CR91); + vga_out8 (0x3d4, 0x36, par); + vga_out8 (0x3d5, par->CR36, par); + vga_out8 (0x3d4, 0x60, par); + vga_out8 (0x3d5, par->CR60, par); + vga_out8 (0x3d4, 0x68, par); + vga_out8 (0x3d5, par->CR68, par); + vga_out8 (0x3d4, 0x69, par); + vga_out8 (0x3d5, par->CR69, par); + vga_out8 (0x3d4, 0x6f, par); + vga_out8 (0x3d5, par->CR6F, par); + + vga_out8 (0x3d4, 0x33, par); + vga_out8 (0x3d5, par->CR33, par); + vga_out8 (0x3d4, 0x86, par); + vga_out8 (0x3d5, par->CR86, par); + vga_out8 (0x3d4, 0x88, par); + vga_out8 (0x3d5, par->CR88, par); + vga_out8 (0x3d4, 0x90, par); + vga_out8 (0x3d5, par->CR90, par); + vga_out8 (0x3d4, 0x91, par); + vga_out8 (0x3d5, par->CR91, par); if (par->chip == S3_SAVAGE4) { - vga_out8 (0x3d4, 0xb0); - vga_out8 (0x3d5, par->CRB0); + vga_out8 (0x3d4, 0xb0, par); + vga_out8 (0x3d5, par->CRB0, par); } - vga_out8 (0x3d4, 0x32); - vga_out8 (0x3d5, par->CR32); + vga_out8 (0x3d4, 0x32, par); + vga_out8 (0x3d5, par->CR32, par); /* unlock extended seq regs */ - vga_out8 (0x3c4, 0x08); - vga_out8 (0x3c5, 0x06); + vga_out8 (0x3c4, 0x08, par); + vga_out8 (0x3c5, 0x06, par); /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates * that we should leave the default SR10 and SR11 values there. */ if (par->SR10 != 255) { - vga_out8 (0x3c4, 0x10); - vga_out8 (0x3c5, par->SR10); - vga_out8 (0x3c4, 0x11); - vga_out8 (0x3c5, par->SR11); + vga_out8 (0x3c4, 0x10, par); + vga_out8 (0x3c5, par->SR10, par); + vga_out8 (0x3c4, 0x11, par); + vga_out8 (0x3c5, par->SR11, par); } /* restore extended seq regs for dclk */ - vga_out8 (0x3c4, 0x0e); - vga_out8 (0x3c5, par->SR0E); - vga_out8 (0x3c4, 0x0f); - vga_out8 (0x3c5, par->SR0F); - vga_out8 (0x3c4, 0x12); - vga_out8 (0x3c5, par->SR12); - vga_out8 (0x3c4, 0x13); - vga_out8 (0x3c5, par->SR13); - vga_out8 (0x3c4, 0x29); - vga_out8 (0x3c5, par->SR29); - - vga_out8 (0x3c4, 0x18); - vga_out8 (0x3c5, par->SR18); + vga_out8 (0x3c4, 0x0e, par); + vga_out8 (0x3c5, par->SR0E, par); + vga_out8 (0x3c4, 0x0f, par); + vga_out8 (0x3c5, par->SR0F, par); + vga_out8 (0x3c4, 0x12, par); + vga_out8 (0x3c5, par->SR12, par); + vga_out8 (0x3c4, 0x13, par); + vga_out8 (0x3c5, par->SR13, par); + vga_out8 (0x3c4, 0x29, par); + vga_out8 (0x3c5, par->SR29, par); + + vga_out8 (0x3c4, 0x18, par); + vga_out8 (0x3c5, par->SR18, par); /* load new m, n pll values for dclk & mclk */ - vga_out8 (0x3c4, 0x15); - tmp = vga_in8 (0x3c5) & ~0x21; + vga_out8 (0x3c4, 0x15, par); + tmp = vga_in8 (0x3c5, par) & ~0x21; - vga_out8 (0x3c5, tmp | 0x03); - vga_out8 (0x3c5, tmp | 0x23); - vga_out8 (0x3c5, tmp | 0x03); - vga_out8 (0x3c5, par->SR15); + vga_out8 (0x3c5, tmp | 0x03, par); + vga_out8 (0x3c5, tmp | 0x23, par); + vga_out8 (0x3c5, tmp | 0x03, par); + vga_out8 (0x3c5, par->SR15, par); udelay (100); - vga_out8 (0x3c4, 0x30); - vga_out8 (0x3c5, par->SR30); - vga_out8 (0x3c4, 0x08); - vga_out8 (0x3c5, par->SR08); + vga_out8 (0x3c4, 0x30, par); + vga_out8 (0x3c5, par->SR30, par); + vga_out8 (0x3c4, 0x08, par); + vga_out8 (0x3c5, par->SR08, par); /* now write out cr67 in full, possibly starting STREAMS */ - VerticalRetraceWait(); - vga_out8 (0x3d4, 0x67); - vga_out8 (0x3d5, par->CR67); + VerticalRetraceWait(par); + vga_out8 (0x3d4, 0x67, par); + vga_out8 (0x3d5, par->CR67, par); - vga_out8 (0x3d4, 0x66); - cr66 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr66 | 0x80); - vga_out8 (0x3d4, 0x3a); - cr3a = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr3a | 0x80); + vga_out8 (0x3d4, 0x66, par); + cr66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr66 | 0x80, par); + vga_out8 (0x3d4, 0x3a, par); + cr3a = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr3a | 0x80, par); if (par->chip != S3_SAVAGE_MX) { - VerticalRetraceWait(); - savage_out32 (FIFO_CONTROL_REG, par->MMPR0); + VerticalRetraceWait(par); + savage_out32 (FIFO_CONTROL_REG, par->MMPR0, par); par->SavageWaitIdle (par); - savage_out32 (MIU_CONTROL_REG, par->MMPR1); + savage_out32 (MIU_CONTROL_REG, par->MMPR1, par); par->SavageWaitIdle (par); - savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2); + savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2, par); par->SavageWaitIdle (par); - savage_out32 (MISC_TIMEOUT_REG, par->MMPR3); + savage_out32 (MISC_TIMEOUT_REG, par->MMPR3, par); } - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66); - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, cr3a); + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66, par); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, cr3a, par); SavageSetup2DEngine (par); vgaHWProtect (par, 0); @@ -1299,10 +1303,10 @@ static void savagefb_update_start (struct savagefb_par *par, * ((var->bits_per_pixel+7) / 8)) >> 2; /* now program the start address registers */ - vga_out16(0x3d4, (base & 0x00ff00) | 0x0c); - vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d); - vga_out8 (0x3d4, 0x69); - vga_out8 (0x3d5, (base & 0x7f0000) >> 16); + vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par); + vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par); + vga_out8 (0x3d4, 0x69, par); + vga_out8 (0x3d5, (base & 0x7f0000) >> 16, par); } @@ -1311,10 +1315,14 @@ static void savagefb_set_fix(struct fb_info *info) info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8; - if (info->var.bits_per_pixel == 8) + if (info->var.bits_per_pixel == 8) { info->fix.visual = FB_VISUAL_PSEUDOCOLOR; - else + info->fix.xpanstep = 4; + } else { info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.xpanstep = 2; + } + } #if defined(CONFIG_FB_SAVAGE_ACCEL) @@ -1359,7 +1367,6 @@ static int savagefb_set_par (struct fb_info *info) par->minClock = 10000; savagefb_set_par_int (par); - savagefb_update_start (par, var); fb_set_cmap (&info->cmap, info); savagefb_set_fix(info); savagefb_set_clip(info); @@ -1406,12 +1413,12 @@ static int savagefb_blank(int blank, struct fb_info *info) u8 sr8 = 0, srd = 0; if (par->display_type == DISP_CRT) { - vga_out8(0x3c4, 0x08); - sr8 = vga_in8(0x3c5); + vga_out8(0x3c4, 0x08, par); + sr8 = vga_in8(0x3c5, par); sr8 |= 0x06; - vga_out8(0x3c5, sr8); - vga_out8(0x3c4, 0x0d); - srd = vga_in8(0x3c5); + vga_out8(0x3c5, sr8, par); + vga_out8(0x3c4, 0x0d, par); + srd = vga_in8(0x3c5, par); srd &= 0x03; switch (blank) { @@ -1429,8 +1436,8 @@ static int savagefb_blank(int blank, struct fb_info *info) break; } - vga_out8(0x3c4, 0x0d); - vga_out8(0x3c5, srd); + vga_out8(0x3c4, 0x0d, par); + vga_out8(0x3c5, srd, par); } if (par->display_type == DISP_LCD || @@ -1438,14 +1445,14 @@ static int savagefb_blank(int blank, struct fb_info *info) switch(blank) { case FB_BLANK_UNBLANK: case FB_BLANK_NORMAL: - vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ - vga_out8(0x3c5, vga_in8(0x3c5) | 0x10); + vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */ + vga_out8(0x3c5, vga_in8(0x3c5, par) | 0x10, par); break; case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: - vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ - vga_out8(0x3c5, vga_in8(0x3c5) & ~0x10); + vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */ + vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x10, par); break; } } @@ -1470,7 +1477,6 @@ static struct fb_ops savagefb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; /* --------------------------------------------------------------------- */ @@ -1499,15 +1505,15 @@ static void savage_enable_mmio (struct savagefb_par *par) DBG ("savage_enable_mmio\n"); - val = vga_in8 (0x3c3); - vga_out8 (0x3c3, val | 0x01); - val = vga_in8 (0x3cc); - vga_out8 (0x3c2, val | 0x01); + val = vga_in8 (0x3c3, par); + vga_out8 (0x3c3, val | 0x01, par); + val = vga_in8 (0x3cc, par); + vga_out8 (0x3c2, val | 0x01, par); if (par->chip >= S3_SAVAGE4) { - vga_out8 (0x3d4, 0x40); - val = vga_in8 (0x3d5); - vga_out8 (0x3d5, val | 1); + vga_out8 (0x3d4, 0x40, par); + val = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, val | 1, par); } } @@ -1519,9 +1525,9 @@ static void savage_disable_mmio (struct savagefb_par *par) DBG ("savage_disable_mmio\n"); if(par->chip >= S3_SAVAGE4 ) { - vga_out8 (0x3d4, 0x40); - val = vga_in8 (0x3d5); - vga_out8 (0x3d5, val | 1); + vga_out8 (0x3d4, 0x40, par); + val = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, val | 1, par); } } @@ -1641,30 +1647,30 @@ static int __devinit savage_init_hw (struct savagefb_par *par) DBG("savage_init_hw"); /* unprotect CRTC[0-7] */ - vga_out8(0x3d4, 0x11); - tmp = vga_in8(0x3d5); - vga_out8(0x3d5, tmp & 0x7f); + vga_out8(0x3d4, 0x11, par); + tmp = vga_in8(0x3d5, par); + vga_out8(0x3d5, tmp & 0x7f, par); /* unlock extended regs */ - vga_out16(0x3d4, 0x4838); - vga_out16(0x3d4, 0xa039); - vga_out16(0x3c4, 0x0608); + vga_out16(0x3d4, 0x4838, par); + vga_out16(0x3d4, 0xa039, par); + vga_out16(0x3c4, 0x0608, par); - vga_out8(0x3d4, 0x40); - tmp = vga_in8(0x3d5); - vga_out8(0x3d5, tmp & ~0x01); + vga_out8(0x3d4, 0x40, par); + tmp = vga_in8(0x3d5, par); + vga_out8(0x3d5, tmp & ~0x01, par); /* unlock sys regs */ - vga_out8(0x3d4, 0x38); - vga_out8(0x3d5, 0x48); + vga_out8(0x3d4, 0x38, par); + vga_out8(0x3d5, 0x48, par); /* Unlock system registers. */ - vga_out16(0x3d4, 0x4838); + vga_out16(0x3d4, 0x4838, par); /* Next go on to detect amount of installed ram */ - vga_out8(0x3d4, 0x36); /* for register CR36 (CONFG_REG1), */ - config1 = vga_in8(0x3d5); /* get amount of vram installed */ + vga_out8(0x3d4, 0x36, par); /* for register CR36 (CONFG_REG1), */ + config1 = vga_in8(0x3d5, par); /* get amount of vram installed */ /* Compute the amount of video memory and offscreen memory. */ @@ -1680,8 +1686,8 @@ static int __devinit savage_init_hw (struct savagefb_par *par) * when it really means 8MB. Why do it the same when you * can do it different... */ - vga_out8(0x3d4, 0x68); /* memory control 1 */ - if( (vga_in8(0x3d5) & 0xC0) == (0x01 << 6) ) + vga_out8(0x3d4, 0x68, par); /* memory control 1 */ + if( (vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6) ) RamSavage4[1] = 8; /*FALLTHROUGH*/ @@ -1710,13 +1716,13 @@ static int __devinit savage_init_hw (struct savagefb_par *par) printk (KERN_INFO "savagefb: probed videoram: %dk\n", videoRam); /* reset graphics engine to avoid memory corruption */ - vga_out8 (0x3d4, 0x66); - cr66 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr66 | 0x02); + vga_out8 (0x3d4, 0x66, par); + cr66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr66 | 0x02, par); udelay (10000); - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66 & ~0x02); /* clear reset flag */ + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66 & ~0x02, par); /* clear reset flag */ udelay (10000); @@ -1724,13 +1730,13 @@ static int __devinit savage_init_hw (struct savagefb_par *par) * reset memory interface, 3D engine, AGP master, PCI master, * master engine unit, motion compensation/LPB */ - vga_out8 (0x3d4, 0x3f); - cr3f = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr3f | 0x08); + vga_out8 (0x3d4, 0x3f, par); + cr3f = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr3f | 0x08, par); udelay (10000); - vga_out8 (0x3d4, 0x3f); - vga_out8 (0x3d5, cr3f & ~0x08); /* clear reset flags */ + vga_out8 (0x3d4, 0x3f, par); + vga_out8 (0x3d5, cr3f & ~0x08, par); /* clear reset flags */ udelay (10000); /* Savage ramdac speeds */ @@ -1741,15 +1747,15 @@ static int __devinit savage_init_hw (struct savagefb_par *par) par->clock[3] = 220000; /* detect current mclk */ - vga_out8(0x3c4, 0x08); - sr8 = vga_in8(0x3c5); - vga_out8(0x3c5, 0x06); - vga_out8(0x3c4, 0x10); - n = vga_in8(0x3c5); - vga_out8(0x3c4, 0x11); - m = vga_in8(0x3c5); - vga_out8(0x3c4, 0x08); - vga_out8(0x3c5, sr8); + vga_out8(0x3c4, 0x08, par); + sr8 = vga_in8(0x3c5, par); + vga_out8(0x3c5, 0x06, par); + vga_out8(0x3c4, 0x10, par); + n = vga_in8(0x3c5, par); + vga_out8(0x3c4, 0x11, par); + m = vga_in8(0x3c5, par); + vga_out8(0x3c4, 0x08, par); + vga_out8(0x3c5, sr8, par); m &= 0x7f; n1 = n & 0x1f; n2 = (n >> 5) & 0x03; @@ -1763,10 +1769,10 @@ static int __devinit savage_init_hw (struct savagefb_par *par) if (par->chip == S3_SAVAGE4) { unsigned char sr30 = 0x00; - vga_out8(0x3c4, 0x30); + vga_out8(0x3c4, 0x30, par); /* clear bit 1 */ - vga_out8(0x3c5, vga_in8(0x3c5) & ~0x02); - sr30 = vga_in8(0x3c5); + vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x02, par); + sr30 = vga_in8(0x3c5, par); if (sr30 & 0x02 /*0x04 */) { dvi = 1; printk("savagefb: Digital Flat Panel Detected\n"); @@ -1783,12 +1789,12 @@ static int __devinit savage_init_hw (struct savagefb_par *par) /* Check LCD panel parrmation */ if (par->display_type == DISP_LCD) { - unsigned char cr6b = VGArCR( 0x6b ); + unsigned char cr6b = VGArCR( 0x6b, par); - int panelX = (VGArSEQ (0x61) + - ((VGArSEQ (0x66) & 0x02) << 7) + 1) * 8; - int panelY = (VGArSEQ (0x69) + - ((VGArSEQ (0x6e) & 0x70) << 4) + 1); + int panelX = (VGArSEQ (0x61, par) + + ((VGArSEQ (0x66, par) & 0x02) << 7) + 1) * 8; + int panelY = (VGArSEQ (0x69, par) + + ((VGArSEQ (0x6e, par) & 0x70) << 4) + 1); char * sTechnology = "Unknown"; @@ -1810,9 +1816,9 @@ static int __devinit savage_init_hw (struct savagefb_par *par) ActiveDUO = 0x80 }; - if ((VGArSEQ (0x39) & 0x03) == 0) { + if ((VGArSEQ (0x39, par) & 0x03) == 0) { sTechnology = "TFT"; - } else if ((VGArSEQ (0x30) & 0x01) == 0) { + } else if ((VGArSEQ (0x30, par) & 0x01) == 0) { sTechnology = "DSTN"; } else { sTechnology = "STN"; @@ -1870,7 +1876,6 @@ static int __devinit savage_init_fb_info (struct fb_info *info, info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.type_aux = 0; - info->fix.xpanstep = 2; info->fix.ypanstep = 1; info->fix.ywrapstep = 0; info->fix.accel = id->driver_data; @@ -2049,24 +2054,11 @@ static int __devinit savagefb_probe (struct pci_dev* dev, info->monspecs.modedb, info->monspecs.modedb_len, NULL, 8); } else if (info->monspecs.modedb != NULL) { - struct fb_monspecs *specs = &info->monspecs; - struct fb_videomode modedb; - - if (info->monspecs.misc & FB_MISC_1ST_DETAIL) { - int i; - - for (i = 0; i < specs->modedb_len; i++) { - if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { - modedb = specs->modedb[i]; - break; - } - } - } else { - /* otherwise, get first mode in database */ - modedb = specs->modedb[0]; - } + struct fb_videomode *modedb; - savage_update_var(&info->var, &modedb); + modedb = fb_find_best_display(&info->monspecs, + &info->modelist); + savage_update_var(&info->var, modedb); } /* maximize virtual vertical length */ diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 34f72edba82..646c43f921c 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -3,6 +3,7 @@ * Copyright (C) 2003 David S. Miller (davem@redhat.com) */ +#include <linux/compat.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/string.h> @@ -182,3 +183,109 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, }; } EXPORT_SYMBOL(sbusfb_ioctl_helper); + +#ifdef CONFIG_COMPAT +struct fbcmap32 { + int index; /* first element (0 origin) */ + int count; + u32 red; + u32 green; + u32 blue; +}; + +#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32) +#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32) + +static int fbiogetputcmap(struct file *file, struct fb_info *info, + unsigned int cmd, unsigned long arg) +{ + struct fbcmap32 __user *argp = (void __user *)arg; + struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p)); + u32 addr; + int ret; + + ret = copy_in_user(p, argp, 2 * sizeof(int)); + ret |= get_user(addr, &argp->red); + ret |= put_user(compat_ptr(addr), &p->red); + ret |= get_user(addr, &argp->green); + ret |= put_user(compat_ptr(addr), &p->green); + ret |= get_user(addr, &argp->blue); + ret |= put_user(compat_ptr(addr), &p->blue); + if (ret) + return -EFAULT; + return info->fbops->fb_ioctl(file->f_dentry->d_inode, file, + (cmd == FBIOPUTCMAP32) ? + FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, + (unsigned long)p, info); +} + +struct fbcursor32 { + short set; /* what to set, choose from the list above */ + short enable; /* cursor on/off */ + struct fbcurpos pos; /* cursor position */ + struct fbcurpos hot; /* cursor hot spot */ + struct fbcmap32 cmap; /* color map info */ + struct fbcurpos size; /* cursor bit map size */ + u32 image; /* cursor image bits */ + u32 mask; /* cursor mask bits */ +}; + +#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32) +#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32) + +static int fbiogscursor(struct file *file, struct fb_info *info, + unsigned long arg) +{ + struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p)); + struct fbcursor32 __user *argp = (void __user *)arg; + compat_uptr_t addr; + int ret; + + ret = copy_in_user(p, argp, + 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)); + ret |= copy_in_user(&p->size, &argp->size, sizeof(struct fbcurpos)); + ret |= copy_in_user(&p->cmap, &argp->cmap, 2 * sizeof(int)); + ret |= get_user(addr, &argp->cmap.red); + ret |= put_user(compat_ptr(addr), &p->cmap.red); + ret |= get_user(addr, &argp->cmap.green); + ret |= put_user(compat_ptr(addr), &p->cmap.green); + ret |= get_user(addr, &argp->cmap.blue); + ret |= put_user(compat_ptr(addr), &p->cmap.blue); + ret |= get_user(addr, &argp->mask); + ret |= put_user(compat_ptr(addr), &p->mask); + ret |= get_user(addr, &argp->image); + ret |= put_user(compat_ptr(addr), &p->image); + if (ret) + return -EFAULT; + return info->fbops->fb_ioctl(file->f_dentry->d_inode, file, + FBIOSCURSOR, (unsigned long)p, info); +} + +long sbusfb_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + switch (cmd) { + case FBIOGTYPE: + case FBIOSATTR: + case FBIOGATTR: + case FBIOSVIDEO: + case FBIOGVIDEO: + case FBIOGCURSOR32: /* This is not implemented yet. + Later it should be converted... */ + case FBIOSCURPOS: + case FBIOGCURPOS: + case FBIOGCURMAX: + return info->fbops->fb_ioctl(file->f_dentry->d_inode, + file, cmd, arg, info); + case FBIOPUTCMAP32: + return fbiogetputcmap(file, info, cmd, arg); + case FBIOGETCMAP32: + return fbiogetputcmap(file, info, cmd, arg); + case FBIOSCURSOR32: + return fbiogscursor(file, info, arg); + default: + return -ENOIOCTLCMD; + } +} +EXPORT_SYMBOL(sbusfb_compat_ioctl); +#endif diff --git a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h index a6aa33ba09d..b470e52ce9e 100644 --- a/drivers/video/sbuslib.h +++ b/drivers/video/sbuslib.h @@ -20,5 +20,7 @@ extern int sbusfb_mmap_helper(struct sbus_mmap_map *map, int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, struct fb_info *info, int type, int fb_depth, unsigned long fb_size); +long sbusfb_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info); #endif /* _SBUSLIB_H */ diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index 8413907b379..7054660767e 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -18,6 +18,8 @@ #include <linux/fb.h> #include <linux/init.h> #include <linux/ioport.h> +#include <linux/platform_device.h> + #include <asm/io.h> #include <asm/mtrr.h> @@ -124,7 +126,6 @@ static struct fb_ops sgivwfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = sgivwfb_mmap, }; @@ -749,13 +750,8 @@ int __init sgivwfb_setup(char *options) /* * Initialisation */ -static void sgivwfb_release(struct device *device) -{ -} - -static int __init sgivwfb_probe(struct device *device) +static int __init sgivwfb_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(device); struct sgivw_par *par; struct fb_info *info; char *monitor; @@ -816,7 +812,7 @@ static int __init sgivwfb_probe(struct device *device) goto fail_register_framebuffer; } - dev_set_drvdata(&dev->dev, info); + platform_set_drvdata(dev, info); printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n", info->node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys); @@ -834,9 +830,9 @@ fail_ioremap_regs: return -ENXIO; } -static int sgivwfb_remove(struct device *device) +static int sgivwfb_remove(struct platform_device *dev) { - struct fb_info *info = dev_get_drvdata(device); + struct fb_info *info = platform_get_drvdata(dev); if (info) { struct sgivw_par *par = info->par; @@ -850,20 +846,15 @@ static int sgivwfb_remove(struct device *device) return 0; } -static struct device_driver sgivwfb_driver = { - .name = "sgivwfb", - .bus = &platform_bus_type, +static struct platform_driver sgivwfb_driver = { .probe = sgivwfb_probe, .remove = sgivwfb_remove, + .driver = { + .name = "sgivwfb", + }, }; -static struct platform_device sgivwfb_device = { - .name = "sgivwfb", - .id = 0, - .dev = { - .release = sgivwfb_release, - } -}; +static struct platform_device *sgivwfb_device; int __init sgivwfb_init(void) { @@ -876,11 +867,17 @@ int __init sgivwfb_init(void) return -ENODEV; sgivwfb_setup(option); #endif - ret = driver_register(&sgivwfb_driver); + ret = platform_driver_register(&sgivwfb_driver); if (!ret) { - ret = platform_device_register(&sgivwfb_device); - if (ret) - driver_unregister(&sgivwfb_driver); + sgivwfb_device = platform_device_alloc("sgivwfb", 0); + if (sgivwfb_device) { + ret = platform_device_add(sgivwfb_device); + } else + ret = -ENOMEM; + if (ret) { + platform_driver_unregister(&sgivwfb_driver); + platform_device_put(sgivwfb_device); + } } return ret; } @@ -892,8 +889,8 @@ MODULE_LICENSE("GPL"); static void __exit sgivwfb_exit(void) { - platform_device_unregister(&sgivwfb_device); - driver_unregister(&sgivwfb_driver); + platform_device_unregister(sgivwfb_device); + platform_driver_unregister(&sgivwfb_driver); } module_exit(sgivwfb_exit); diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 42c54b69726..dea1a46c67c 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -2002,7 +2002,9 @@ static struct fb_ops sisfb_ops = { .fb_fillrect = fbcon_sis_fillrect, .fb_copyarea = fbcon_sis_copyarea, .fb_imageblit = cfb_imageblit, +#ifdef CONFIG_FB_SOFT_CURSOR .fb_cursor = soft_cursor, +#endif .fb_sync = fbcon_sis_sync, #ifdef SIS_NEW_CONFIG_COMPAT .fb_compat_ioctl= sisfb_compat_ioctl, diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 7b43716ab66..a01e7ecc15e 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -457,11 +457,8 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) } /** - * xxxfb_cursor - REQUIRED function. If your hardware lacks support - * for a cursor you can use the default cursor whose - * function is called soft_cursor. It will always - * work since it uses xxxfb_imageblit function which - * is required. + * xxxfb_cursor - OPTIONAL. If your hardware lacks support + * for a cursor, leave this field NULL. * * @info: frame buffer structure that represents a single frame buffer * @cursor: structure defining the cursor to draw. @@ -663,7 +660,7 @@ static struct fb_ops xxxfb_ops = { .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ .fb_copyarea = xxxfb_copyarea, /* Needed !!! */ .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ - .fb_cursor = xxxfb_cursor, /* Needed !!! */ + .fb_cursor = xxxfb_cursor, /* Optional !!! */ .fb_rotate = xxxfb_rotate, .fb_poll = xxxfb_poll, .fb_sync = xxxfb_sync, diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 663d53657fa..e0f14df840d 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -1382,7 +1382,6 @@ static struct fb_ops sstfb_ops = { .fb_fillrect = cfb_fillrect, /* sstfb_fillrect */ .fb_copyarea = cfb_copyarea, /* sstfb_copyarea */ .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = sstfb_ioctl, }; diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 9e52794768e..fbb17332afd 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1147,7 +1147,6 @@ static struct fb_ops stifb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 1986a8b3833..fe4f63f3849 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -52,7 +52,9 @@ static struct fb_ops tcx_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = tcx_mmap, .fb_ioctl = tcx_ioctl, - .fb_cursor = soft_cursor, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sbusfb_compat_ioctl, +#endif }; /* THC definitions */ diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 7044226c5d4..9d53387e6a6 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -184,7 +184,6 @@ static struct fb_ops tdfxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 9d9d2009ad8..7398bd48ba6 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -63,7 +63,6 @@ static struct fb_ops tgafb_ops = { .fb_fillrect = tgafb_fillrect, .fb_copyarea = tgafb_copyarea, .fb_imageblit = tgafb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 81a6d9f188c..9ac2d317118 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -1293,7 +1293,6 @@ static struct fb_ops tridentfb_ops = { .fb_fillrect = tridentfb_fillrect, .fb_copyarea= tridentfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; module_init(tridentfb_init); diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c index 39d9ca71856..d904da44e1a 100644 --- a/drivers/video/tx3912fb.c +++ b/drivers/video/tx3912fb.c @@ -89,7 +89,6 @@ static struct fb_ops tx3912fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 31a2bbc5397..ce97ec8eae9 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -135,7 +135,6 @@ static struct fb_ops valkyriefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* Sets the video mode according to info->var */ diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 1ca80264c7b..3e58ddc2bc3 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -19,6 +19,8 @@ #include <linux/fb.h> #include <linux/ioport.h> #include <linux/init.h> +#include <linux/platform_device.h> + #include <video/vga.h> #include <asm/io.h> #include <asm/mtrr.h> @@ -46,7 +48,7 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = { }; static int inverse = 0; -static int mtrr = 3; /* default to write-combining */ +static int mtrr = 0; /* disable mtrr */ static int vram_remap __initdata = 0; /* Set amount of memory to be used */ static int vram_total __initdata = 0; /* Set total amount of memory */ static int pmi_setpal = 0; /* pmi for palette changes ??? */ @@ -96,14 +98,14 @@ static int vesafb_blank(int blank, struct fb_info *info) int loop = 10000; u8 seq = 0, crtc17 = 0; - err = 0; - - if (blank) { + if (blank == FB_BLANK_POWERDOWN) { seq = 0x20; crtc17 = 0x00; + err = 0; } else { seq = 0x00; crtc17 = 0x80; + err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL; } vga_wseq(NULL, 0x00, 0x01); @@ -164,45 +166,39 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, if (regno >= info->cmap.len) return 1; - switch (info->var.bits_per_pixel) { - case 8: + if (info->var.bits_per_pixel == 8) vesa_setpalette(regno,red,green,blue); - break; - case 16: - if (info->var.red.offset == 10) { - /* 1:5:5:5 */ - ((u32*) (info->pseudo_palette))[regno] = + else if (regno < 16) { + switch (info->var.bits_per_pixel) { + case 16: + if (info->var.red.offset == 10) { + /* 1:5:5:5 */ + ((u32*) (info->pseudo_palette))[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); - } else { - /* 0:5:6:5 */ - ((u32*) (info->pseudo_palette))[regno] = + } else { + /* 0:5:6:5 */ + ((u32*) (info->pseudo_palette))[regno] = ((red & 0xf800) ) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); + } + break; + case 24: + case 32: + red >>= 8; + green >>= 8; + blue >>= 8; + ((u32 *)(info->pseudo_palette))[regno] = + (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + break; } - break; - case 24: - red >>= 8; - green >>= 8; - blue >>= 8; - ((u32 *)(info->pseudo_palette))[regno] = - (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - break; - case 32: - red >>= 8; - green >>= 8; - blue >>= 8; - ((u32 *)(info->pseudo_palette))[regno] = - (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - break; - } - return 0; + } + + return 0; } static struct fb_ops vesafb_ops = { @@ -213,7 +209,6 @@ static struct fb_ops vesafb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __init vesafb_setup(char *options) @@ -250,9 +245,8 @@ static int __init vesafb_setup(char *options) return 0; } -static int __init vesafb_probe(struct device *device) +static int __init vesafb_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(device); struct fb_info *info; int i, err; unsigned int size_vmode; @@ -419,6 +413,7 @@ static int __init vesafb_probe(struct device *device) * region already (FIXME) */ request_region(0x3c0, 32, "vesafb"); +#ifdef CONFIG_MTRR if (mtrr) { unsigned int temp_size = size_total; unsigned int type = 0; @@ -456,6 +451,7 @@ static int __init vesafb_probe(struct device *device) } while (temp_size >= PAGE_SIZE && rc == -EINVAL); } } +#endif info->fbops = &vesafb_ops; info->var = vesafb_defined; @@ -485,10 +481,11 @@ err: return err; } -static struct device_driver vesafb_driver = { - .name = "vesafb", - .bus = &platform_bus_type, +static struct platform_driver vesafb_driver = { .probe = vesafb_probe, + .driver = { + .name = "vesafb", + }, }; static struct platform_device vesafb_device = { @@ -503,12 +500,12 @@ static int __init vesafb_init(void) /* ignore error return of fb_get_options */ fb_get_options("vesafb", &option); vesafb_setup(option); - ret = driver_register(&vesafb_driver); + ret = platform_driver_register(&vesafb_driver); if (!ret) { ret = platform_device_register(&vesafb_device); if (ret) - driver_unregister(&vesafb_driver); + platform_driver_unregister(&vesafb_driver); } return ret; } diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index b137a3fe075..ffa1ad47422 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -20,6 +20,8 @@ #include <linux/vmalloc.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> + #include <asm/uaccess.h> #include <linux/fb.h> #include <linux/init.h> @@ -90,7 +92,6 @@ static struct fb_ops vfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = vfb_mmap, }; @@ -402,9 +403,8 @@ static void vfb_platform_release(struct device *device) // This is called when the reference count goes to zero. } -static int __init vfb_probe(struct device *device) +static int __init vfb_probe(struct platform_device *dev) { - struct platform_device *dev = to_platform_device(device); struct fb_info *info; int retval = -ENOMEM; @@ -446,7 +446,7 @@ static int __init vfb_probe(struct device *device) retval = register_framebuffer(info); if (retval < 0) goto err2; - dev_set_drvdata(&dev->dev, info); + platform_set_drvdata(dev, info); printk(KERN_INFO "fb%d: Virtual frame buffer device, using %ldK of video memory\n", @@ -461,9 +461,9 @@ err: return retval; } -static int vfb_remove(struct device *device) +static int vfb_remove(struct platform_device *dev) { - struct fb_info *info = dev_get_drvdata(device); + struct fb_info *info = platform_get_drvdata(dev); if (info) { unregister_framebuffer(info); @@ -473,11 +473,12 @@ static int vfb_remove(struct device *device) return 0; } -static struct device_driver vfb_driver = { - .name = "vfb", - .bus = &platform_bus_type, +static struct platform_driver vfb_driver = { .probe = vfb_probe, .remove = vfb_remove, + .driver = { + .name = "vfb", + }, }; static struct platform_device vfb_device = { @@ -503,12 +504,12 @@ static int __init vfb_init(void) if (!vfb_enable) return -ENXIO; - ret = driver_register(&vfb_driver); + ret = platform_driver_register(&vfb_driver); if (!ret) { ret = platform_device_register(&vfb_device); if (ret) - driver_unregister(&vfb_driver); + platform_driver_unregister(&vfb_driver); } return ret; } @@ -519,7 +520,7 @@ module_init(vfb_init); static void __exit vfb_exit(void) { platform_device_unregister(&vfb_device); - driver_unregister(&vfb_driver); + platform_driver_unregister(&vfb_driver); } module_exit(vfb_exit); diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index b46454c55c9..226ae8a8848 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -21,6 +21,7 @@ #include <linux/fb.h> #include <linux/ioport.h> #include <linux/init.h> +#include <linux/platform_device.h> #include <asm/io.h> #include <video/vga.h> @@ -51,35 +52,33 @@ * card parameters */ -static struct fb_info vga16fb; - -static struct vga16fb_par { +struct vga16fb_par { /* structure holding original VGA register settings when the screen is blanked */ struct { - unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ - unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ - unsigned char CrtMiscIO; /* Miscellaneous register */ - unsigned char HorizontalTotal; /* CRT-Controller:00h */ - unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ - unsigned char StartHorizRetrace; /* CRT-Controller:04h */ - unsigned char EndHorizRetrace; /* CRT-Controller:05h */ - unsigned char Overflow; /* CRT-Controller:07h */ - unsigned char StartVertRetrace; /* CRT-Controller:10h */ - unsigned char EndVertRetrace; /* CRT-Controller:11h */ - unsigned char ModeControl; /* CRT-Controller:17h */ - unsigned char ClockingMode; /* Seq-Controller:01h */ + unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ + unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ + unsigned char CrtMiscIO; /* Miscellaneous register */ + unsigned char HorizontalTotal; /* CRT-Controller:00h */ + unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ + unsigned char StartHorizRetrace;/* CRT-Controller:04h */ + unsigned char EndHorizRetrace; /* CRT-Controller:05h */ + unsigned char Overflow; /* CRT-Controller:07h */ + unsigned char StartVertRetrace; /* CRT-Controller:10h */ + unsigned char EndVertRetrace; /* CRT-Controller:11h */ + unsigned char ModeControl; /* CRT-Controller:17h */ + unsigned char ClockingMode; /* Seq-Controller:01h */ } vga_state; struct vgastate state; atomic_t ref_count; int palette_blanked, vesa_blanked, mode, isVGA; u8 misc, pel_msk, vss, clkdiv; u8 crtc[VGA_CRT_C]; -} vga16_par; +}; /* --------------------------------------------------------------------- */ -static struct fb_var_screeninfo vga16fb_defined = { +static struct fb_var_screeninfo vga16fb_defined __initdata = { .xres = 640, .yres = 480, .xres_virtual = 640, @@ -205,7 +204,7 @@ static inline void setindex(int index) static void vga16fb_pan_var(struct fb_info *info, struct fb_var_screeninfo *var) { - struct vga16fb_par *par = (struct vga16fb_par *) info->par; + struct vga16fb_par *par = info->par; u32 xoffset, pos; xoffset = var->xoffset; @@ -300,7 +299,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, static int vga16fb_open(struct fb_info *info, int user) { - struct vga16fb_par *par = (struct vga16fb_par *) info->par; + struct vga16fb_par *par = info->par; int cnt = atomic_read(&par->ref_count); if (!cnt) { @@ -315,7 +314,7 @@ static int vga16fb_open(struct fb_info *info, int user) static int vga16fb_release(struct fb_info *info, int user) { - struct vga16fb_par *par = (struct vga16fb_par *) info->par; + struct vga16fb_par *par = info->par; int cnt = atomic_read(&par->ref_count); if (!cnt) @@ -330,7 +329,7 @@ static int vga16fb_release(struct fb_info *info, int user) static int vga16fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - struct vga16fb_par *par = (struct vga16fb_par *) info->par; + struct vga16fb_par *par = info->par; u32 xres, right, hslen, left, xtotal; u32 yres, lower, vslen, upper, ytotal; u32 vxres, xoffset, vyres, yoffset; @@ -535,7 +534,7 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var, static int vga16fb_set_par(struct fb_info *info) { - struct vga16fb_par *par = (struct vga16fb_par *) info->par; + struct vga16fb_par *par = info->par; u8 gdc[VGA_GFX_C]; u8 seq[VGA_SEQ_C]; u8 atc[VGA_ATT_C]; @@ -677,7 +676,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - struct vga16fb_par *par = (struct vga16fb_par *) info->par; + struct vga16fb_par *par = info->par; int gray; /* @@ -850,7 +849,7 @@ static void vga_pal_blank(void) /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ static int vga16fb_blank(int blank, struct fb_info *info) { - struct vga16fb_par *par = (struct vga16fb_par *) info->par; + struct vga16fb_par *par = info->par; switch (blank) { case FB_BLANK_UNBLANK: /* Unblank */ @@ -1201,7 +1200,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im { char __iomem *where = info->screen_base + (image->dx/8) + image->dy * info->fix.line_length; - struct vga16fb_par *par = (struct vga16fb_par *) info->par; + struct vga16fb_par *par = info->par; char *cdat = (char *) image->data; char __iomem *dst; int x, y; @@ -1266,7 +1265,7 @@ static void vga_imageblit_color(struct fb_info *info, const struct fb_image *ima /* * Draw logo */ - struct vga16fb_par *par = (struct vga16fb_par *) info->par; + struct vga16fb_par *par = info->par; char __iomem *where = info->screen_base + image->dy * info->fix.line_length + image->dx/8; @@ -1326,7 +1325,6 @@ static struct fb_ops vga16fb_ops = { .fb_fillrect = vga16fb_fillrect, .fb_copyarea = vga16fb_copyarea, .fb_imageblit = vga16fb_imageblit, - .fb_cursor = soft_cursor, }; #ifndef MODULE @@ -1344,89 +1342,141 @@ static int vga16fb_setup(char *options) } #endif -static int __init vga16fb_init(void) +static int __init vga16fb_probe(struct device *device) { + struct platform_device *dev = to_platform_device(device); + struct fb_info *info; + struct vga16fb_par *par; int i; - int ret; -#ifndef MODULE - char *option = NULL; + int ret = 0; - if (fb_get_options("vga16fb", &option)) - return -ENODEV; - - vga16fb_setup(option); -#endif printk(KERN_DEBUG "vga16fb: initializing\n"); + info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev); + + if (!info) { + ret = -ENOMEM; + goto err_fb_alloc; + } /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ + info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS); - vga16fb.screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS); - if (!vga16fb.screen_base) { + if (!info->screen_base) { printk(KERN_ERR "vga16fb: unable to map device\n"); ret = -ENOMEM; goto err_ioremap; } - printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.screen_base); - vga16_par.isVGA = ORIG_VIDEO_ISVGA; - vga16_par.palette_blanked = 0; - vga16_par.vesa_blanked = 0; + printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); + par = info->par; - i = vga16_par.isVGA? 6 : 2; + par->isVGA = ORIG_VIDEO_ISVGA; + par->palette_blanked = 0; + par->vesa_blanked = 0; + + i = par->isVGA? 6 : 2; vga16fb_defined.red.length = i; vga16fb_defined.green.length = i; vga16fb_defined.blue.length = i; /* name should not depend on EGA/VGA */ - vga16fb.fbops = &vga16fb_ops; - vga16fb.var = vga16fb_defined; - vga16fb.fix = vga16fb_fix; - vga16fb.par = &vga16_par; - vga16fb.flags = FBINFO_FLAG_DEFAULT | + info->fbops = &vga16fb_ops; + info->var = vga16fb_defined; + info->fix = vga16fb_fix; + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_HWACCEL_YPAN; - i = (vga16fb_defined.bits_per_pixel == 8) ? 256 : 16; - ret = fb_alloc_cmap(&vga16fb.cmap, i, 0); + i = (info->var.bits_per_pixel == 8) ? 256 : 16; + ret = fb_alloc_cmap(&info->cmap, i, 0); if (ret) { printk(KERN_ERR "vga16fb: unable to allocate colormap\n"); ret = -ENOMEM; goto err_alloc_cmap; } - if (vga16fb_check_var(&vga16fb.var, &vga16fb)) { + if (vga16fb_check_var(&info->var, info)) { printk(KERN_ERR "vga16fb: unable to validate variable\n"); ret = -EINVAL; goto err_check_var; } - vga16fb_update_fix(&vga16fb); + vga16fb_update_fix(info); - if (register_framebuffer(&vga16fb) < 0) { + if (register_framebuffer(info) < 0) { printk(KERN_ERR "vga16fb: unable to register framebuffer\n"); ret = -EINVAL; goto err_check_var; } printk(KERN_INFO "fb%d: %s frame buffer device\n", - vga16fb.node, vga16fb.fix.id); + info->node, info->fix.id); + dev_set_drvdata(device, info); return 0; err_check_var: - fb_dealloc_cmap(&vga16fb.cmap); + fb_dealloc_cmap(&info->cmap); err_alloc_cmap: - iounmap(vga16fb.screen_base); + iounmap(info->screen_base); err_ioremap: + framebuffer_release(info); + err_fb_alloc: + return ret; +} + +static int vga16fb_remove(struct device *device) +{ + struct fb_info *info = dev_get_drvdata(device); + + if (info) { + unregister_framebuffer(info); + iounmap(info->screen_base); + fb_dealloc_cmap(&info->cmap); + /* XXX unshare VGA regions */ + framebuffer_release(info); + } + + return 0; +} + +static struct device_driver vga16fb_driver = { + .name = "vga16fb", + .bus = &platform_bus_type, + .probe = vga16fb_probe, + .remove = vga16fb_remove, +}; + +static struct platform_device vga16fb_device = { + .name = "vga16fb", +}; + +static int __init vga16fb_init(void) +{ + int ret; +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("vga16fb", &option)) + return -ENODEV; + + vga16fb_setup(option); +#endif + ret = driver_register(&vga16fb_driver); + + if (!ret) { + ret = platform_device_register(&vga16fb_device); + if (ret) + driver_unregister(&vga16fb_driver); + } + return ret; } static void __exit vga16fb_exit(void) { - unregister_framebuffer(&vga16fb); - iounmap(vga16fb.screen_base); - fb_dealloc_cmap(&vga16fb.cmap); - /* XXX unshare VGA regions */ + platform_device_unregister(&vga16fb_device); + driver_unregister(&vga16fb_driver); } MODULE_LICENSE("GPL"); diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c index ca92940f394..d9e01daee63 100644 --- a/drivers/video/vgastate.c +++ b/drivers/video/vgastate.c @@ -485,11 +485,6 @@ int restore_vga (struct vgastate *state) return 0; } -#ifdef MODULE -int init_module(void) { return 0; }; -void cleanup_module(void) {}; -#endif - EXPORT_SYMBOL(save_vga); EXPORT_SYMBOL(restore_vga); diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index 0030c071da8..f6e24ee85f0 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -25,7 +25,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/mm.h> -#include <linux/device.h> +#include <linux/platform_device.h> #include <linux/string.h> #include <linux/vmalloc.h> #include <asm/io.h> @@ -397,7 +397,6 @@ static struct fb_ops w100fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; #ifdef CONFIG_PM @@ -438,36 +437,34 @@ static void w100fb_restore_vidmem(struct w100fb_par *par) } } -static int w100fb_suspend(struct device *dev, pm_message_t state, uint32_t level) +static int w100fb_suspend(struct platform_device *dev, pm_message_t state) { - if (level == SUSPEND_POWER_DOWN) { - struct fb_info *info = dev_get_drvdata(dev); - struct w100fb_par *par=info->par; - struct w100_tg_info *tg = par->mach->tg; - - w100fb_save_vidmem(par); - if(tg && tg->suspend) - tg->suspend(par); - w100_suspend(W100_SUSPEND_ALL); - par->blanked = 1; - } + struct fb_info *info = platform_get_drvdata(dev); + struct w100fb_par *par=info->par; + struct w100_tg_info *tg = par->mach->tg; + + w100fb_save_vidmem(par); + if(tg && tg->suspend) + tg->suspend(par); + w100_suspend(W100_SUSPEND_ALL); + par->blanked = 1; + return 0; } -static int w100fb_resume(struct device *dev, uint32_t level) +static int w100fb_resume(struct platform_device *dev) { - if (level == RESUME_POWER_ON) { - struct fb_info *info = dev_get_drvdata(dev); - struct w100fb_par *par=info->par; - struct w100_tg_info *tg = par->mach->tg; + struct fb_info *info = platform_get_drvdata(dev); + struct w100fb_par *par=info->par; + struct w100_tg_info *tg = par->mach->tg; + + w100_hw_init(par); + w100fb_activate_var(par); + w100fb_restore_vidmem(par); + if(tg && tg->resume) + tg->resume(par); + par->blanked = 0; - w100_hw_init(par); - w100fb_activate_var(par); - w100fb_restore_vidmem(par); - if(tg && tg->resume) - tg->resume(par); - par->blanked = 0; - } return 0; } #else @@ -476,13 +473,12 @@ static int w100fb_resume(struct device *dev, uint32_t level) #endif -int __init w100fb_probe(struct device *dev) +int __init w100fb_probe(struct platform_device *pdev) { int err = -EIO; struct w100fb_mach_info *inf; struct fb_info *info = NULL; struct w100fb_par *par; - struct platform_device *pdev = to_platform_device(dev); struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); unsigned int chip_id; @@ -518,16 +514,16 @@ int __init w100fb_probe(struct device *dev) if (remapped_fbuf == NULL) goto out; - info=framebuffer_alloc(sizeof(struct w100fb_par), dev); + info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev); if (!info) { err = -ENOMEM; goto out; } par = info->par; - dev_set_drvdata(dev, info); + platform_set_drvdata(pdev, info); - inf = dev->platform_data; + inf = pdev->dev.platform_data; par->chip_id = chip_id; par->mach = inf; par->fastpll_mode = 0; @@ -603,10 +599,10 @@ int __init w100fb_probe(struct device *dev) goto out; } - device_create_file(dev, &dev_attr_fastpllclk); - device_create_file(dev, &dev_attr_reg_read); - device_create_file(dev, &dev_attr_reg_write); - device_create_file(dev, &dev_attr_flip); + device_create_file(&pdev->dev, &dev_attr_fastpllclk); + device_create_file(&pdev->dev, &dev_attr_reg_read); + device_create_file(&pdev->dev, &dev_attr_reg_write); + device_create_file(&pdev->dev, &dev_attr_flip); printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); return 0; @@ -625,15 +621,15 @@ out: } -static int w100fb_remove(struct device *dev) +static int w100fb_remove(struct platform_device *pdev) { - struct fb_info *info = dev_get_drvdata(dev); + struct fb_info *info = platform_get_drvdata(pdev); struct w100fb_par *par=info->par; - device_remove_file(dev, &dev_attr_fastpllclk); - device_remove_file(dev, &dev_attr_reg_read); - device_remove_file(dev, &dev_attr_reg_write); - device_remove_file(dev, &dev_attr_flip); + device_remove_file(&pdev->dev, &dev_attr_fastpllclk); + device_remove_file(&pdev->dev, &dev_attr_reg_read); + device_remove_file(&pdev->dev, &dev_attr_reg_write); + device_remove_file(&pdev->dev, &dev_attr_flip); unregister_framebuffer(info); @@ -1451,23 +1447,24 @@ static void w100_vsync(void) writel(0x00000002, remapped_regs + mmGEN_INT_STATUS); } -static struct device_driver w100fb_driver = { - .name = "w100fb", - .bus = &platform_bus_type, +static struct platform_driver w100fb_driver = { .probe = w100fb_probe, .remove = w100fb_remove, .suspend = w100fb_suspend, .resume = w100fb_resume, + .driver = { + .name = "w100fb", + }, }; int __devinit w100fb_init(void) { - return driver_register(&w100fb_driver); + return platform_driver_register(&w100fb_driver); } void __exit w100fb_cleanup(void) { - driver_unregister(&w100fb_driver); + platform_driver_unregister(&w100fb_driver); } module_init(w100fb_init); |