diff options
Diffstat (limited to 'drivers/video')
109 files changed, 13572 insertions, 8120 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index b1cb72c..eebcb70 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -3,8 +3,14 @@ # menu "Graphics support" + depends on HAS_IOMEM source "drivers/video/backlight/Kconfig" +source "drivers/video/display/Kconfig" + +config VGASTATE + tristate + default n config FB tristate "Support for frame buffer devices" @@ -90,6 +96,43 @@ config FB_CFB_IMAGEBLIT blitting. This is used by drivers that don't provide their own (accelerated) version. +config FB_SYS_FILLRECT + tristate + depends on FB + default n + ---help--- + Include the sys_fillrect function for generic software rectangle + filling. This is used by drivers that don't provide their own + (accelerated) version and the framebuffer is in system RAM. + +config FB_SYS_COPYAREA + tristate + depends on FB + default n + ---help--- + Include the sys_copyarea function for generic software area copying. + This is used by drivers that don't provide their own (accelerated) + version and the framebuffer is in system RAM. + +config FB_SYS_IMAGEBLIT + tristate + depends on FB + default n + ---help--- + Include the sys_imageblit function for generic software image + blitting. This is used by drivers that don't provide their own + (accelerated) version and the framebuffer is in system RAM. + +config FB_SYS_FOPS + tristate + depends on FB + default n + +config FB_DEFERRED_IO + bool + depends on FB + default y + config FB_SVGALIB tristate depends on FB @@ -191,7 +234,7 @@ config FB_ARMCLCD If you want to compile this as a module (=code which can be inserted into and removed from the running kernel), say M - here and read <file:Documentation/modules.txt>. The module + here and read <file:Documentation/kbuild/modules.txt>. The module will be called amba-clcd. choice @@ -375,9 +418,10 @@ config FB_FM2 config FB_ARC tristate "Arc Monochrome LCD board support" depends on FB && X86 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS 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 @@ -389,7 +433,10 @@ config FB_ARC config FB_ATARI bool "Atari native chipset support" - depends on (FB = y) && ATARI && BROKEN + depends on (FB = y) && ATARI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT help This is the frame buffer device driver for the builtin graphics chipset found in Ataris. @@ -472,6 +519,8 @@ config FB_VGA16 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select VGASTATE + select FONT_8x16 if FRAMEBUFFER_CONSOLE help This is the frame buffer device driver for VGA 16 color graphic cards. Say Y if you have such a card. @@ -516,15 +565,25 @@ config FB_HP300 default y config FB_TGA - tristate "TGA framebuffer support" - depends on FB && ALPHA + tristate "TGA/SFB+ framebuffer support" + depends on FB && (ALPHA || TC) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select BITREVERSE - help - This is the frame buffer device driver for generic TGA graphic - cards. Say Y if you have one of those. + ---help--- + This is the frame buffer device driver for generic TGA and SFB+ + graphic cards. These include DEC ZLXp-E1, -E2 and -E3 PCI cards, + also known as PBXGA-A, -B and -C, and DEC ZLX-E1, -E2 and -E3 + TURBOchannel cards, also known as PMAGD-A, -B and -C. + + Due to hardware limitations ZLX-E2 and E3 cards are not supported + for DECstation 5000/200 systems. Additionally due to firmware + limitations these cards may cause troubles with booting DECstation + 5000/240 and /260 systems, but are fully supported under Linux if + you manage to get it going. ;-) + + Say Y if you have one of those. config FB_VESA bool "VESA VGA graphics support" @@ -548,6 +607,21 @@ config FB_IMAC help This is the frame buffer device driver for the Intel-based Macintosh +config FB_HECUBA + tristate "Hecuba board support" + depends on FB && X86 && MMU + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + help + This enables support for the Hecuba board. This driver was tested + with an E-Ink 800x600 display and x86 SBCs through a 16 bit GPIO + interface (8 bit data, 4 bit control). If you anticpate using + this driver, say Y or M; otherwise say N. You must specify the + GPIO IO address to be used for setting control and data. + config FB_HGA tristate "Hercules mono graphics support" depends on FB && X86 @@ -674,6 +748,22 @@ config FB_S1D13XXX working with S1D13806). Product specs at <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm> +config FB_ATMEL + tristate "AT91/AT32 LCD Controller support" + depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || AVR32) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This enables support for the AT91/AT32 LCD Controller. + +config FB_INTSRAM + bool "Frame Buffer in internal SRAM" + depends on FB_ATMEL && ARCH_AT91SAM9261 + help + Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want + to let frame buffer in external SDRAM. + config FB_NVIDIA tristate "nVidia Framebuffer Support" depends on FB && PCI @@ -683,6 +773,7 @@ config FB_NVIDIA select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select BITREVERSE + select VGASTATE help This driver supports graphics boards with the nVidia chips, TNT and newer. For very old chipsets, such as the RIVA128, then use @@ -705,6 +796,15 @@ config FB_NVIDIA_I2C independently validate video mode parameters, you should say Y here. +config FB_NVIDIA_DEBUG + bool "Lots of debug output" + depends on FB_NVIDIA + default n + help + Say Y here if you want the nVidia driver to output all sorts + of debugging information to provide to the maintainer when + something goes wrong. + config FB_NVIDIA_BACKLIGHT bool "Support for backlight control" depends on FB_NVIDIA @@ -721,6 +821,7 @@ config FB_RIVA select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select BITREVERSE + select VGASTATE help This driver supports graphics boards with the nVidia Riva/Geforce chips. @@ -743,7 +844,7 @@ config FB_RIVA_I2C here. config FB_RIVA_DEBUG - bool "Lots of debug output from Riva(nVidia) driver" + bool "Lots of debug output" depends on FB_RIVA default n help @@ -767,6 +868,7 @@ config FB_I810 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select VGASTATE help This driver supports the on-board graphics built in to the Intel 810 and 815 chipsets. Say Y if you have and plan to use such a board. @@ -806,6 +908,22 @@ config FB_I810_I2C select FB_DDC help +config FB_LE80578 + tristate "Intel LE80578 (Vermilion) support" + depends on FB && PCI && X86 + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This driver supports the LE80578 (Vermilion Range) chipset + +config FB_CARILLO_RANCH + tristate "Intel Carillo Ranch support" + depends on FB_LE80578 && FB && PCI && X86 + help + This driver supports the LE80578 (Carillo Ranch) board + config FB_INTEL tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)" depends on FB && EXPERIMENTAL && PCI && X86 @@ -1117,6 +1235,8 @@ config FB_S3 select FB_CFB_IMAGEBLIT select FB_TILEBLITTING select FB_SVGALIB + select VGASTATE + select FONT_8x16 if FRAMEBUFFER_CONSOLE ---help--- Driver for graphics boards with S3 Trio / S3 Virge chip. @@ -1127,6 +1247,7 @@ config FB_SAVAGE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select VGASTATE help This driver supports notebooks and computers with S3 Savage PCI/AGP chips. @@ -1193,6 +1314,7 @@ config FB_NEOMAGIC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select VGASTATE help This driver supports notebooks with NeoMagic PCI chips. Say Y if you have such a graphics card. @@ -1252,6 +1374,20 @@ config FB_VOODOO1 Please read the <file:Documentation/fb/README-sstfb.txt> for supported options and other important info support. +config FB_VT8623 + tristate "VIA VT8623 support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_TILEBLITTING + select FB_SVGALIB + select VGASTATE + select FONT_8x16 if FRAMEBUFFER_CONSOLE + ---help--- + Driver for CastleRock integrated graphics core in the + VIA VT8623 [Apollo CLE266] chipset. + config FB_CYBLA tristate "Cyberblade/i1 support" depends on FB && PCI && X86_32 && !64BIT @@ -1305,9 +1441,26 @@ config FB_TRIDENT_ACCEL This will compile the Trident frame buffer device with acceleration functions. +config FB_ARK + tristate "ARK 2000PV support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_TILEBLITTING + select FB_SVGALIB + select VGASTATE + select FONT_8x16 if FRAMEBUFFER_CONSOLE + ---help--- + Driver for PCI graphics boards with ARK 2000PV chip + and ICS 5342 RAMDAC. + config FB_PM3 - tristate "Permedia3 support" - depends on FB && PCI && BROKEN + tristate "Permedia3 support (EXPERIMENTAL)" + depends on FB && PCI && EXPERIMENTAL + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT help This is the frame buffer device driver for the 3DLabs Permedia3 chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & @@ -1380,6 +1533,32 @@ config FB_LEO This is the frame buffer device driver for the SBUS-based Sun ZX (leo) frame buffer cards. +config FB_XVR500 + bool "Sun XVR-500 3DLABS Wildcat support" + depends on FB && PCI && SPARC64 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the Sun XVR-500 and similar + graphics cards based upon the 3DLABS Wildcat chipset. The driver + only works on sparc64 systems where the system firwmare has + mostly initialized the card already. It is treated as a + completely dumb framebuffer device. + +config FB_XVR2500 + bool "Sun XVR-2500 3DLABS Wildcat support" + depends on FB && PCI && SPARC64 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the Sun XVR-2500 and similar + graphics cards based upon the 3DLABS Wildcat chipset. The driver + only works on sparc64 systems where the system firwmare has + mostly initialized the card already. It is treated as a + completely dumb framebuffer device. + config FB_PCI bool "PCI framebuffers" depends on (FB = y) && PCI && SPARC @@ -1491,7 +1670,7 @@ config FB_PXA 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 pxafb. If you want to compile it as a module, - say M here and read <file:Documentation/modules.txt>. + say M here and read <file:Documentation/kbuild/modules.txt>. If unsure, say N. @@ -1544,7 +1723,7 @@ config FB_W100 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 w100fb. If you want to compile it as a module, - say M here and read <file:Documentation/modules.txt>. + say M here and read <file:Documentation/kbuild/modules.txt>. If unsure, say N. @@ -1561,7 +1740,7 @@ config FB_S3C2410 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 s3c2410fb. If you want to compile it as a module, - say M here and read <file:Documentation/modules.txt>. + say M here and read <file:Documentation/kbuild/modules.txt>. If unsure, say N. config FB_S3C2410_DEBUG @@ -1633,13 +1812,25 @@ config FB_PS3_DEFAULT_SIZE_M The default value can be overridden on the kernel command line using the "ps3fb" option (e.g. "ps3fb=9M"); -config FB_VIRTUAL - tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" - depends on FB +config FB_XILINX + tristate "Xilinx frame buffer support" + depends on FB && XILINX_VIRTEX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT ---help--- + Include support for the Xilinx ML300/ML403 reference design + framebuffer. ML300 carries a 640*480 LCD display on the board, + ML403 uses a standard DB15 VGA connector. + +config FB_VIRTUAL + tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" + depends on FB + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + ---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 board. This means you cannot see any output sent to this frame diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 760305c..bd8b052 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -4,6 +4,7 @@ # Each configuration option enables a list of files. +obj-$(CONFIG_VGASTATE) += vgastate.o obj-y += fb_notify.o obj-$(CONFIG_FB) += fb.o fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ @@ -12,14 +13,19 @@ fb-objs := $(fb-y) obj-$(CONFIG_VT) += console/ obj-$(CONFIG_LOGO) += logo/ -obj-y += backlight/ +obj-y += backlight/ display/ obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o +obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o +obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o +obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o +obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o obj-$(CONFIG_FB_SVGALIB) += svgalib.o obj-$(CONFIG_FB_MACMODES) += macmodes.o obj-$(CONFIG_FB_DDC) += fb_ddc.o +obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o # Hardware specific drivers go first obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o @@ -30,7 +36,7 @@ obj-$(CONFIG_FB_PM2) += pm2fb.o obj-$(CONFIG_FB_PM3) += pm3fb.o obj-$(CONFIG_FB_MATROX) += matrox/ -obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o +obj-$(CONFIG_FB_RIVA) += riva/ obj-$(CONFIG_FB_NVIDIA) += nvidia/ obj-$(CONFIG_FB_ATY) += aty/ macmodes.o obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o @@ -40,8 +46,7 @@ obj-$(CONFIG_FB_KYRO) += kyro/ obj-$(CONFIG_FB_SAVAGE) += savage/ obj-$(CONFIG_FB_GEODE) += geode/ obj-$(CONFIG_FB_MBX) += mbx/ -obj-$(CONFIG_FB_I810) += vgastate.o -obj-$(CONFIG_FB_NEOMAGIC) += neofb.o vgastate.o +obj-$(CONFIG_FB_NEOMAGIC) += neofb.o obj-$(CONFIG_FB_3DFX) += tdfxfb.o obj-$(CONFIG_FB_CONTROL) += controlfb.o obj-$(CONFIG_FB_PLATINUM) += platinumfb.o @@ -49,9 +54,12 @@ obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o obj-$(CONFIG_FB_CT65550) += chipsfb.o obj-$(CONFIG_FB_IMSTT) += imsttfb.o obj-$(CONFIG_FB_FM2) += fm2fb.o +obj-$(CONFIG_FB_VT8623) += vt8623fb.o obj-$(CONFIG_FB_CYBLA) += cyblafb.o obj-$(CONFIG_FB_TRIDENT) += tridentfb.o -obj-$(CONFIG_FB_S3) += s3fb.o vgastate.o +obj-$(CONFIG_FB_LE80578) += vermilion/ +obj-$(CONFIG_FB_S3) += s3fb.o +obj-$(CONFIG_FB_ARK) += arkfb.o obj-$(CONFIG_FB_STI) += stifb.o obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o @@ -63,9 +71,13 @@ obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o obj-$(CONFIG_FB_SGIVW) += sgivwfb.o obj-$(CONFIG_FB_ACORN) += acornfb.o -obj-$(CONFIG_FB_ATARI) += atafb.o +obj-$(CONFIG_FB_ATARI) += atafb.o c2p.o atafb_mfb.o \ + atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o obj-$(CONFIG_FB_MAC) += macfb.o +obj-$(CONFIG_FB_HECUBA) += hecubafb.o obj-$(CONFIG_FB_HGA) += hgafb.o +obj-$(CONFIG_FB_XVR500) += sunxvr500.o +obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o obj-$(CONFIG_FB_IGA) += igafb.o obj-$(CONFIG_FB_APOLLO) += dnfb.o obj-$(CONFIG_FB_Q40) += q40fb.o @@ -75,6 +87,7 @@ obj-$(CONFIG_FB_G364) += g364fb.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o obj-$(CONFIG_FB_HIT) += hitfb.o obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o +obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o @@ -99,11 +112,12 @@ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o obj-$(CONFIG_FB_PS3) += ps3fb.o obj-$(CONFIG_FB_SM501) += sm501fb.o +obj-$(CONFIG_FB_XILINX) += xilinxfb.o # Platform or fallback drivers go here obj-$(CONFIG_FB_VESA) += vesafb.o obj-$(CONFIG_FB_IMAC) += imacfb.o -obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o +obj-$(CONFIG_FB_VGA16) += vga16fb.o obj-$(CONFIG_FB_OF) += offb.o # the test framebuffer is last diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 30a83697..db15bac 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -262,7 +262,8 @@ static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper, ks108_set_yaddr(par, chipindex, upper/8); linesize = par->info->var.xres/8; - src = par->info->screen_base + (left/8) + (upper * linesize); + src = (unsigned char __force *) par->info->screen_base + (left/8) + + (upper * linesize); ks108_set_xaddr(par, chipindex, left); bitmask=1; @@ -368,7 +369,7 @@ static void arcfb_fillrect(struct fb_info *info, { struct arcfb_par *par = info->par; - cfb_fillrect(info, rect); + sys_fillrect(info, rect); /* update the physical lcd */ arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height); @@ -379,7 +380,7 @@ static void arcfb_copyarea(struct fb_info *info, { struct arcfb_par *par = info->par; - cfb_copyarea(info, area); + sys_copyarea(info, area); /* update the physical lcd */ arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height); @@ -389,7 +390,7 @@ static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image) { struct arcfb_par *par = info->par; - cfb_imageblit(info, image); + sys_imageblit(info, image); /* update the physical lcd */ arcfb_lcd_update(par, image->dx, image->dy, image->width, @@ -439,14 +440,11 @@ static int arcfb_ioctl(struct fb_info *info, * the fb. it's inefficient for them to do anything less than 64*8 * writes since we update the lcd in each write() anyway. */ -static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t count, - loff_t *ppos) +static ssize_t arcfb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) { /* modded from epson 1355 */ - struct inode *inode; - int fbidx; - struct fb_info *info; unsigned long p; int err=-EINVAL; unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount; @@ -454,13 +452,6 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou unsigned int xres; p = *ppos; - inode = file->f_path.dentry->d_inode; - fbidx = iminor(inode); - info = registered_fb[fbidx]; - - if (!info || !info->screen_base) - return -ENODEV; - par = info->par; xres = info->var.xres; fbmemlength = (xres * info->var.yres)/8; @@ -477,7 +468,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou if (count) { char *base_addr; - base_addr = info->screen_base; + base_addr = (char __force *)info->screen_base; count -= copy_from_user(base_addr + p, buf, count); *ppos += count; err = -EFAULT; @@ -503,6 +494,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou static struct fb_ops arcfb_ops = { .owner = THIS_MODULE, .fb_open = arcfb_open, + .fb_read = fb_sys_read, .fb_write = arcfb_write, .fb_release = arcfb_release, .fb_pan_display = arcfb_pan_display, @@ -603,7 +595,7 @@ static int arcfb_remove(struct platform_device *dev) if (info) { unregister_framebuffer(info); - vfree(info->screen_base); + vfree((void __force *)info->screen_base); framebuffer_release(info); } return 0; diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c new file mode 100644 index 0000000..ba6fede --- /dev/null +++ b/drivers/video/arkfb.c @@ -0,0 +1,1200 @@ +/* + * linux/drivers/video/arkfb.c -- Frame buffer device driver for ARK 2000PV + * with ICS 5342 dac (it is easy to add support for different dacs). + * + * Copyright (c) 2007 Ondrej Zajicek <santiago@crfreenet.org> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Code is based on s3fb + */ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/svga.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */ +#include <video/vga.h> + +#ifdef CONFIG_MTRR +#include <asm/mtrr.h> +#endif + +struct arkfb_info { + int mclk_freq; + int mtrr_reg; + + struct dac_info *dac; + struct vgastate state; + struct mutex open_lock; + unsigned int ref_count; + u32 pseudo_palette[16]; +}; + + +/* ------------------------------------------------------------------------- */ + + +static const struct svga_fb_format arkfb_formats[] = { + { 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, + FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4, FB_VISUAL_PSEUDOCOLOR, 8, 8}, + { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 16}, + { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 1, + FB_TYPE_INTERLEAVED_PLANES, 1, FB_VISUAL_PSEUDOCOLOR, 8, 16}, + { 8, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 8}, + {16, {10, 5, 0}, {5, 5, 0}, {0, 5, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 4, 4}, + {16, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 4, 4}, + {24, {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 8, 8}, + {32, {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 2, 2}, + SVGA_FORMAT_END +}; + + +/* CRT timing register sets */ + +static const struct vga_regset ark_h_total_regs[] = {{0x00, 0, 7}, {0x41, 7, 7}, VGA_REGSET_END}; +static const struct vga_regset ark_h_display_regs[] = {{0x01, 0, 7}, {0x41, 6, 6}, VGA_REGSET_END}; +static const struct vga_regset ark_h_blank_start_regs[] = {{0x02, 0, 7}, {0x41, 5, 5}, VGA_REGSET_END}; +static const struct vga_regset ark_h_blank_end_regs[] = {{0x03, 0, 4}, {0x05, 7, 7 }, VGA_REGSET_END}; +static const struct vga_regset ark_h_sync_start_regs[] = {{0x04, 0, 7}, {0x41, 4, 4}, VGA_REGSET_END}; +static const struct vga_regset ark_h_sync_end_regs[] = {{0x05, 0, 4}, VGA_REGSET_END}; + +static const struct vga_regset ark_v_total_regs[] = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x40, 7, 7}, VGA_REGSET_END}; +static const struct vga_regset ark_v_display_regs[] = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x40, 6, 6}, VGA_REGSET_END}; +static const struct vga_regset ark_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x40, 5, 5}, VGA_REGSET_END}; +// const struct vga_regset ark_v_blank_end_regs[] = {{0x16, 0, 6}, VGA_REGSET_END}; +static const struct vga_regset ark_v_blank_end_regs[] = {{0x16, 0, 7}, VGA_REGSET_END}; +static const struct vga_regset ark_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x40, 4, 4}, VGA_REGSET_END}; +static const struct vga_regset ark_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END}; + +static const struct vga_regset ark_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, VGA_REGSET_END}; +static const struct vga_regset ark_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x40, 0, 2}, VGA_REGSET_END}; +static const struct vga_regset ark_offset_regs[] = {{0x13, 0, 7}, {0x41, 3, 3}, VGA_REGSET_END}; + +static const struct svga_timing_regs ark_timing_regs = { + ark_h_total_regs, ark_h_display_regs, ark_h_blank_start_regs, + ark_h_blank_end_regs, ark_h_sync_start_regs, ark_h_sync_end_regs, + ark_v_total_regs, ark_v_display_regs, ark_v_blank_start_regs, + ark_v_blank_end_regs, ark_v_sync_start_regs, ark_v_sync_end_regs, +}; + + +/* ------------------------------------------------------------------------- */ + + +/* Module parameters */ + +static char *mode = "640x480-8@60"; + +#ifdef CONFIG_MTRR +static int mtrr = 1; +#endif + +MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <santiago@crfreenet.org>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("fbdev driver for ARK 2000PV"); + +module_param(mode, charp, 0444); +MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc)"); + +#ifdef CONFIG_MTRR +module_param(mtrr, int, 0444); +MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)"); +#endif + +static int threshold = 4; + +module_param(threshold, int, 0644); +MODULE_PARM_DESC(threshold, "FIFO threshold"); + + +/* ------------------------------------------------------------------------- */ + + +static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map) +{ + const u8 *font = map->data; + u8 __iomem *fb = (u8 __iomem *)info->screen_base; + int i, c; + + if ((map->width != 8) || (map->height != 16) || + (map->depth != 1) || (map->length != 256)) { + printk(KERN_ERR "fb%d: unsupported font parameters: width %d, " + "height %d, depth %d, length %d\n", info->node, + map->width, map->height, map->depth, map->length); + return; + } + + fb += 2; + for (c = 0; c < map->length; c++) { + for (i = 0; i < map->height; i++) { + fb_writeb(font[i], &fb[i * 4]); + fb_writeb(font[i], &fb[i * 4 + (128 * 8)]); + } + fb += 128; + + if ((c % 8) == 7) + fb += 128*8; + + font += map->height; + } +} + +static struct fb_tile_ops arkfb_tile_ops = { + .fb_settile = arkfb_settile, + .fb_tilecopy = svga_tilecopy, + .fb_tilefill = svga_tilefill, + .fb_tileblit = svga_tileblit, + .fb_tilecursor = svga_tilecursor, + .fb_get_tilemax = svga_get_tilemax, +}; + + +/* ------------------------------------------------------------------------- */ + + +/* image data is MSB-first, fb structure is MSB-first too */ +static inline u32 expand_color(u32 c) +{ + return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF; +} + +/* arkfb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */ +static void arkfb_iplan_imageblit(struct fb_info *info, const struct fb_image *image) +{ + u32 fg = expand_color(image->fg_color); + u32 bg = expand_color(image->bg_color); + const u8 *src1, *src; + u8 __iomem *dst1; + u32 __iomem *dst; + u32 val; + int x, y; + + src1 = image->data; + dst1 = info->screen_base + (image->dy * info->fix.line_length) + + ((image->dx / 8) * 4); + + for (y = 0; y < image->height; y++) { + src = src1; + dst = (u32 __iomem *) dst1; + for (x = 0; x < image->width; x += 8) { + val = *(src++) * 0x01010101; + val = (val & fg) | (~val & bg); + fb_writel(val, dst++); + } + src1 += image->width / 8; + dst1 += info->fix.line_length; + } + +} + +/* arkfb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */ +static void arkfb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + u32 fg = expand_color(rect->color); + u8 __iomem *dst1; + u32 __iomem *dst; + int x, y; + + dst1 = info->screen_base + (rect->dy * info->fix.line_length) + + ((rect->dx / 8) * 4); + + for (y = 0; y < rect->height; y++) { + dst = (u32 __iomem *) dst1; + for (x = 0; x < rect->width; x += 8) { + fb_writel(fg, dst++); + } + dst1 += info->fix.line_length; + } + +} + + +/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */ +static inline u32 expand_pixel(u32 c) +{ + return (((c & 1) << 24) | ((c & 2) << 27) | ((c & 4) << 14) | ((c & 8) << 17) | + ((c & 16) << 4) | ((c & 32) << 7) | ((c & 64) >> 6) | ((c & 128) >> 3)) * 0xF; +} + +/* arkfb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */ +static void arkfb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image) +{ + u32 fg = image->fg_color * 0x11111111; + u32 bg = image->bg_color * 0x11111111; + const u8 *src1, *src; + u8 __iomem *dst1; + u32 __iomem *dst; + u32 val; + int x, y; + + src1 = image->data; + dst1 = info->screen_base + (image->dy * info->fix.line_length) + + ((image->dx / 8) * 4); + + for (y = 0; y < image->height; y++) { + src = src1; + dst = (u32 __iomem *) dst1; + for (x = 0; x < image->width; x += 8) { + val = expand_pixel(*(src++)); + val = (val & fg) | (~val & bg); + fb_writel(val, dst++); + } + src1 += image->width / 8; + dst1 += info->fix.line_length; + } + +} + +static void arkfb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + if ((info->var.bits_per_pixel == 4) && (image->depth == 1) + && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) { + if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES) + arkfb_iplan_imageblit(info, image); + else + arkfb_cfb4_imageblit(info, image); + } else + cfb_imageblit(info, image); +} + +static void arkfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + if ((info->var.bits_per_pixel == 4) + && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0) + && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)) + arkfb_iplan_fillrect(info, rect); + else + cfb_fillrect(info, rect); +} + + +/* ------------------------------------------------------------------------- */ + + +enum +{ + DAC_PSEUDO8_8, + DAC_RGB1555_8, + DAC_RGB0565_8, + DAC_RGB0888_8, + DAC_RGB8888_8, + DAC_PSEUDO8_16, + DAC_RGB1555_16, + DAC_RGB0565_16, + DAC_RGB0888_16, + DAC_RGB8888_16, + DAC_MAX +}; + +struct dac_ops { + int (*dac_get_mode)(struct dac_info *info); + int (*dac_set_mode)(struct dac_info *info, int mode); + int (*dac_get_freq)(struct dac_info *info, int channel); + int (*dac_set_freq)(struct dac_info *info, int channel, u32 freq); + void (*dac_release)(struct dac_info *info); +}; + +typedef void (*dac_read_regs_t)(void *data, u8 *code, int count); +typedef void (*dac_write_regs_t)(void *data, u8 *code, int count); + +struct dac_info +{ + struct dac_ops *dacops; + dac_read_regs_t dac_read_regs; + dac_write_regs_t dac_write_regs; + void *data; +}; + + +static inline u8 dac_read_reg(struct dac_info *info, u8 reg) +{ + u8 code[2] = {reg, 0}; + info->dac_read_regs(info->data, code, 1); + return code[1]; +} + +static inline void dac_read_regs(struct dac_info *info, u8 *code, int count) +{ + info->dac_read_regs(info->data, code, count); +} + +static inline void dac_write_reg(struct dac_info *info, u8 reg, u8 val) +{ + u8 code[2] = {reg, val}; + info->dac_write_regs(info->data, code, 1); +} + +static inline void dac_write_regs(struct dac_info *info, u8 *code, int count) +{ + info->dac_write_regs(info->data, code, count); +} + +static inline int dac_set_mode(struct dac_info *info, int mode) +{ + return info->dacops->dac_set_mode(info, mode); +} + +static inline int dac_set_freq(struct dac_info *info, int channel, u32 freq) +{ + return info->dacops->dac_set_freq(info, channel, freq); +} + +static inline void dac_release(struct dac_info *info) +{ + info->dacops->dac_release(info); +} + + +/* ------------------------------------------------------------------------- */ + + +/* ICS5342 DAC */ + +struct ics5342_info +{ + struct dac_info dac; + u8 mode; +}; + +#define DAC_PAR(info) ((struct ics5342_info *) info) + +/* LSB is set to distinguish unused slots */ +static const u8 ics5342_mode_table[DAC_MAX] = { + [DAC_PSEUDO8_8] = 0x01, [DAC_RGB1555_8] = 0x21, [DAC_RGB0565_8] = 0x61, + [DAC_RGB0888_8] = 0x41, [DAC_PSEUDO8_16] = 0x11, [DAC_RGB1555_16] = 0x31, + [DAC_RGB0565_16] = 0x51, [DAC_RGB0888_16] = 0x91, [DAC_RGB8888_16] = 0x71 +}; + +static int ics5342_set_mode(struct dac_info *info, int mode) +{ + u8 code; + + if (mode >= DAC_MAX) + return -EINVAL; + + code = ics5342_mode_table[mode]; + + if (! code) + return -EINVAL; + + dac_write_reg(info, 6, code & 0xF0); + DAC_PAR(info)->mode = mode; + + return 0; +} + +static const struct svga_pll ics5342_pll = {3, 129, 3, 33, 0, 3, + 60000, 250000, 14318}; + +/* pd4 - allow only posdivider 4 (r=2) */ +static const struct svga_pll ics5342_pll_pd4 = {3, 129, 3, 33, 2, 2, + 60000, 335000, 14318}; + +/* 270 MHz should be upper bound for VCO clock according to specs, + but that is too restrictive in pd4 case */ + +static int ics5342_set_freq(struct dac_info *info, int channel, u32 freq) +{ + u16 m, n, r; + + /* only postdivider 4 (r=2) is valid in mode DAC_PSEUDO8_16 */ + int rv = svga_compute_pll((DAC_PAR(info)->mode == DAC_PSEUDO8_16) + ? &ics5342_pll_pd4 : &ics5342_pll, + freq, &m, &n, &r, 0); + + if (rv < 0) { + return -EINVAL; + } else { + u8 code[6] = {4, 3, 5, m-2, 5, (n-2) | (r << 5)}; + dac_write_regs(info, code, 3); + return 0; + } +} + +static void ics5342_release(struct dac_info *info) +{ + ics5342_set_mode(info, DAC_PSEUDO8_8); + kfree(info); +} + +static struct dac_ops ics5342_ops = { + .dac_set_mode = ics5342_set_mode, + .dac_set_freq = ics5342_set_freq, + .dac_release = ics5342_release +}; + + +static struct dac_info * ics5342_init(dac_read_regs_t drr, dac_write_regs_t dwr, void *data) +{ + struct dac_info *info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL); + + if (! info) + return NULL; + + info->dacops = &ics5342_ops; + info->dac_read_regs = drr; + info->dac_write_regs = dwr; + info->data = data; + DAC_PAR(info)->mode = DAC_PSEUDO8_8; /* estimation */ + return info; +} + + +/* ------------------------------------------------------------------------- */ + + +static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7}; + +static void ark_dac_read_regs(void *data, u8 *code, int count) +{ + u8 regval = vga_rseq(NULL, 0x1C); + + while (count != 0) + { + vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0); + code[1] = vga_r(NULL, dac_regs[code[0] & 3]); + count--; + code += 2; + } + + vga_wseq(NULL, 0x1C, regval); +} + +static void ark_dac_write_regs(void *data, u8 *code, int count) +{ + u8 regval = vga_rseq(NULL, 0x1C); + + while (count != 0) + { + vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0); + vga_w(NULL, dac_regs[code[0] & 3], code[1]); + count--; + code += 2; + } + + vga_wseq(NULL, 0x1C, regval); +} + + +static void ark_set_pixclock(struct fb_info *info, u32 pixclock) +{ + struct arkfb_info *par = info->par; + u8 regval; + + int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock); + if (rv < 0) { + printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); + return; + } + + /* Set VGA misc register */ + regval = vga_r(NULL, VGA_MIS_R); + vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); +} + + +/* Open framebuffer */ + +static int arkfb_open(struct fb_info *info, int user) +{ + struct arkfb_info *par = info->par; + + mutex_lock(&(par->open_lock)); + if (par->ref_count == 0) { + memset(&(par->state), 0, sizeof(struct vgastate)); + par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; + par->state.num_crtc = 0x60; + par->state.num_seq = 0x30; + save_vga(&(par->state)); + } + + par->ref_count++; + mutex_unlock(&(par->open_lock)); + + return 0; +} + +/* Close framebuffer */ + +static int arkfb_release(struct fb_info *info, int user) +{ + struct arkfb_info *par = info->par; + + mutex_lock(&(par->open_lock)); + if (par->ref_count == 0) { + mutex_unlock(&(par->open_lock)); + return -EINVAL; + } + + if (par->ref_count == 1) { + restore_vga(&(par->state)); + dac_set_mode(par->dac, DAC_PSEUDO8_8); + } + + par->ref_count--; + mutex_unlock(&(par->open_lock)); + + return 0; +} + +/* Validate passed in var */ + +static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + int rv, mem, step; + + /* Find appropriate format */ + rv = svga_match_format (arkfb_formats, var, NULL); + if (rv < 0) + { + printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node); + return rv; + } + + /* Do not allow to have real resoulution larger than virtual */ + if (var->xres > var->xres_virtual) + var->xres_virtual = var->xres; + + if (var->yres > var->yres_virtual) + var->yres_virtual = var->yres; + + /* Round up xres_virtual to have proper alignment of lines */ + step = arkfb_formats[rv].xresstep - 1; + var->xres_virtual = (var->xres_virtual+step) & ~step; + + + /* Check whether have enough memory */ + mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual; + if (mem > info->screen_size) + { + printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n", info->node, mem >> 10, (unsigned int) (info->screen_size >> 10)); + return -EINVAL; + } + + rv = svga_check_timings (&ark_timing_regs, var, info->node); + if (rv < 0) + { + printk(KERN_ERR "fb%d: invalid timings requested\n", info->node); + return rv; + } + + /* Interlaced mode is broken */ + if (var->vmode & FB_VMODE_INTERLACED) + return -EINVAL; + + return 0; +} + +/* Set video mode from par */ + +static int arkfb_set_par(struct fb_info *info) +{ + struct arkfb_info *par = info->par; + u32 value, mode, hmul, hdiv, offset_value, screen_size; + u32 bpp = info->var.bits_per_pixel; + u8 regval; + + if (bpp != 0) { + info->fix.ypanstep = 1; + info->fix.line_length = (info->var.xres_virtual * bpp) / 8; + + info->flags &= ~FBINFO_MISC_TILEBLITTING; + info->tileops = NULL; + + /* in 4bpp supports 8p wide tiles only, any tiles otherwise */ + info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0); + info->pixmap.blit_y = ~(u32)0; + + offset_value = (info->var.xres_virtual * bpp) / 64; + screen_size = info->var.yres_virtual * info->fix.line_length; + } else { + info->fix.ypanstep = 16; + info->fix.line_length = 0; + + info->flags |= FBINFO_MISC_TILEBLITTING; + info->tileops = &arkfb_tile_ops; + + /* supports 8x16 tiles only */ + info->pixmap.blit_x = 1 << (8 - 1); + info->pixmap.blit_y = 1 << (16 - 1); + + offset_value = info->var.xres_virtual / 16; + screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64; + } + + info->var.xoffset = 0; + info->var.yoffset = 0; + info->var.activate = FB_ACTIVATE_NOW; + + /* Unlock registers */ + svga_wcrt_mask(0x11, 0x00, 0x80); + + /* Blank screen and turn off sync */ + svga_wseq_mask(0x01, 0x20, 0x20); + svga_wcrt_mask(0x17, 0x00, 0x80); + + /* Set default values */ + svga_set_default_gfx_regs(); + svga_set_default_atc_regs(); + svga_set_default_seq_regs(); + svga_set_default_crt_regs(); + svga_wcrt_multi(ark_line_compare_regs, 0xFFFFFFFF); + svga_wcrt_multi(ark_start_address_regs, 0); + + /* ARK specific initialization */ + svga_wseq_mask(0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */ + svga_wseq_mask(0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */ + + vga_wseq(NULL, 0x13, info->fix.smem_start >> 16); + vga_wseq(NULL, 0x14, info->fix.smem_start >> 24); + vga_wseq(NULL, 0x15, 0); + vga_wseq(NULL, 0x16, 0); + + /* Set the FIFO threshold register */ + /* It is fascinating way to store 5-bit value in 8-bit register */ + regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1; + vga_wseq(NULL, 0x18, regval); + + /* Set the offset register */ + pr_debug("fb%d: offset register : %d\n", info->node, offset_value); + svga_wcrt_multi(ark_offset_regs, offset_value); + + /* fix for hi-res textmode */ + svga_wcrt_mask(0x40, 0x08, 0x08); + + if (info->var.vmode & FB_VMODE_DOUBLE) + svga_wcrt_mask(0x09, 0x80, 0x80); + else + svga_wcrt_mask(0x09, 0x00, 0x80); + + if (info->var.vmode & FB_VMODE_INTERLACED) + svga_wcrt_mask(0x44, 0x04, 0x04); + else + svga_wcrt_mask(0x44, 0x00, 0x04); + + hmul = 1; + hdiv = 1; + mode = svga_match_format(arkfb_formats, &(info->var), &(info->fix)); + + /* Set mode-specific register values */ + switch (mode) { + case 0: + pr_debug("fb%d: text mode\n", info->node); + svga_set_textmode_vga_regs(); + + vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */ + svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ + dac_set_mode(par->dac, DAC_PSEUDO8_8); + + break; + case 1: + pr_debug("fb%d: 4 bit pseudocolor\n", info->node); + vga_wgfx(NULL, VGA_GFX_MODE, 0x40); + + vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */ + svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ + dac_set_mode(par->dac, DAC_PSEUDO8_8); + break; + case 2: + pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); + + vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */ + svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ + dac_set_mode(par->dac, DAC_PSEUDO8_8); + break; + case 3: + pr_debug("fb%d: 8 bit pseudocolor\n", info->node); + + vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode */ + + if (info->var.pixclock > 20000) { + pr_debug("fb%d: not using multiplex\n", info->node); + svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ + dac_set_mode(par->dac, DAC_PSEUDO8_8); + } else { + pr_debug("fb%d: using multiplex\n", info->node); + svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ + dac_set_mode(par->dac, DAC_PSEUDO8_16); + hdiv = 2; + } + break; + case 4: + pr_debug("fb%d: 5/5/5 truecolor\n", info->node); + + vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */ + svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ + dac_set_mode(par->dac, DAC_RGB1555_16); + break; + case 5: + pr_debug("fb%d: 5/6/5 truecolor\n", info->node); + + vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */ + svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ + dac_set_mode(par->dac, DAC_RGB0565_16); + break; + case 6: + pr_debug("fb%d: 8/8/8 truecolor\n", info->node); + + vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode ??? */ + svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ + dac_set_mode(par->dac, DAC_RGB0888_16); + hmul = 3; + hdiv = 2; + break; + case 7: + pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); + + vga_wseq(NULL, 0x11, 0x1E); /* 32bpp accel mode */ + svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ + dac_set_mode(par->dac, DAC_RGB8888_16); + hmul = 2; + break; + default: + printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); + return -EINVAL; + } + + ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul); + svga_set_timings(&ark_timing_regs, &(info->var), hmul, hdiv, + (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, + (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, + hmul, info->node); + + /* Set interlaced mode start/end register */ + value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; + value = ((value * hmul / hdiv) / 8) - 5; + vga_wcrt(NULL, 0x42, (value + 1) / 2); + + memset_io(info->screen_base, 0x00, screen_size); + /* Device and screen back on */ + svga_wcrt_mask(0x17, 0x80, 0x80); + svga_wseq_mask(0x01, 0x00, 0x20); + + return 0; +} + +/* Set a colour register */ + +static int arkfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *fb) +{ + switch (fb->var.bits_per_pixel) { + case 0: + case 4: + if (regno >= 16) + return -EINVAL; + + if ((fb->var.bits_per_pixel == 4) && + (fb->var.nonstd == 0)) { + outb(0xF0, VGA_PEL_MSK); + outb(regno*16, VGA_PEL_IW); + } else { + outb(0x0F, VGA_PEL_MSK); + outb(regno, VGA_PEL_IW); + } + outb(red >> 10, VGA_PEL_D); + outb(green >> 10, VGA_PEL_D); + outb(blue >> 10, VGA_PEL_D); + break; + case 8: + if (regno >= 256) + return -EINVAL; + + outb(0xFF, VGA_PEL_MSK); + outb(regno, VGA_PEL_IW); + outb(red >> 10, VGA_PEL_D); + outb(green >> 10, VGA_PEL_D); + outb(blue >> 10, VGA_PEL_D); + break; + case 16: + if (regno >= 16) + return 0; + + if (fb->var.green.length == 5) + ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) | + ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11); + else if (fb->var.green.length == 6) + ((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) | + ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); + else + return -EINVAL; + break; + case 24: + case 32: + if (regno >= 16) + return 0; + + ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) | + (green & 0xFF00) | ((blue & 0xFF00) >> 8); + break; + default: + return -EINVAL; + } + + return 0; +} + +/* Set the display blanking state */ + +static int arkfb_blank(int blank_mode, struct fb_info *info) +{ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + pr_debug("fb%d: unblank\n", info->node); + svga_wseq_mask(0x01, 0x00, 0x20); + svga_wcrt_mask(0x17, 0x80, 0x80); + break; + case FB_BLANK_NORMAL: + pr_debug("fb%d: blank\n", info->node); + svga_wseq_mask(0x01, 0x20, 0x20); + svga_wcrt_mask(0x17, 0x80, 0x80); + break; + case FB_BLANK_POWERDOWN: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_VSYNC_SUSPEND: + pr_debug("fb%d: sync down\n", info->node); + svga_wseq_mask(0x01, 0x20, 0x20); + svga_wcrt_mask(0x17, 0x00, 0x80); + break; + } + return 0; +} + + +/* Pan the display */ + +static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +{ + unsigned int offset; + + /* Calculate the offset */ + if (var->bits_per_pixel == 0) { + offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); + offset = offset >> 2; + } else { + offset = (var->yoffset * info->fix.line_length) + + (var->xoffset * var->bits_per_pixel / 8); + offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 3); + } + + /* Set the offset */ + svga_wcrt_multi(ark_start_address_regs, offset); + + return 0; +} + + +/* ------------------------------------------------------------------------- */ + + +/* Frame buffer operations */ + +static struct fb_ops arkfb_ops = { + .owner = THIS_MODULE, + .fb_open = arkfb_open, + .fb_release = arkfb_release, + .fb_check_var = arkfb_check_var, + .fb_set_par = arkfb_set_par, + .fb_setcolreg = arkfb_setcolreg, + .fb_blank = arkfb_blank, + .fb_pan_display = arkfb_pan_display, + .fb_fillrect = arkfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = arkfb_imageblit, + .fb_get_caps = svga_get_caps, +}; + + +/* ------------------------------------------------------------------------- */ + + +/* PCI probe */ +static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct fb_info *info; + struct arkfb_info *par; + int rc; + u8 regval; + + /* Ignore secondary VGA device because there is no VGA arbitration */ + if (! svga_primary_device(dev)) { + dev_info(&(dev->dev), "ignoring secondary device\n"); + return -ENODEV; + } + + /* Allocate and fill driver data structure */ + info = framebuffer_alloc(sizeof(struct arkfb_info), NULL); + if (! info) { + dev_err(&(dev->dev), "cannot allocate memory\n"); + return -ENOMEM; + } + + par = info->par; + mutex_init(&par->open_lock); + + info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN; + info->fbops = &arkfb_ops; + + /* Prepare PCI device */ + rc = pci_enable_device(dev); + if (rc < 0) { + dev_err(&(dev->dev), "cannot enable PCI device\n"); + goto err_enable_device; + } + + rc = pci_request_regions(dev, "arkfb"); + if (rc < 0) { + dev_err(&(dev->dev), "cannot reserve framebuffer region\n"); + goto err_request_regions; + } + + par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info); + if (! par->dac) { + rc = -ENOMEM; + dev_err(&(dev->dev), "RAMDAC initialization failed\n"); + goto err_dac; + } + + info->fix.smem_start = pci_resource_start(dev, 0); + info->fix.smem_len = pci_resource_len(dev, 0); + + /* Map physical IO memory address into kernel space */ + info->screen_base = pci_iomap(dev, 0, 0); + if (! info->screen_base) { + rc = -ENOMEM; + dev_err(&(dev->dev), "iomap for framebuffer failed\n"); + goto err_iomap; + } + + /* FIXME get memsize */ + regval = vga_rseq(NULL, 0x10); + info->screen_size = (1 << (regval >> 6)) << 20; + info->fix.smem_len = info->screen_size; + + strcpy(info->fix.id, "ARK 2000PV"); + info->fix.mmio_start = 0; + info->fix.mmio_len = 0; + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + info->fix.ypanstep = 0; + info->fix.accel = FB_ACCEL_NONE; + info->pseudo_palette = (void*) (par->pseudo_palette); + + /* Prepare startup mode */ + rc = fb_find_mode(&(info->var), info, mode, NULL, 0, NULL, 8); + if (! ((rc == 1) || (rc == 2))) { + rc = -EINVAL; + dev_err(&(dev->dev), "mode %s not found\n", mode); + goto err_find_mode; + } + + rc = fb_alloc_cmap(&info->cmap, 256, 0); + if (rc < 0) { + dev_err(&(dev->dev), "cannot allocate colormap\n"); + goto err_alloc_cmap; + } + + rc = register_framebuffer(info); + if (rc < 0) { + dev_err(&(dev->dev), "cannot register framebugger\n"); + goto err_reg_fb; + } + + printk(KERN_INFO "fb%d: %s on %s, %d MB RAM\n", info->node, info->fix.id, + pci_name(dev), info->fix.smem_len >> 20); + + /* Record a reference to the driver data */ + pci_set_drvdata(dev, info); + +#ifdef CONFIG_MTRR + if (mtrr) { + par->mtrr_reg = -1; + par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1); + } +#endif + + return 0; + + /* Error handling */ +err_reg_fb: + fb_dealloc_cmap(&info->cmap); +err_alloc_cmap: +err_find_mode: + pci_iounmap(dev, info->screen_base); +err_iomap: + dac_release(par->dac); +err_dac: + pci_release_regions(dev); +err_request_regions: +/* pci_disable_device(dev); */ +err_enable_device: + framebuffer_release(info); + return rc; +} + +/* PCI remove */ + +static void __devexit ark_pci_remove(struct pci_dev *dev) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct arkfb_info *par = info->par; + + if (info) { +#ifdef CONFIG_MTRR + if (par->mtrr_reg >= 0) { + mtrr_del(par->mtrr_reg, 0, 0); + par->mtrr_reg = -1; + } +#endif + + dac_release(par->dac); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + + pci_iounmap(dev, info->screen_base); + pci_release_regions(dev); +/* pci_disable_device(dev); */ + + pci_set_drvdata(dev, NULL); + framebuffer_release(info); + } +} + + +#ifdef CONFIG_PM +/* PCI suspend */ + +static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct arkfb_info *par = info->par; + + dev_info(&(dev->dev), "suspend\n"); + + acquire_console_sem(); + mutex_lock(&(par->open_lock)); + + if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { + mutex_unlock(&(par->open_lock)); + release_console_sem(); + return 0; + } + + fb_set_suspend(info, 1); + + pci_save_state(dev); + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + + mutex_unlock(&(par->open_lock)); + release_console_sem(); + + return 0; +} + + +/* PCI resume */ + +static int ark_pci_resume (struct pci_dev* dev) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct arkfb_info *par = info->par; + + dev_info(&(dev->dev), "resume\n"); + + acquire_console_sem(); + mutex_lock(&(par->open_lock)); + + if (par->ref_count == 0) { + mutex_unlock(&(par->open_lock)); + release_console_sem(); + return 0; + } + + pci_set_power_state(dev, PCI_D0); + pci_restore_state(dev); + + if (pci_enable_device(dev)) + goto fail; + + pci_set_master(dev); + + arkfb_set_par(info); + fb_set_suspend(info, 0); + + mutex_unlock(&(par->open_lock)); +fail: + release_console_sem(); + return 0; +} +#else +#define ark_pci_suspend NULL +#define ark_pci_resume NULL +#endif /* CONFIG_PM */ + +/* List of boards that we are trying to support */ + +static struct pci_device_id ark_devices[] __devinitdata = { + {PCI_DEVICE(0xEDD8, 0xA099)}, + {0, 0, 0, 0, 0, 0, 0} +}; + + +MODULE_DEVICE_TABLE(pci, ark_devices); + +static struct pci_driver arkfb_pci_driver = { + .name = "arkfb", + .id_table = ark_devices, + .probe = ark_pci_probe, + .remove = __devexit_p(ark_pci_remove), + .suspend = ark_pci_suspend, + .resume = ark_pci_resume, +}; + +/* Cleanup */ + +static void __exit arkfb_cleanup(void) +{ + pr_debug("arkfb: cleaning up\n"); + pci_unregister_driver(&arkfb_pci_driver); +} + +/* Driver Initialisation */ + +static int __init arkfb_init(void) +{ + +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("arkfb", &option)) + return -ENODEV; + + if (option && *option) + mode = option; +#endif + + pr_debug("arkfb: initializing\n"); + return pci_register_driver(&arkfb_pci_driver); +} + +module_init(arkfb_init); +module_exit(arkfb_cleanup); diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index bffe2b9..0038a05 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -2,7 +2,7 @@ * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device * * Copyright (C) 1994 Martin Schaller & Roman Hodek - * + * * 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. @@ -70,14 +70,8 @@ #include <linux/fb.h> #include <asm/atarikb.h> -#include <video/fbcon.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-iplan2p2.h> -#include <video/fbcon-iplan2p4.h> -#include <video/fbcon-iplan2p8.h> -#include <video/fbcon-mfb.h> - +#include "c2p.h" +#include "atafb.h" #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */ #define SWITCH_SND6 0x40 @@ -87,22 +81,48 @@ #define up(x, r) (((x) + (r) - 1) & ~((r)-1)) + /* + * Interface to the world + */ + +static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); +static int atafb_set_par(struct fb_info *info); +static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, + unsigned int blue, unsigned int transp, + struct fb_info *info); +static int atafb_blank(int blank, struct fb_info *info); +static int atafb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info); +static void atafb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect); +static void atafb_copyarea(struct fb_info *info, + const struct fb_copyarea *region); +static void atafb_imageblit(struct fb_info *info, const struct fb_image *image); +static int atafb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg); + -static int default_par=0; /* default resolution (0=none) */ +static int default_par; /* default resolution (0=none) */ -static unsigned long default_mem_req=0; +static unsigned long default_mem_req; -static int hwscroll=-1; +static int hwscroll = -1; static int use_hwscroll = 1; -static int sttt_xres=640,st_yres=400,tt_yres=480; -static int sttt_xres_virtual=640,sttt_yres_virtual=400; -static int ovsc_offset=0, ovsc_addlen=0; +static int sttt_xres = 640, st_yres = 400, tt_yres = 480; +static int sttt_xres_virtual = 640, sttt_yres_virtual = 400; +static int ovsc_offset, ovsc_addlen; + + /* + * Hardware parameters for current mode + */ static struct atafb_par { void *screen_base; int yres_virtual; + u_long next_line; + u_long next_plane; #if defined ATAFB_TT || defined ATAFB_STE union { struct { @@ -138,7 +158,7 @@ static struct atafb_par { /* Don't calculate an own resolution, and thus don't change the one found when * booting (currently used for the Falcon to keep settings for internal video * hardware extensions (e.g. ScreenBlaster) */ -static int DontCalcRes = 0; +static int DontCalcRes = 0; #ifdef ATAFB_FALCON #define HHT hw.falcon.hht @@ -163,83 +183,84 @@ static int DontCalcRes = 0; #define VMO_PREMASK 0x0c #endif -static struct fb_info fb_info; +static struct fb_info fb_info = { + .fix = { + .id = "Atari ", + .visual = FB_VISUAL_PSEUDOCOLOR, + .accel = FB_ACCEL_NONE, + } +}; static void *screen_base; /* base address of screen */ static void *real_screen_base; /* (only for Overscan) */ static int screen_len; -static int current_par_valid=0; +static int current_par_valid; -static int mono_moni=0; - -static struct display disp; +static int mono_moni; #ifdef ATAFB_EXT -/* external video handling */ -static unsigned external_xres; -static unsigned external_xres_virtual; -static unsigned external_yres; -/* not needed - atafb will never support panning/hardwarescroll with external - * static unsigned external_yres_virtual; -*/ +/* external video handling */ +static unsigned int external_xres; +static unsigned int external_xres_virtual; +static unsigned int external_yres; -static unsigned external_depth; -static int external_pmode; -static void *external_addr = 0; -static unsigned long external_len; -static unsigned long external_vgaiobase = 0; -static unsigned int external_bitspercol = 6; - -/* -JOE <joe@amber.dinoco.de>: -added card type for external driver, is only needed for -colormap handling. -*/ +/* + * not needed - atafb will never support panning/hardwarescroll with external + * static unsigned int external_yres_virtual; + */ +static unsigned int external_depth; +static int external_pmode; +static void *external_addr; +static unsigned long external_len; +static unsigned long external_vgaiobase; +static unsigned int external_bitspercol = 6; +/* + * JOE <joe@amber.dinoco.de>: + * added card type for external driver, is only needed for + * colormap handling. + */ enum cardtype { IS_VGA, IS_MV300 }; static enum cardtype external_card_type = IS_VGA; /* -The MV300 mixes the color registers. So we need an array of munged -indices in order to access the correct reg. -*/ -static int MV300_reg_1bit[2]={0,1}; -static int MV300_reg_4bit[16]={ -0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; -static int MV300_reg_8bit[256]={ -0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, -8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, -4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, -12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, -2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, -10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, -6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, -14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, -1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, -9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, -5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, -13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, -3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, -11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, -7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, -15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; + * The MV300 mixes the color registers. So we need an array of munged + * indices in order to access the correct reg. + */ +static int MV300_reg_1bit[2] = { + 0, 1 +}; +static int MV300_reg_4bit[16] = { + 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 +}; +static int MV300_reg_8bit[256] = { + 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, + 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, + 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, + 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, + 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, + 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, + 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, + 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, + 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, + 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, + 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, + 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, + 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, + 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, + 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, + 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 +}; static int *MV300_reg = MV300_reg_8bit; - -/* -And on the MV300 it's difficult to read out the hardware palette. So we -just keep track of the set colors in our own array here, and use that! -*/ - -static struct { unsigned char red,green,blue,pad; } ext_color[256]; #endif /* ATAFB_EXT */ -static int inverse=0; +static int inverse; extern int fontheight_8x8; extern int fontwidth_8x8; @@ -249,96 +270,154 @@ extern int fontheight_8x16; extern int fontwidth_8x16; extern unsigned char fontdata_8x16[]; +/* + * struct fb_ops { + * * open/release and usage marking + * struct module *owner; + * int (*fb_open)(struct fb_info *info, int user); + * int (*fb_release)(struct fb_info *info, int user); + * + * * For framebuffers with strange non linear layouts or that do not + * * work with normal memory mapped access + * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos); + * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos); + * + * * checks var and eventually tweaks it to something supported, + * * DOES NOT MODIFY PAR * + * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info); + * + * * set the video mode according to info->var * + * int (*fb_set_par)(struct fb_info *info); + * + * * set color register * + * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green, + * unsigned int blue, unsigned int transp, struct fb_info *info); + * + * * set color registers in batch * + * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info); + * + * * blank display * + * int (*fb_blank)(int blank, struct fb_info *info); + * + * * pan display * + * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); + * + * *** The meat of the drawing engine *** + * * Draws a rectangle * + * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); + * * Copy data from area to another * + * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); + * * Draws a image to the display * + * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); + * + * * Draws cursor * + * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor); + * + * * Rotates the display * + * void (*fb_rotate)(struct fb_info *info, int angle); + * + * * wait for blit idle, optional * + * int (*fb_sync)(struct fb_info *info); + * + * * perform fb specific ioctl (optional) * + * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, + * unsigned long arg); + * + * * Handle 32bit compat ioctl (optional) * + * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd, + * unsigned long arg); + * + * * perform fb specific mmap * + * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); + * + * * save current hardware state * + * void (*fb_save_state)(struct fb_info *info); + * + * * restore saved state * + * void (*fb_restore_state)(struct fb_info *info); + * } ; + */ + + /* ++roman: This structure abstracts from the underlying hardware (ST(e), * TT, or Falcon. * - * int (*detect)( void ) + * int (*detect)(void) * This function should detect the current video mode settings and * store them in atafb_predefined[0] for later reference by the * user. Return the index+1 of an equivalent predefined mode or 0 * if there is no such. - * - * int (*encode_fix)( struct fb_fix_screeninfo *fix, - * struct atafb_par *par ) + * + * int (*encode_fix)(struct fb_fix_screeninfo *fix, + * struct atafb_par *par) * This function should fill in the 'fix' structure based on the * values in the 'par' structure. - * - * int (*decode_var)( struct fb_var_screeninfo *var, - * struct atafb_par *par ) + * !!! Obsolete, perhaps !!! + * + * int (*decode_var)(struct fb_var_screeninfo *var, + * struct atafb_par *par) * Get the video params out of 'var'. If a value doesn't fit, round * it up, if it's too big, return EINVAL. - * Round up in the following order: bits_per_pixel, xres, yres, - * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, + * Round up in the following order: bits_per_pixel, xres, yres, + * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, * horizontal timing, vertical timing. * - * int (*encode_var)( struct fb_var_screeninfo *var, - * struct atafb_par *par ); + * int (*encode_var)(struct fb_var_screeninfo *var, + * struct atafb_par *par); * Fill the 'var' structure based on the values in 'par' and maybe * other values read out of the hardware. - * - * void (*get_par)( struct atafb_par *par ) + * + * void (*get_par)(struct atafb_par *par) * Fill the hardware's 'par' structure. - * - * void (*set_par)( struct atafb_par *par ) + * !!! Used only by detect() !!! + * + * void (*set_par)(struct atafb_par *par) * Set the hardware according to 'par'. - * - * int (*getcolreg)( unsigned regno, unsigned *red, - * unsigned *green, unsigned *blue, - * unsigned *transp, struct fb_info *info ) - * Read a single color register and split it into - * colors/transparent. Return != 0 for invalid regno. * * void (*set_screen_base)(void *s_base) * Set the base address of the displayed frame buffer. Only called * if yres_virtual > yres or xres_virtual > xres. * - * int (*blank)( int blank_mode ) - * Blank the screen if blank_mode!=0, else unblank. If blank==NULL then + * int (*blank)(int blank_mode) + * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then * the caller blanks by setting the CLUT to all black. Return 0 if blanking * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which * doesn't support it. Implements VESA suspend and powerdown modes on * hardware that supports disabling hsync/vsync: - * blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown. + * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown. */ static struct fb_hwswitch { - int (*detect)( void ); - int (*encode_fix)( struct fb_fix_screeninfo *fix, - struct atafb_par *par ); - int (*decode_var)( struct fb_var_screeninfo *var, - struct atafb_par *par ); - int (*encode_var)( struct fb_var_screeninfo *var, - struct atafb_par *par ); - void (*get_par)( struct atafb_par *par ); - void (*set_par)( struct atafb_par *par ); - int (*getcolreg)( unsigned regno, unsigned *red, - unsigned *green, unsigned *blue, - unsigned *transp, struct fb_info *info ); + int (*detect)(void); + int (*encode_fix)(struct fb_fix_screeninfo *fix, + struct atafb_par *par); + int (*decode_var)(struct fb_var_screeninfo *var, + struct atafb_par *par); + int (*encode_var)(struct fb_var_screeninfo *var, + struct atafb_par *par); + void (*get_par)(struct atafb_par *par); + void (*set_par)(struct atafb_par *par); void (*set_screen_base)(void *s_base); - int (*blank)( int blank_mode ); - int (*pan_display)( struct fb_var_screeninfo *var, - struct atafb_par *par); + int (*blank)(int blank_mode); + int (*pan_display)(struct fb_var_screeninfo *var, + struct fb_info *info); } *fbhw; -static char *autodetect_names[] = {"autodetect", NULL}; -static char *stlow_names[] = {"stlow", NULL}; -static char *stmid_names[] = {"stmid", "default5", NULL}; -static char *sthigh_names[] = {"sthigh", "default4", NULL}; -static char *ttlow_names[] = {"ttlow", NULL}; -static char *ttmid_names[]= {"ttmid", "default1", NULL}; -static char *tthigh_names[]= {"tthigh", "default2", NULL}; -static char *vga2_names[] = {"vga2", NULL}; -static char *vga4_names[] = {"vga4", NULL}; -static char *vga16_names[] = {"vga16", "default3", NULL}; -static char *vga256_names[] = {"vga256", NULL}; -static char *falh2_names[] = {"falh2", NULL}; -static char *falh16_names[] = {"falh16", NULL}; +static char *autodetect_names[] = { "autodetect", NULL }; +static char *stlow_names[] = { "stlow", NULL }; +static char *stmid_names[] = { "stmid", "default5", NULL }; +static char *sthigh_names[] = { "sthigh", "default4", NULL }; +static char *ttlow_names[] = { "ttlow", NULL }; +static char *ttmid_names[] = { "ttmid", "default1", NULL }; +static char *tthigh_names[] = { "tthigh", "default2", NULL }; +static char *vga2_names[] = { "vga2", NULL }; +static char *vga4_names[] = { "vga4", NULL }; +static char *vga16_names[] = { "vga16", "default3", NULL }; +static char *vga256_names[] = { "vga256", NULL }; +static char *falh2_names[] = { "falh2", NULL }; +static char *falh16_names[] = { "falh16", NULL }; static char **fb_var_names[] = { - /* Writing the name arrays directly in this array (via "(char *[]){...}") - * crashes gcc 2.5.8 (sigsegv) if the inner array - * contains more than two items. I've also seen that all elements - * were identical to the last (my cross-gcc) :-(*/ autodetect_names, stlow_names, stmid_names, @@ -353,18 +432,17 @@ static char **fb_var_names[] = { falh2_names, falh16_names, NULL - /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */ }; static struct fb_var_screeninfo atafb_predefined[] = { - /* - * yres_virtual==0 means use hw-scrolling if possible, else yres - */ - { /* autodetect */ - 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */ - {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/ + /* + * yres_virtual == 0 means use hw-scrolling if possible, else yres + */ + { /* autodetect */ + 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */ + {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/ 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { /* st low */ + { /* st low */ 320, 200, 320, 0, 0, 0, 4, 0, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, @@ -414,27 +492,100 @@ static struct fb_var_screeninfo atafb_predefined[] = { 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, }; -static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined); +static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined); +static struct fb_videomode atafb_modedb[] __initdata = { + /* + * Atari Video Modes + * + * If you change these, make sure to update DEFMODE_* as well! + */ -static int -get_video_mode(char *vname) + /* + * ST/TT Video Modes + */ + + { + /* 320x200, 15 kHz, 60 Hz (ST low) */ + "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + }, { + /* 640x200, 15 kHz, 60 Hz (ST medium) */ + "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + }, { + /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */ + "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + }, { + /* 320x480, 15 kHz, 60 Hz (TT low) */ + "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + }, { + /* 640x480, 29 kHz, 57 Hz (TT medium) */ + "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + }, { + /* 1280x960, 29 kHz, 60 Hz (TT high) */ + "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + }, + + /* + * VGA Video Modes + */ + + { + /* 640x480, 31 kHz, 60 Hz (VGA) */ + "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + }, { + /* 640x400, 31 kHz, 70 Hz (VGA) */ + "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3, + FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + }, + + /* + * Falcon HiRes Video Modes + */ + + { + /* 896x608, 31 kHz, 60 Hz (Falcon High) */ + "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + }, +}; + +#define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb) + +static char *mode_option __initdata = NULL; + + /* default modes */ + +#define DEFMODE_TT 5 /* "tt-high" for TT */ +#define DEFMODE_F30 7 /* "vga70" for Falcon */ +#define DEFMODE_STE 2 /* "st-high" for ST/E */ +#define DEFMODE_EXT 6 /* "vga" for external */ + + +static int get_video_mode(char *vname) { - char ***name_list; - char **name; - int i; - name_list=fb_var_names; - for (i = 0 ; i < num_atafb_predefined ; i++) { - name=*(name_list++); - if (! name || ! *name) - break; - while (*name) { - if (! strcmp(vname, *name)) - return i+1; - name++; + char ***name_list; + char **name; + int i; + + name_list = fb_var_names; + for (i = 0; i < num_atafb_predefined; i++) { + name = *name_list++; + if (!name || !*name) + break; + while (*name) { + if (!strcmp(vname, *name)) + return i + 1; + name++; + } } - } - return 0; + return 0; } @@ -443,93 +594,84 @@ get_video_mode(char *vname) #ifdef ATAFB_TT -static int tt_encode_fix( struct fb_fix_screeninfo *fix, - struct atafb_par *par ) - +static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par) { int mode; - strcpy(fix->id,"Atari Builtin"); + strcpy(fix->id, "Atari Builtin"); fix->smem_start = (unsigned long)real_screen_base; fix->smem_len = screen_len; - fix->type=FB_TYPE_INTERLEAVED_PLANES; - fix->type_aux=2; - fix->visual=FB_VISUAL_PSEUDOCOLOR; + fix->type = FB_TYPE_INTERLEAVED_PLANES; + fix->type_aux = 2; + fix->visual = FB_VISUAL_PSEUDOCOLOR; mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK; if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) { - fix->type=FB_TYPE_PACKED_PIXELS; - fix->type_aux=0; + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; if (mode == TT_SHIFTER_TTHIGH) - fix->visual=FB_VISUAL_MONO01; + fix->visual = FB_VISUAL_MONO01; } - fix->xpanstep=0; - fix->ypanstep=1; - fix->ywrapstep=0; + fix->xpanstep = 0; + fix->ypanstep = 1; + fix->ywrapstep = 0; fix->line_length = 0; fix->accel = FB_ACCEL_ATARIBLITT; return 0; } - -static int tt_decode_var( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par) { - int xres=var->xres; - int yres=var->yres; - int bpp=var->bits_per_pixel; + int xres = var->xres; + int yres = var->yres; + int bpp = var->bits_per_pixel; int linelen; int yres_virtual = var->yres_virtual; if (mono_moni) { - if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2) + if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2) return -EINVAL; - par->hw.tt.mode=TT_SHIFTER_TTHIGH; - xres=sttt_xres*2; - yres=tt_yres*2; - bpp=1; + par->hw.tt.mode = TT_SHIFTER_TTHIGH; + xres = sttt_xres * 2; + yres = tt_yres * 2; + bpp = 1; } else { if (bpp > 8 || xres > sttt_xres || yres > tt_yres) return -EINVAL; if (bpp > 4) { - if (xres > sttt_xres/2 || yres > tt_yres) + if (xres > sttt_xres / 2 || yres > tt_yres) return -EINVAL; - par->hw.tt.mode=TT_SHIFTER_TTLOW; - xres=sttt_xres/2; - yres=tt_yres; - bpp=8; - } - else if (bpp > 2) { + par->hw.tt.mode = TT_SHIFTER_TTLOW; + xres = sttt_xres / 2; + yres = tt_yres; + bpp = 8; + } else if (bpp > 2) { if (xres > sttt_xres || yres > tt_yres) return -EINVAL; - if (xres > sttt_xres/2 || yres > st_yres/2) { - par->hw.tt.mode=TT_SHIFTER_TTMID; - xres=sttt_xres; - yres=tt_yres; - bpp=4; - } - else { - par->hw.tt.mode=TT_SHIFTER_STLOW; - xres=sttt_xres/2; - yres=st_yres/2; - bpp=4; + if (xres > sttt_xres / 2 || yres > st_yres / 2) { + par->hw.tt.mode = TT_SHIFTER_TTMID; + xres = sttt_xres; + yres = tt_yres; + bpp = 4; + } else { + par->hw.tt.mode = TT_SHIFTER_STLOW; + xres = sttt_xres / 2; + yres = st_yres / 2; + bpp = 4; } - } - else if (bpp > 1) { - if (xres > sttt_xres || yres > st_yres/2) + } else if (bpp > 1) { + if (xres > sttt_xres || yres > st_yres / 2) return -EINVAL; - par->hw.tt.mode=TT_SHIFTER_STMID; - xres=sttt_xres; - yres=st_yres/2; - bpp=2; - } - else if (var->xres > sttt_xres || var->yres > st_yres) { + par->hw.tt.mode = TT_SHIFTER_STMID; + xres = sttt_xres; + yres = st_yres / 2; + bpp = 2; + } else if (var->xres > sttt_xres || var->yres > st_yres) { return -EINVAL; - } - else { - par->hw.tt.mode=TT_SHIFTER_STHIGH; - xres=sttt_xres; - yres=st_yres; - bpp=1; + } else { + par->hw.tt.mode = TT_SHIFTER_STHIGH; + xres = sttt_xres; + yres = st_yres; + bpp = 1; } } if (yres_virtual <= 0) @@ -537,10 +679,10 @@ static int tt_decode_var( struct fb_var_screeninfo *var, else if (yres_virtual < yres) yres_virtual = yres; if (var->sync & FB_SYNC_EXT) - par->hw.tt.sync=0; + par->hw.tt.sync = 0; else - par->hw.tt.sync=1; - linelen=xres*bpp/8; + par->hw.tt.sync = 1; + linelen = xres * bpp / 8; if (yres_virtual * linelen > screen_len && screen_len) return -EINVAL; if (yres * linelen > screen_len && screen_len) @@ -552,154 +694,123 @@ static int tt_decode_var( struct fb_var_screeninfo *var, return 0; } -static int tt_encode_var( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par) { int linelen; memset(var, 0, sizeof(struct fb_var_screeninfo)); - var->red.offset=0; - var->red.length=4; - var->red.msb_right=0; - var->grayscale=0; - - var->pixclock=31041; - var->left_margin=120; /* these may be incorrect */ - var->right_margin=100; - var->upper_margin=8; - var->lower_margin=16; - var->hsync_len=140; - var->vsync_len=30; - - var->height=-1; - var->width=-1; + var->red.offset = 0; + var->red.length = 4; + var->red.msb_right = 0; + var->grayscale = 0; + + var->pixclock = 31041; + var->left_margin = 120; /* these may be incorrect */ + var->right_margin = 100; + var->upper_margin = 8; + var->lower_margin = 16; + var->hsync_len = 140; + var->vsync_len = 30; + + var->height = -1; + var->width = -1; if (par->hw.tt.sync & 1) - var->sync=0; + var->sync = 0; else - var->sync=FB_SYNC_EXT; + var->sync = FB_SYNC_EXT; switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) { case TT_SHIFTER_STLOW: - var->xres=sttt_xres/2; - var->xres_virtual=sttt_xres_virtual/2; - var->yres=st_yres/2; - var->bits_per_pixel=4; + var->xres = sttt_xres / 2; + var->xres_virtual = sttt_xres_virtual / 2; + var->yres = st_yres / 2; + var->bits_per_pixel = 4; break; case TT_SHIFTER_STMID: - var->xres=sttt_xres; - var->xres_virtual=sttt_xres_virtual; - var->yres=st_yres/2; - var->bits_per_pixel=2; + var->xres = sttt_xres; + var->xres_virtual = sttt_xres_virtual; + var->yres = st_yres / 2; + var->bits_per_pixel = 2; break; case TT_SHIFTER_STHIGH: - var->xres=sttt_xres; - var->xres_virtual=sttt_xres_virtual; - var->yres=st_yres; - var->bits_per_pixel=1; + var->xres = sttt_xres; + var->xres_virtual = sttt_xres_virtual; + var->yres = st_yres; + var->bits_per_pixel = 1; break; case TT_SHIFTER_TTLOW: - var->xres=sttt_xres/2; - var->xres_virtual=sttt_xres_virtual/2; - var->yres=tt_yres; - var->bits_per_pixel=8; + var->xres = sttt_xres / 2; + var->xres_virtual = sttt_xres_virtual / 2; + var->yres = tt_yres; + var->bits_per_pixel = 8; break; case TT_SHIFTER_TTMID: - var->xres=sttt_xres; - var->xres_virtual=sttt_xres_virtual; - var->yres=tt_yres; - var->bits_per_pixel=4; + var->xres = sttt_xres; + var->xres_virtual = sttt_xres_virtual; + var->yres = tt_yres; + var->bits_per_pixel = 4; break; case TT_SHIFTER_TTHIGH: - var->red.length=0; - var->xres=sttt_xres*2; - var->xres_virtual=sttt_xres_virtual*2; - var->yres=tt_yres*2; - var->bits_per_pixel=1; + var->red.length = 0; + var->xres = sttt_xres * 2; + var->xres_virtual = sttt_xres_virtual * 2; + var->yres = tt_yres * 2; + var->bits_per_pixel = 1; break; - } - var->blue=var->green=var->red; - var->transp.offset=0; - var->transp.length=0; - var->transp.msb_right=0; - linelen=var->xres_virtual * var->bits_per_pixel / 8; - if (! use_hwscroll) - var->yres_virtual=var->yres; + } + var->blue = var->green = var->red; + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; + linelen = var->xres_virtual * var->bits_per_pixel / 8; + if (!use_hwscroll) + var->yres_virtual = var->yres; else if (screen_len) { if (par->yres_virtual) var->yres_virtual = par->yres_virtual; else - /* yres_virtual==0 means use maximum */ + /* yres_virtual == 0 means use maximum */ var->yres_virtual = screen_len / linelen; } else { if (hwscroll < 0) var->yres_virtual = 2 * var->yres; else - var->yres_virtual=var->yres+hwscroll * 16; + var->yres_virtual = var->yres + hwscroll * 16; } - var->xoffset=0; + var->xoffset = 0; if (screen_base) - var->yoffset=(par->screen_base - screen_base)/linelen; + var->yoffset = (par->screen_base - screen_base) / linelen; else - var->yoffset=0; - var->nonstd=0; - var->activate=0; - var->vmode=FB_VMODE_NONINTERLACED; + var->yoffset = 0; + var->nonstd = 0; + var->activate = 0; + var->vmode = FB_VMODE_NONINTERLACED; return 0; } - -static void tt_get_par( struct atafb_par *par ) +static void tt_get_par(struct atafb_par *par) { unsigned long addr; - par->hw.tt.mode=shifter_tt.tt_shiftmode; - par->hw.tt.sync=shifter.syncmode; + par->hw.tt.mode = shifter_tt.tt_shiftmode; + par->hw.tt.sync = shifter.syncmode; addr = ((shifter.bas_hi & 0xff) << 16) | ((shifter.bas_md & 0xff) << 8) | ((shifter.bas_lo & 0xff)); par->screen_base = phys_to_virt(addr); } -static void tt_set_par( struct atafb_par *par ) +static void tt_set_par(struct atafb_par *par) { - shifter_tt.tt_shiftmode=par->hw.tt.mode; - shifter.syncmode=par->hw.tt.sync; + shifter_tt.tt_shiftmode = par->hw.tt.mode; + shifter.syncmode = par->hw.tt.sync; /* only set screen_base if really necessary */ if (current_par.screen_base != par->screen_base) fbhw->set_screen_base(par->screen_base); } - -static int tt_getcolreg(unsigned regno, unsigned *red, - unsigned *green, unsigned *blue, - unsigned *transp, struct fb_info *info) -{ - int t, col; - - if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) - regno += 254; - if (regno > 255) - return 1; - t = tt_palette[regno]; - col = t & 15; - col |= col << 4; - col |= col << 8; - *blue = col; - col = (t >> 4) & 15; - col |= col << 4; - col |= col << 8; - *green = col; - col = (t >> 8) & 15; - col |= col << 4; - col |= col << 8; - *red = col; - *transp = 0; - return 0; -} - - -static int tt_setcolreg(unsigned regno, unsigned red, - unsigned green, unsigned blue, - unsigned transp, struct fb_info *info) +static int tt_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) { if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) regno += 254; @@ -708,15 +819,14 @@ static int tt_setcolreg(unsigned regno, unsigned red, tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) | (blue >> 12)); if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == - TT_SHIFTER_STHIGH && regno == 254) + TT_SHIFTER_STHIGH && regno == 254) tt_palette[0] = 0; return 0; } - -static int tt_detect( void ) - -{ struct atafb_par par; +static int tt_detect(void) +{ + struct atafb_par par; /* Determine the connected monitor: The DMA sound must be * disabled before reading the MFP GPIP, because the Sound @@ -726,9 +836,9 @@ static int tt_detect( void ) * announced that the Eagle is TT compatible, but only the PCM is * missing... */ - if (ATARIHW_PRESENT(PCM_8BIT)) { + if (ATARIHW_PRESENT(PCM_8BIT)) { tt_dmasnd.ctrl = DMASND_CTRL_OFF; - udelay(20); /* wait a while for things to settle down */ + udelay(20); /* wait a while for things to settle down */ } mono_moni = (mfp.par_dt_reg & 0x80) == 0; @@ -755,19 +865,24 @@ static struct pixel_clock { unsigned long f; /* f/[Hz] */ unsigned long t; /* t/[ps] (=1/f) */ int right, hsync, left; /* standard timing in clock cycles, not pixel */ - /* hsync initialized in falcon_detect() */ + /* hsync initialized in falcon_detect() */ int sync_mask; /* or-mask for hw.falcon.sync to set this clock */ int control_mask; /* ditto, for hw.falcon.vid_control */ -} -f25 = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25}, -f32 = {32000000, 31250, 18, 0, 42, 0x0, 0}, -fext = { 0, 0, 18, 0, 42, 0x1, 0}; +} f25 = { + 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25 +}, f32 = { + 32000000, 31250, 18, 0, 42, 0x0, 0 +}, fext = { + 0, 0, 18, 0, 42, 0x1, 0 +}; /* VIDEL-prescale values [mon_type][pixel_length from VCO] */ -static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}}; +static int vdl_prescale[4][3] = { + { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 } +}; /* Default hsync timing [mon_type] in picoseconds */ -static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000}; +static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 }; #ifdef FBCON_HAS_CFB16 static u16 fbcon_cfb16_cmap[16]; @@ -775,12 +890,12 @@ static u16 fbcon_cfb16_cmap[16]; static inline int hxx_prescale(struct falcon_hw *hw) { - return hw->ste_mode ? 16 : - vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3]; + return hw->ste_mode ? 16 + : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3]; } -static int falcon_encode_fix( struct fb_fix_screeninfo *fix, - struct atafb_par *par ) +static int falcon_encode_fix(struct fb_fix_screeninfo *fix, + struct atafb_par *par) { strcpy(fix->id, "Atari Builtin"); fix->smem_start = (unsigned long)real_screen_base; @@ -796,8 +911,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, fix->type_aux = 0; /* no smooth scrolling with longword aligned video mem */ fix->xpanstep = 32; - } - else if (par->hw.falcon.f_shift & 0x100) { + } else if (par->hw.falcon.f_shift & 0x100) { fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; /* Is this ok or should it be DIRECTCOLOR? */ @@ -809,9 +923,8 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, return 0; } - -static int falcon_decode_var( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int falcon_decode_var(struct fb_var_screeninfo *var, + struct atafb_par *par) { int bpp = var->bits_per_pixel; int xres = var->xres; @@ -823,17 +936,19 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, int linelen; int interlace = 0, doubleline = 0; struct pixel_clock *pclock; - int plen; /* width of pixel in clock cycles */ + int plen; /* width of pixel in clock cycles */ int xstretch; int prescale; int longoffset = 0; int hfreq, vfreq; + int hdb_off, hde_off, base_off; + int gstart, gend1, gend2, align; /* Get the video params out of 'var'. If a value doesn't fit, round it up, if it's too big, return EINVAL. - Round up in the following order: bits_per_pixel, xres, yres, - xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, + Round up in the following order: bits_per_pixel, xres, yres, + xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, horizontal timing, vertical timing. There is a maximum of screen resolution determined by pixelclock @@ -843,11 +958,11 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, Frequency range for multisync monitors is given via command line. For TV and SM124 both frequencies are fixed. - X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0) + X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0) Y % 16 == 0 to fit 8x16 font Y % 8 == 0 if Y<400 - Currently interlace and doubleline mode in var are ignored. + Currently interlace and doubleline mode in var are ignored. On SM124 and TV only the standard resolutions can be used. */ @@ -855,43 +970,38 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, if (!xres || !yres || !bpp) return -EINVAL; - if (mon_type == F_MON_SM && bpp != 1) { + if (mon_type == F_MON_SM && bpp != 1) return -EINVAL; - } - else if (bpp <= 1) { + + if (bpp <= 1) { bpp = 1; par->hw.falcon.f_shift = 0x400; par->hw.falcon.st_shift = 0x200; - } - else if (bpp <= 2) { + } else if (bpp <= 2) { bpp = 2; par->hw.falcon.f_shift = 0x000; par->hw.falcon.st_shift = 0x100; - } - else if (bpp <= 4) { + } else if (bpp <= 4) { bpp = 4; par->hw.falcon.f_shift = 0x000; par->hw.falcon.st_shift = 0x000; - } - else if (bpp <= 8) { + } else if (bpp <= 8) { bpp = 8; par->hw.falcon.f_shift = 0x010; - } - else if (bpp <= 16) { - bpp = 16; /* packed pixel mode */ - par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */ - } - else + } else if (bpp <= 16) { + bpp = 16; /* packed pixel mode */ + par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */ + } else return -EINVAL; par->hw.falcon.bpp = bpp; if (mon_type == F_MON_SM || DontCalcRes) { /* Skip all calculations. VGA/TV/SC1224 only supported. */ struct fb_var_screeninfo *myvar = &atafb_predefined[0]; - + if (bpp > myvar->bits_per_pixel || - var->xres > myvar->xres || - var->yres > myvar->yres) + var->xres > myvar->xres || + var->yres > myvar->yres) return -EINVAL; fbhw->get_par(par); /* Current par will be new par */ goto set_screen_base; /* Don't forget this */ @@ -910,8 +1020,8 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, yres = 400; /* 2 planes must use STE compatibility mode */ - par->hw.falcon.ste_mode = bpp==2; - par->hw.falcon.mono = bpp==1; + par->hw.falcon.ste_mode = bpp == 2; + par->hw.falcon.mono = bpp == 1; /* Total and visible scanline length must be a multiple of one longword, * this and the console fontwidth yields the alignment for xres and @@ -967,8 +1077,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, left_margin = hsync_len = 128 / plen; right_margin = 0; /* TODO set all margins */ - } - else + } else #endif if (mon_type == F_MON_SC || mon_type == F_MON_TV) { plen = 2 * xstretch; @@ -1002,26 +1111,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, vsync_len *= 2; } } - } - else - { /* F_MON_VGA */ + } else { /* F_MON_VGA */ if (bpp == 16) - xstretch = 2; /* Double pixel width only for hicolor */ + xstretch = 2; /* Double pixel width only for hicolor */ /* Default values are used for vert./hor. timing if no pixelclock given. */ if (var->pixclock == 0) { int linesize; /* Choose master pixelclock depending on hor. timing */ plen = 1 * xstretch; - if ((plen * xres + f25.right+f25.hsync+f25.left) * + if ((plen * xres + f25.right + f25.hsync + f25.left) * fb_info.monspecs.hfmin < f25.f) pclock = &f25; - else if ((plen * xres + f32.right+f32.hsync+f32.left) * - fb_info.monspecs.hfmin < f32.f) + else if ((plen * xres + f32.right + f32.hsync + + f32.left) * fb_info.monspecs.hfmin < f32.f) pclock = &f32; - else if ((plen * xres + fext.right+fext.hsync+fext.left) * - fb_info.monspecs.hfmin < fext.f - && fext.f) + else if ((plen * xres + fext.right + fext.hsync + + fext.left) * fb_info.monspecs.hfmin < fext.f && + fext.f) pclock = &fext; else return -EINVAL; @@ -1033,22 +1140,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, upper_margin = 31; lower_margin = 11; vsync_len = 3; - } - else { + } else { /* Choose largest pixelclock <= wanted clock */ int i; unsigned long pcl = ULONG_MAX; pclock = 0; - for (i=1; i <= 4; i *= 2) { - if (f25.t*i >= var->pixclock && f25.t*i < pcl) { + for (i = 1; i <= 4; i *= 2) { + if (f25.t * i >= var->pixclock && + f25.t * i < pcl) { pcl = f25.t * i; pclock = &f25; } - if (f32.t*i >= var->pixclock && f32.t*i < pcl) { + if (f32.t * i >= var->pixclock && + f32.t * i < pcl) { pcl = f32.t * i; pclock = &f32; } - if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) { + if (fext.t && fext.t * i >= var->pixclock && + fext.t * i < pcl) { pcl = fext.t * i; pclock = &fext; } @@ -1070,8 +1179,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, upper_margin = (upper_margin + 1) / 2; lower_margin = (lower_margin + 1) / 2; vsync_len = (vsync_len + 1) / 2; - } - else if (var->vmode & FB_VMODE_DOUBLE) { + } else if (var->vmode & FB_VMODE_DOUBLE) { /* External unit is [double lines per frame] */ upper_margin *= 2; lower_margin *= 2; @@ -1079,7 +1187,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, } } if (pclock == &fext) - longoffset = 1; /* VIDEL doesn't synchronize on short offset */ + longoffset = 1; /* VIDEL doesn't synchronize on short offset */ } /* Is video bus bandwidth (32MB/s) too low for this resolution? */ /* this is definitely wrong if bus clock != 32MHz */ @@ -1098,7 +1206,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, * between interlace and non-interlace without messing around * with these. */ - again: +again: /* Set base_offset 128 and video bus width */ par->hw.falcon.vid_control = mon_type | f030_bus_width; if (!longoffset) @@ -1112,37 +1220,34 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, /* External or internal clock */ par->hw.falcon.sync = pclock->sync_mask | 0x2; /* Pixellength and prescale */ - par->hw.falcon.vid_mode = (2/plen) << 2; + par->hw.falcon.vid_mode = (2 / plen) << 2; if (doubleline) par->hw.falcon.vid_mode |= VMO_DOUBLE; if (interlace) par->hw.falcon.vid_mode |= VMO_INTER; /********************* - Horizontal timing: unit = [master clock cycles] - unit of hxx-registers: [master clock cycles * prescale] - Hxx-registers are 9 bit wide - - 1 line = ((hht + 2) * 2 * prescale) clock cycles - - graphic output = hdb & 0x200 ? - ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff: - ( hht + 2 - hdb + hde) * prescale - hdboff + hdeoff - (this must be a multiple of plen*128/bpp, on VGA pixels - to the right may be cut off with a bigger right margin) - - start of graphics relative to start of 1st halfline = hdb & 0x200 ? - (hdb - hht - 2) * prescale + hdboff : - hdb * prescale + hdboff - - end of graphics relative to start of 1st halfline = - (hde + hht + 2) * prescale + hdeoff - *********************/ + * Horizontal timing: unit = [master clock cycles] + * unit of hxx-registers: [master clock cycles * prescale] + * Hxx-registers are 9 bit wide + * + * 1 line = ((hht + 2) * 2 * prescale) clock cycles + * + * graphic output = hdb & 0x200 ? + * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff: + * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff + * (this must be a multiple of plen*128/bpp, on VGA pixels + * to the right may be cut off with a bigger right margin) + * + * start of graphics relative to start of 1st halfline = hdb & 0x200 ? + * (hdb - hht - 2) * prescale + hdboff : + * hdb * prescale + hdboff + * + * end of graphics relative to start of 1st halfline = + * (hde + hht + 2) * prescale + hdeoff + *********************/ /* Calculate VIDEL registers */ - { - int hdb_off, hde_off, base_off; - int gstart, gend1, gend2, align; - +{ prescale = hxx_prescale(&par->hw.falcon); base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128; @@ -1154,8 +1259,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, align = 1; hde_off = 0; hdb_off = (base_off + 16 * plen) + prescale; - } - else { + } else { align = 128 / bpp; hde_off = ((128 / bpp + 2) * plen); if (par->hw.falcon.ste_mode) @@ -1164,23 +1268,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale; } - gstart = (prescale/2 + plen * left_margin) / prescale; + gstart = (prescale / 2 + plen * left_margin) / prescale; /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */ - gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale; + gend1 = gstart + ((xres + align - 1) / align) * align * plen / prescale; /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */ gend2 = gstart + xres * plen / prescale; par->HHT = plen * (left_margin + xres + right_margin) / (2 * prescale) - 2; /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/ - par->HDB = gstart - hdb_off/prescale; + par->HDB = gstart - hdb_off / prescale; par->HBE = gstart; - if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200; - par->HDE = gend1 - par->HHT - 2 - hde_off/prescale; + if (par->HDB < 0) + par->HDB += par->HHT + 2 + 0x200; + par->HDE = gend1 - par->HHT - 2 - hde_off / prescale; par->HBB = gend2 - par->HHT - 2; #if 0 /* One more Videl constraint: data fetch of two lines must not overlap */ - if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) { + if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) { /* if this happens increase margins, decrease hfreq. */ } #endif @@ -1189,11 +1294,11 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, par->HSS = par->HHT + 2 - plen * hsync_len / prescale; if (par->HSS < par->HBB) par->HSS = par->HBB; - } +} /* check hor. frequency */ - hfreq = pclock->f / ((par->HHT+2)*prescale*2); - if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) { + hfreq = pclock->f / ((par->HHT + 2) * prescale * 2); + if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) { /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */ /* Too high -> enlarge margin */ left_margin += 1; @@ -1213,12 +1318,14 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */ par->VDB = par->VBE; par->VDE = yres; - if (!interlace) par->VDE <<= 1; - if (doubleline) par->VDE <<= 1; /* VDE now half lines per (half-)frame */ + if (!interlace) + par->VDE <<= 1; + if (doubleline) + par->VDE <<= 1; /* VDE now half lines per (half-)frame */ par->VDE += par->VDB; par->VBB = par->VDE; par->VFT = par->VBB + (lower_margin * 2 - 1) - 1; - par->VSS = par->VFT+1 - (vsync_len * 2 - 1); + par->VSS = par->VFT + 1 - (vsync_len * 2 - 1); /* vbb,vss,vft must be even in interlace mode */ if (interlace) { par->VBB++; @@ -1229,55 +1336,53 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, /* V-frequency check, hope I didn't create any loop here. */ /* Interlace and doubleline are mutually exclusive. */ vfreq = (hfreq * 2) / (par->VFT + 1); - if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) { + if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) { /* Too high -> try again with doubleline */ doubleline = 1; goto again; - } - else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) { + } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) { /* Too low -> try again with interlace */ interlace = 1; goto again; - } - else if (vfreq < fb_info.monspecs.vfmin && doubleline) { + } else if (vfreq < fb_info.monspecs.vfmin && doubleline) { /* Doubleline too low -> clear doubleline and enlarge margins */ int lines; doubleline = 0; - for (lines=0; - (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax; + for (lines = 0; + (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) > + fb_info.monspecs.vfmax; lines++) ; upper_margin += lines; lower_margin += lines; goto again; - } - else if (vfreq > fb_info.monspecs.vfmax && doubleline) { + } else if (vfreq > fb_info.monspecs.vfmax && doubleline) { /* Doubleline too high -> enlarge margins */ int lines; - for (lines=0; - (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax; - lines+=2) + for (lines = 0; + (hfreq * 2) / (par->VFT + 1 + 4 * lines) > + fb_info.monspecs.vfmax; + lines += 2) ; upper_margin += lines; lower_margin += lines; goto again; - } - else if (vfreq > fb_info.monspecs.vfmax && interlace) { + } else if (vfreq > fb_info.monspecs.vfmax && interlace) { /* Interlace, too high -> enlarge margins */ int lines; - for (lines=0; - (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax; + for (lines = 0; + (hfreq * 2) / (par->VFT + 1 + 4 * lines) > + fb_info.monspecs.vfmax; lines++) ; upper_margin += lines; lower_margin += lines; goto again; - } - else if (vfreq < fb_info.monspecs.vfmin || - vfreq > fb_info.monspecs.vfmax) + } else if (vfreq < fb_info.monspecs.vfmin || + vfreq > fb_info.monspecs.vfmax) return -EINVAL; - set_screen_base: +set_screen_base: linelen = xres_virtual * bpp / 8; if (yres_virtual * linelen > screen_len && screen_len) return -EINVAL; @@ -1289,11 +1394,20 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, par->screen_base = screen_base + var->yoffset * linelen; par->hw.falcon.xoffset = 0; + // FIXME!!! sort of works, no crash + //par->next_line = linelen; + //par->next_plane = yres_virtual * linelen; + par->next_line = linelen; + par->next_plane = 2; + // crashes + //par->next_plane = linelen; + //par->next_line = yres_virtual * linelen; + return 0; } -static int falcon_encode_var( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int falcon_encode_var(struct fb_var_screeninfo *var, + struct atafb_par *par) { /* !!! only for VGA !!! */ int linelen; @@ -1306,10 +1420,10 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, var->pixclock = hw->sync & 0x1 ? fext.t : hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t; - var->height=-1; - var->width=-1; + var->height = -1; + var->width = -1; - var->sync=0; + var->sync = 0; if (hw->vid_control & VCO_HSYPOS) var->sync |= FB_SYNC_HOR_HIGH_ACT; if (hw->vid_control & VCO_VSYPOS) @@ -1320,7 +1434,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, var->vmode |= FB_VMODE_INTERLACED; if (hw->vid_mode & VMO_DOUBLE) var->vmode |= FB_VMODE_DOUBLE; - + /* visible y resolution: * Graphics display starts at line VDB and ends at line * VDE. If interlace mode off unit of VC-registers is @@ -1332,14 +1446,15 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, if (var->vmode & FB_VMODE_DOUBLE) var->yres >>= 1; - /* to get bpp, we must examine f_shift and st_shift. + /* + * to get bpp, we must examine f_shift and st_shift. * f_shift is valid if any of bits no. 10, 8 or 4 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e. * if bit 10 set then bit 8 and bit 4 don't care... * If all these bits are 0 get display depth from st_shift * (as for ST and STE) */ - if (hw->f_shift & 0x400) /* 2 colors */ + if (hw->f_shift & 0x400) /* 2 colors */ var->bits_per_pixel = 1; else if (hw->f_shift & 0x100) /* hicolor */ var->bits_per_pixel = 16; @@ -1349,7 +1464,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, var->bits_per_pixel = 4; else if (hw->st_shift == 0x100) var->bits_per_pixel = 2; - else /* if (hw->st_shift == 0x200) */ + else /* if (hw->st_shift == 0x200) */ var->bits_per_pixel = 1; var->xres = hw->line_width * 16 / var->bits_per_pixel; @@ -1358,42 +1473,42 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, var->xres_virtual += 16; if (var->bits_per_pixel == 16) { - var->red.offset=11; - var->red.length=5; - var->red.msb_right=0; - var->green.offset=5; - var->green.length=6; - var->green.msb_right=0; - var->blue.offset=0; - var->blue.length=5; - var->blue.msb_right=0; - } - else { - var->red.offset=0; + var->red.offset = 11; + var->red.length = 5; + var->red.msb_right = 0; + var->green.offset = 5; + var->green.length = 6; + var->green.msb_right = 0; + var->blue.offset = 0; + var->blue.length = 5; + var->blue.msb_right = 0; + } else { + var->red.offset = 0; var->red.length = hw->ste_mode ? 4 : 6; - var->red.msb_right=0; - var->grayscale=0; - var->blue=var->green=var->red; + if (var->red.length > var->bits_per_pixel) + var->red.length = var->bits_per_pixel; + var->red.msb_right = 0; + var->grayscale = 0; + var->blue = var->green = var->red; } - var->transp.offset=0; - var->transp.length=0; - var->transp.msb_right=0; + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; linelen = var->xres_virtual * var->bits_per_pixel / 8; if (screen_len) { if (par->yres_virtual) var->yres_virtual = par->yres_virtual; else - /* yres_virtual==0 means use maximum */ + /* yres_virtual == 0 means use maximum */ var->yres_virtual = screen_len / linelen; - } - else { + } else { if (hwscroll < 0) var->yres_virtual = 2 * var->yres; else - var->yres_virtual=var->yres+hwscroll * 16; + var->yres_virtual = var->yres + hwscroll * 16; } - var->xoffset=0; /* TODO change this */ + var->xoffset = 0; /* TODO change this */ /* hdX-offsets */ prescale = hxx_prescale(hw); @@ -1402,8 +1517,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, if (hw->f_shift & 0x100) { hde_off = 0; hdb_off = (base_off + 16 * plen) + prescale; - } - else { + } else { hde_off = ((128 / var->bits_per_pixel + 2) * plen); if (hw->ste_mode) hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen) @@ -1415,8 +1529,8 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, /* Right margin includes hsync */ var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) - - (hw->hdb & 0x200 ? 2+hw->hht : 0)); - if (hw->ste_mode || mon_type!=F_MON_VGA) + (hw->hdb & 0x200 ? 2 + hw->hht : 0)); + if (hw->ste_mode || mon_type != F_MON_VGA) var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off; else /* can't use this in ste_mode, because hbb is +1 off */ @@ -1424,15 +1538,14 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, var->hsync_len = prescale * (hw->hht + 2 - hw->hss); /* Lower margin includes vsync */ - var->upper_margin = hw->vdb / 2 ; /* round down to full lines */ - var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */ - var->vsync_len = (hw->vft+1 - hw->vss + 1) / 2; /* round up */ + var->upper_margin = hw->vdb / 2; /* round down to full lines */ + var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2; /* round up */ + var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2; /* round up */ if (var->vmode & FB_VMODE_INTERLACED) { var->upper_margin *= 2; var->lower_margin *= 2; var->vsync_len *= 2; - } - else if (var->vmode & FB_VMODE_DOUBLE) { + } else if (var->vmode & FB_VMODE_DOUBLE) { var->upper_margin = (var->upper_margin + 1) / 2; var->lower_margin = (var->lower_margin + 1) / 2; var->vsync_len = (var->vsync_len + 1) / 2; @@ -1447,20 +1560,19 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, var->lower_margin -= var->vsync_len; if (screen_base) - var->yoffset=(par->screen_base - screen_base)/linelen; + var->yoffset = (par->screen_base - screen_base) / linelen; else - var->yoffset=0; - var->nonstd=0; /* what is this for? */ - var->activate=0; + var->yoffset = 0; + var->nonstd = 0; /* what is this for? */ + var->activate = 0; return 0; } - -static int f_change_mode = 0; +static int f_change_mode; static struct falcon_hw f_new_mode; -static int f_pan_display = 0; +static int f_pan_display; -static void falcon_get_par( struct atafb_par *par ) +static void falcon_get_par(struct atafb_par *par) { unsigned long addr; struct falcon_hw *hw = &par->hw.falcon; @@ -1492,12 +1604,12 @@ static void falcon_get_par( struct atafb_par *par ) par->screen_base = phys_to_virt(addr); /* derived parameters */ - hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100; + hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100; hw->mono = (hw->f_shift & 0x400) || - ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200); + ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200); } -static void falcon_set_par( struct atafb_par *par ) +static void falcon_set_par(struct atafb_par *par) { f_change_mode = 0; @@ -1519,8 +1631,7 @@ static void falcon_set_par( struct atafb_par *par ) f_change_mode = 1; } - -static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) +static irqreturn_t falcon_vbl_switcher(int irq, void *dummy) { struct falcon_hw *hw = &f_new_mode; @@ -1529,11 +1640,10 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) if (hw->sync & 0x1) { /* Enable external pixelclock. This code only for ScreenWonder */ - *(volatile unsigned short*)0xffff9202 = 0xffbf; - } - else { + *(volatile unsigned short *)0xffff9202 = 0xffbf; + } else { /* Turn off external clocks. Read sets all output bits to 1. */ - *(volatile unsigned short*)0xffff9202; + *(volatile unsigned short *)0xffff9202; } shifter.syncmode = hw->sync; @@ -1550,15 +1660,14 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) videl.vde = hw->vde; videl.vss = hw->vss; - videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */ + videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */ if (hw->ste_mode) { - videl.st_shift = hw->st_shift; /* write enables STE palette */ - } - else { + videl.st_shift = hw->st_shift; /* write enables STE palette */ + } else { /* IMPORTANT: - * set st_shift 0, so we can tell the screen-depth if f_shift==0. + * set st_shift 0, so we can tell the screen-depth if f_shift == 0. * Writing 0 to f_shift enables 4 plane Falcon mode but - * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible + * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible * with Falcon palette. */ videl.st_shift = 0; @@ -1580,12 +1689,13 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) return IRQ_HANDLED; } - -static int falcon_pan_display( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int falcon_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) { + struct atafb_par *par = (struct atafb_par *)info->par; + int xoffset; - int bpp = fb_display[fb_info.currcon].var.bits_per_pixel; + int bpp = info->var.bits_per_pixel; if (bpp == 1) var->xoffset = up(var->xoffset, 32); @@ -1596,45 +1706,24 @@ static int falcon_pan_display( struct fb_var_screeninfo *var, var->xoffset = up(var->xoffset, 2); } par->hw.falcon.line_offset = bpp * - (fb_display[fb_info.currcon].var.xres_virtual - fb_display[fb_info.currcon].var.xres) / 16; + (info->var.xres_virtual - info->var.xres) / 16; if (par->hw.falcon.xoffset) par->hw.falcon.line_offset -= bpp; xoffset = var->xoffset - par->hw.falcon.xoffset; par->screen_base = screen_base + - (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + xoffset) * bpp / 8; + (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8; if (fbhw->set_screen_base) - fbhw->set_screen_base (par->screen_base); + fbhw->set_screen_base(par->screen_base); else - return -EINVAL; /* shouldn't happen */ + return -EINVAL; /* shouldn't happen */ f_pan_display = 1; return 0; } - -static int falcon_getcolreg( unsigned regno, unsigned *red, - unsigned *green, unsigned *blue, - unsigned *transp, struct fb_info *info ) -{ unsigned long col; - - if (regno > 255) - return 1; - /* This works in STE-mode (with 4bit/color) since f030_col-registers - * hold up to 6bit/color. - * Even with hicolor r/g/b=5/6/5 bit! - */ - col = f030_col[regno]; - *red = (col >> 16) & 0xff00; - *green = (col >> 8) & 0xff00; - *blue = (col << 8) & 0xff00; - *transp = 0; - return 0; -} - - -static int falcon_setcolreg( unsigned regno, unsigned red, - unsigned green, unsigned blue, - unsigned transp, struct fb_info *info ) +static int falcon_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) { if (regno > 255) return 1; @@ -1655,13 +1744,12 @@ static int falcon_setcolreg( unsigned regno, unsigned red, return 0; } - -static int falcon_blank( int blank_mode ) +static int falcon_blank(int blank_mode) { -/* ++guenther: we can switch off graphics by changing VDB and VDE, - * so VIDEL doesn't hog the bus while saving. - * (this may affect usleep()). - */ + /* ++guenther: we can switch off graphics by changing VDB and VDE, + * so VIDEL doesn't hog the bus while saving. + * (this may affect usleep()). + */ int vdb, vss, hbe, hss; if (mon_type == F_MON_SM) /* this doesn't work on SM124 */ @@ -1694,14 +1782,13 @@ static int falcon_blank( int blank_mode ) return 0; } - -static int falcon_detect( void ) +static int falcon_detect(void) { struct atafb_par par; unsigned char fhw; /* Determine connected monitor and set monitor parameters */ - fhw = *(unsigned char*)0xffff8006; + fhw = *(unsigned char *)0xffff8006; mon_type = fhw >> 6 & 0x3; /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */ f030_bus_width = fhw << 6 & 0x80; @@ -1715,7 +1802,7 @@ static int falcon_detect( void ) case F_MON_SC: case F_MON_TV: /* PAL...NTSC */ - fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */ + fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */ fb_info.monspecs.vfmax = 60; fb_info.monspecs.hfmin = 15620; fb_info.monspecs.hfmax = 15755; @@ -1740,13 +1827,12 @@ static int falcon_detect( void ) #ifdef ATAFB_STE -static int stste_encode_fix( struct fb_fix_screeninfo *fix, - struct atafb_par *par ) - +static int stste_encode_fix(struct fb_fix_screeninfo *fix, + struct atafb_par *par) { int mode; - strcpy(fix->id,"Atari Builtin"); + strcpy(fix->id, "Atari Builtin"); fix->smem_start = (unsigned long)real_screen_base; fix->smem_len = screen_len; fix->type = FB_TYPE_INTERLEAVED_PLANES; @@ -1771,43 +1857,40 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix, return 0; } - -static int stste_decode_var( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int stste_decode_var(struct fb_var_screeninfo *var, + struct atafb_par *par) { - int xres=var->xres; - int yres=var->yres; - int bpp=var->bits_per_pixel; + int xres = var->xres; + int yres = var->yres; + int bpp = var->bits_per_pixel; int linelen; int yres_virtual = var->yres_virtual; if (mono_moni) { if (bpp > 1 || xres > sttt_xres || yres > st_yres) return -EINVAL; - par->hw.st.mode=ST_HIGH; - xres=sttt_xres; - yres=st_yres; - bpp=1; + par->hw.st.mode = ST_HIGH; + xres = sttt_xres; + yres = st_yres; + bpp = 1; } else { if (bpp > 4 || xres > sttt_xres || yres > st_yres) return -EINVAL; if (bpp > 2) { - if (xres > sttt_xres/2 || yres > st_yres/2) + if (xres > sttt_xres / 2 || yres > st_yres / 2) return -EINVAL; - par->hw.st.mode=ST_LOW; - xres=sttt_xres/2; - yres=st_yres/2; - bpp=4; - } - else if (bpp > 1) { - if (xres > sttt_xres || yres > st_yres/2) + par->hw.st.mode = ST_LOW; + xres = sttt_xres / 2; + yres = st_yres / 2; + bpp = 4; + } else if (bpp > 1) { + if (xres > sttt_xres || yres > st_yres / 2) return -EINVAL; - par->hw.st.mode=ST_MID; - xres=sttt_xres; - yres=st_yres/2; - bpp=2; - } - else + par->hw.st.mode = ST_MID; + xres = sttt_xres; + yres = st_yres / 2; + bpp = 2; + } else return -EINVAL; } if (yres_virtual <= 0) @@ -1815,10 +1898,10 @@ static int stste_decode_var( struct fb_var_screeninfo *var, else if (yres_virtual < yres) yres_virtual = yres; if (var->sync & FB_SYNC_EXT) - par->hw.st.sync=(par->hw.st.sync & ~1) | 1; + par->hw.st.sync = (par->hw.st.sync & ~1) | 1; else - par->hw.st.sync=(par->hw.st.sync & ~1); - linelen=xres*bpp/8; + par->hw.st.sync = (par->hw.st.sync & ~1); + linelen = xres * bpp / 8; if (yres_virtual * linelen > screen_len && screen_len) return -EINVAL; if (yres * linelen > screen_len && screen_len) @@ -1826,93 +1909,91 @@ static int stste_decode_var( struct fb_var_screeninfo *var, if (var->yoffset + yres > yres_virtual && yres_virtual) return -EINVAL; par->yres_virtual = yres_virtual; - par->screen_base=screen_base+ var->yoffset*linelen; + par->screen_base = screen_base + var->yoffset * linelen; return 0; } -static int stste_encode_var( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int stste_encode_var(struct fb_var_screeninfo *var, + struct atafb_par *par) { int linelen; memset(var, 0, sizeof(struct fb_var_screeninfo)); - var->red.offset=0; + var->red.offset = 0; var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3; - var->red.msb_right=0; - var->grayscale=0; + var->red.msb_right = 0; + var->grayscale = 0; - var->pixclock=31041; - var->left_margin=120; /* these are incorrect */ - var->right_margin=100; - var->upper_margin=8; - var->lower_margin=16; - var->hsync_len=140; - var->vsync_len=30; + var->pixclock = 31041; + var->left_margin = 120; /* these are incorrect */ + var->right_margin = 100; + var->upper_margin = 8; + var->lower_margin = 16; + var->hsync_len = 140; + var->vsync_len = 30; - var->height=-1; - var->width=-1; + var->height = -1; + var->width = -1; if (!(par->hw.st.sync & 1)) - var->sync=0; + var->sync = 0; else - var->sync=FB_SYNC_EXT; + var->sync = FB_SYNC_EXT; switch (par->hw.st.mode & 3) { case ST_LOW: - var->xres=sttt_xres/2; - var->yres=st_yres/2; - var->bits_per_pixel=4; + var->xres = sttt_xres / 2; + var->yres = st_yres / 2; + var->bits_per_pixel = 4; break; case ST_MID: - var->xres=sttt_xres; - var->yres=st_yres/2; - var->bits_per_pixel=2; + var->xres = sttt_xres; + var->yres = st_yres / 2; + var->bits_per_pixel = 2; break; case ST_HIGH: - var->xres=sttt_xres; - var->yres=st_yres; - var->bits_per_pixel=1; + var->xres = sttt_xres; + var->yres = st_yres; + var->bits_per_pixel = 1; break; - } - var->blue=var->green=var->red; - var->transp.offset=0; - var->transp.length=0; - var->transp.msb_right=0; - var->xres_virtual=sttt_xres_virtual; - linelen=var->xres_virtual * var->bits_per_pixel / 8; - ovsc_addlen=linelen*(sttt_yres_virtual - st_yres); - - if (! use_hwscroll) - var->yres_virtual=var->yres; + } + var->blue = var->green = var->red; + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; + var->xres_virtual = sttt_xres_virtual; + linelen = var->xres_virtual * var->bits_per_pixel / 8; + ovsc_addlen = linelen * (sttt_yres_virtual - st_yres); + + if (!use_hwscroll) + var->yres_virtual = var->yres; else if (screen_len) { if (par->yres_virtual) var->yres_virtual = par->yres_virtual; else - /* yres_virtual==0 means use maximum */ + /* yres_virtual == 0 means use maximum */ var->yres_virtual = screen_len / linelen; - } - else { + } else { if (hwscroll < 0) var->yres_virtual = 2 * var->yres; else - var->yres_virtual=var->yres+hwscroll * 16; + var->yres_virtual = var->yres + hwscroll * 16; } - var->xoffset=0; + var->xoffset = 0; if (screen_base) - var->yoffset=(par->screen_base - screen_base)/linelen; + var->yoffset = (par->screen_base - screen_base) / linelen; else - var->yoffset=0; - var->nonstd=0; - var->activate=0; - var->vmode=FB_VMODE_NONINTERLACED; + var->yoffset = 0; + var->nonstd = 0; + var->activate = 0; + var->vmode = FB_VMODE_NONINTERLACED; return 0; } - -static void stste_get_par( struct atafb_par *par ) +static void stste_get_par(struct atafb_par *par) { unsigned long addr; - par->hw.st.mode=shifter_tt.st_shiftmode; - par->hw.st.sync=shifter.syncmode; + par->hw.st.mode = shifter_tt.st_shiftmode; + par->hw.st.sync = shifter.syncmode; addr = ((shifter.bas_hi & 0xff) << 16) | ((shifter.bas_md & 0xff) << 8); if (ATARIHW_PRESENT(EXTD_SHIFTER)) @@ -1920,55 +2001,18 @@ static void stste_get_par( struct atafb_par *par ) par->screen_base = phys_to_virt(addr); } -static void stste_set_par( struct atafb_par *par ) +static void stste_set_par(struct atafb_par *par) { - shifter_tt.st_shiftmode=par->hw.st.mode; - shifter.syncmode=par->hw.st.sync; + shifter_tt.st_shiftmode = par->hw.st.mode; + shifter.syncmode = par->hw.st.sync; /* only set screen_base if really necessary */ if (current_par.screen_base != par->screen_base) fbhw->set_screen_base(par->screen_base); } - -static int stste_getcolreg(unsigned regno, unsigned *red, - unsigned *green, unsigned *blue, - unsigned *transp, struct fb_info *info) -{ - unsigned col, t; - - if (regno > 15) - return 1; - col = shifter_tt.color_reg[regno]; - if (ATARIHW_PRESENT(EXTD_SHIFTER)) { - t = ((col >> 7) & 0xe) | ((col >> 11) & 1); - t |= t << 4; - *red = t | (t << 8); - t = ((col >> 3) & 0xe) | ((col >> 7) & 1); - t |= t << 4; - *green = t | (t << 8); - t = ((col << 1) & 0xe) | ((col >> 3) & 1); - t |= t << 4; - *blue = t | (t << 8); - } - else { - t = (col >> 7) & 0xe; - t |= t << 4; - *red = t | (t << 8); - t = (col >> 3) & 0xe; - t |= t << 4; - *green = t | (t << 8); - t = (col << 1) & 0xe; - t |= t << 4; - *blue = t | (t << 8); - } - *transp = 0; - return 0; -} - - -static int stste_setcolreg(unsigned regno, unsigned red, - unsigned green, unsigned blue, - unsigned transp, struct fb_info *info) +static int stste_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) { if (regno > 15) return 1; @@ -1988,10 +2032,9 @@ static int stste_setcolreg(unsigned regno, unsigned red, return 0; } - -static int stste_detect( void ) - -{ struct atafb_par par; +static int stste_detect(void) +{ + struct atafb_par par; /* Determine the connected monitor: The DMA sound must be * disabled before reading the MFP GPIP, because the Sound @@ -1999,7 +2042,7 @@ static int stste_detect( void ) */ if (ATARIHW_PRESENT(PCM_8BIT)) { tt_dmasnd.ctrl = DMASND_CTRL_OFF; - udelay(20); /* wait a while for things to settle down */ + udelay(20); /* wait a while for things to settle down */ } mono_moni = (mfp.par_dt_reg & 0x80) == 0; @@ -2014,12 +2057,12 @@ static int stste_detect( void ) static void stste_set_screen_base(void *s_base) { unsigned long addr; - addr= virt_to_phys(s_base); + addr = virt_to_phys(s_base); /* Setup Screen Memory */ - shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16); - shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8); + shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16); + shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8); if (ATARIHW_PRESENT(EXTD_SHIFTER)) - shifter.bas_lo=(unsigned char) (addr & 0x0000ff); + shifter.bas_lo = (unsigned char)(addr & 0x0000ff); } #endif /* ATAFB_STE */ @@ -2045,51 +2088,49 @@ static void stste_set_screen_base(void *s_base) /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */ static void st_ovsc_switch(void) { - unsigned long flags; - register unsigned char old, new; + unsigned long flags; + register unsigned char old, new; - if (!(atari_switches & ATARI_SWITCH_OVSC_MASK)) - return; - local_irq_save(flags); - - mfp.tim_ct_b = 0x10; - mfp.active_edge |= 8; - mfp.tim_ct_b = 0; - mfp.tim_dt_b = 0xf0; - mfp.tim_ct_b = 8; - while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */ - ; - new = mfp.tim_dt_b; - do { - udelay(LINE_DELAY); - old = new; + if (!(atari_switches & ATARI_SWITCH_OVSC_MASK)) + return; + local_irq_save(flags); + + mfp.tim_ct_b = 0x10; + mfp.active_edge |= 8; + mfp.tim_ct_b = 0; + mfp.tim_dt_b = 0xf0; + mfp.tim_ct_b = 8; + while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */ + ; new = mfp.tim_dt_b; - } while (old != new); - mfp.tim_ct_b = 0x10; - udelay(SYNC_DELAY); - - if (atari_switches & ATARI_SWITCH_OVSC_IKBD) - acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE; - if (atari_switches & ATARI_SWITCH_OVSC_MIDI) - acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID; - if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) { - sound_ym.rd_data_reg_sel = 14; - sound_ym.wd_data = sound_ym.rd_data_reg_sel | - ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) | - ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0); - } - local_irq_restore(flags); + do { + udelay(LINE_DELAY); + old = new; + new = mfp.tim_dt_b; + } while (old != new); + mfp.tim_ct_b = 0x10; + udelay(SYNC_DELAY); + + if (atari_switches & ATARI_SWITCH_OVSC_IKBD) + acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE; + if (atari_switches & ATARI_SWITCH_OVSC_MIDI) + acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID; + if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) { + sound_ym.rd_data_reg_sel = 14; + sound_ym.wd_data = sound_ym.rd_data_reg_sel | + ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) | + ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0); + } + local_irq_restore(flags); } /* ------------------- External Video ---------------------- */ #ifdef ATAFB_EXT -static int ext_encode_fix( struct fb_fix_screeninfo *fix, - struct atafb_par *par ) - +static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par) { - strcpy(fix->id,"Unknown Extern"); + strcpy(fix->id, "Unknown Extern"); fix->smem_start = (unsigned long)external_addr; fix->smem_len = PAGE_ALIGN(external_len); if (external_depth == 1) { @@ -2099,31 +2140,29 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix, fix->visual = (external_pmode == FB_TYPE_INTERLEAVED_PLANES || external_pmode == FB_TYPE_PACKED_PIXELS) ? - FB_VISUAL_MONO10 : - FB_VISUAL_MONO01; - } - else { + FB_VISUAL_MONO10 : FB_VISUAL_MONO01; + } else { /* Use STATIC if we don't know how to access color registers */ int visual = external_vgaiobase ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; switch (external_pmode) { - case -1: /* truecolor */ - fix->type=FB_TYPE_PACKED_PIXELS; - fix->visual=FB_VISUAL_TRUECOLOR; + case -1: /* truecolor */ + fix->type = FB_TYPE_PACKED_PIXELS; + fix->visual = FB_VISUAL_TRUECOLOR; break; - case FB_TYPE_PACKED_PIXELS: - fix->type=FB_TYPE_PACKED_PIXELS; - fix->visual=visual; + case FB_TYPE_PACKED_PIXELS: + fix->type = FB_TYPE_PACKED_PIXELS; + fix->visual = visual; break; - case FB_TYPE_PLANES: - fix->type=FB_TYPE_PLANES; - fix->visual=visual; + case FB_TYPE_PLANES: + fix->type = FB_TYPE_PLANES; + fix->visual = visual; break; - case FB_TYPE_INTERLEAVED_PLANES: - fix->type=FB_TYPE_INTERLEAVED_PLANES; - fix->type_aux=2; - fix->visual=visual; + case FB_TYPE_INTERLEAVED_PLANES: + fix->type = FB_TYPE_INTERLEAVED_PLANES; + fix->type_aux = 2; + fix->visual = visual; break; } } @@ -2134,137 +2173,112 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix, return 0; } - -static int ext_decode_var( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par) { struct fb_var_screeninfo *myvar = &atafb_predefined[0]; - + if (var->bits_per_pixel > myvar->bits_per_pixel || - var->xres > myvar->xres || - var->xres_virtual > myvar->xres_virtual || - var->yres > myvar->yres || - var->xoffset > 0 || - var->yoffset > 0) + var->xres > myvar->xres || + var->xres_virtual > myvar->xres_virtual || + var->yres > myvar->yres || + var->xoffset > 0 || + var->yoffset > 0) return -EINVAL; return 0; } - -static int ext_encode_var( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par) { memset(var, 0, sizeof(struct fb_var_screeninfo)); - var->red.offset=0; - var->red.length=(external_pmode == -1) ? external_depth/3 : + var->red.offset = 0; + var->red.length = (external_pmode == -1) ? external_depth / 3 : (external_vgaiobase ? external_bitspercol : 0); - var->red.msb_right=0; - var->grayscale=0; + var->red.msb_right = 0; + var->grayscale = 0; - var->pixclock=31041; - var->left_margin=120; /* these are surely incorrect */ - var->right_margin=100; - var->upper_margin=8; - var->lower_margin=16; - var->hsync_len=140; - var->vsync_len=30; + var->pixclock = 31041; + var->left_margin = 120; /* these are surely incorrect */ + var->right_margin = 100; + var->upper_margin = 8; + var->lower_margin = 16; + var->hsync_len = 140; + var->vsync_len = 30; - var->height=-1; - var->width=-1; + var->height = -1; + var->width = -1; - var->sync=0; + var->sync = 0; var->xres = external_xres; var->yres = external_yres; var->xres_virtual = external_xres_virtual; var->bits_per_pixel = external_depth; - - var->blue=var->green=var->red; - var->transp.offset=0; - var->transp.length=0; - var->transp.msb_right=0; - var->yres_virtual=var->yres; - var->xoffset=0; - var->yoffset=0; - var->nonstd=0; - var->activate=0; - var->vmode=FB_VMODE_NONINTERLACED; + + var->blue = var->green = var->red; + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; + var->yres_virtual = var->yres; + var->xoffset = 0; + var->yoffset = 0; + var->nonstd = 0; + var->activate = 0; + var->vmode = FB_VMODE_NONINTERLACED; return 0; } - -static void ext_get_par( struct atafb_par *par ) +static void ext_get_par(struct atafb_par *par) { par->screen_base = external_addr; } -static void ext_set_par( struct atafb_par *par ) +static void ext_set_par(struct atafb_par *par) { } #define OUTB(port,val) \ - *((unsigned volatile char *) ((port)+external_vgaiobase))=(val) + *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val) #define INB(port) \ (*((unsigned volatile char *) ((port)+external_vgaiobase))) -#define DACDelay \ +#define DACDelay \ do { \ - unsigned char tmp=INB(0x3da); \ - tmp=INB(0x3da); \ + unsigned char tmp = INB(0x3da); \ + tmp = INB(0x3da); \ } while (0) -static int ext_getcolreg( unsigned regno, unsigned *red, - unsigned *green, unsigned *blue, - unsigned *transp, struct fb_info *info ) +static int ext_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) { - if (! external_vgaiobase) + unsigned char colmask = (1 << external_bitspercol) - 1; + + if (!external_vgaiobase) return 1; - *red = ext_color[regno].red; - *green = ext_color[regno].green; - *blue = ext_color[regno].blue; - *transp=0; - return 0; -} - -static int ext_setcolreg( unsigned regno, unsigned red, - unsigned green, unsigned blue, - unsigned transp, struct fb_info *info ) + switch (external_card_type) { + case IS_VGA: + OUTB(0x3c8, regno); + DACDelay; + OUTB(0x3c9, red & colmask); + DACDelay; + OUTB(0x3c9, green & colmask); + DACDelay; + OUTB(0x3c9, blue & colmask); + DACDelay; + return 0; -{ unsigned char colmask = (1 << external_bitspercol) - 1; + case IS_MV300: + OUTB((MV300_reg[regno] << 2) + 1, red); + OUTB((MV300_reg[regno] << 2) + 1, green); + OUTB((MV300_reg[regno] << 2) + 1, blue); + return 0; - if (! external_vgaiobase) + default: return 1; - - ext_color[regno].red = red; - ext_color[regno].green = green; - ext_color[regno].blue = blue; - - switch (external_card_type) { - case IS_VGA: - OUTB(0x3c8, regno); - DACDelay; - OUTB(0x3c9, red & colmask); - DACDelay; - OUTB(0x3c9, green & colmask); - DACDelay; - OUTB(0x3c9, blue & colmask); - DACDelay; - return 0; - - case IS_MV300: - OUTB((MV300_reg[regno] << 2)+1, red); - OUTB((MV300_reg[regno] << 2)+1, green); - OUTB((MV300_reg[regno] << 2)+1, blue); - return 0; - - default: - return 1; - } + } } - - -static int ext_detect( void ) +static int ext_detect(void) { struct fb_var_screeninfo *myvar = &atafb_predefined[0]; struct atafb_par dummy_par; @@ -2284,213 +2298,182 @@ static int ext_detect( void ) static void set_screen_base(void *s_base) { unsigned long addr; - addr= virt_to_phys(s_base); + + addr = virt_to_phys(s_base); /* Setup Screen Memory */ - shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16); - shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8); - shifter.bas_lo=(unsigned char) (addr & 0x0000ff); + shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16); + shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8); + shifter.bas_lo = (unsigned char)(addr & 0x0000ff); } - -static int pan_display( struct fb_var_screeninfo *var, - struct atafb_par *par ) +static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { + struct atafb_par *par = (struct atafb_par *)info->par; + if (!fbhw->set_screen_base || - (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset)) + (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset)) return -EINVAL; var->xoffset = up(var->xoffset, 16); par->screen_base = screen_base + - (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + var->xoffset) - * fb_display[fb_info.currcon].var.bits_per_pixel / 8; - fbhw->set_screen_base (par->screen_base); + (var->yoffset * info->var.xres_virtual + var->xoffset) + * info->var.bits_per_pixel / 8; + fbhw->set_screen_base(par->screen_base); return 0; } - /* ------------ Interfaces to hardware functions ------------ */ - #ifdef ATAFB_TT static struct fb_hwswitch tt_switch = { - tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var, - tt_get_par, tt_set_par, tt_getcolreg, - set_screen_base, NULL, pan_display + .detect = tt_detect, + .encode_fix = tt_encode_fix, + .decode_var = tt_decode_var, + .encode_var = tt_encode_var, + .get_par = tt_get_par, + .set_par = tt_set_par, + .set_screen_base = set_screen_base, + .pan_display = pan_display, }; #endif #ifdef ATAFB_FALCON static struct fb_hwswitch falcon_switch = { - falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var, - falcon_get_par, falcon_set_par, falcon_getcolreg, - set_screen_base, falcon_blank, falcon_pan_display + .detect = falcon_detect, + .encode_fix = falcon_encode_fix, + .decode_var = falcon_decode_var, + .encode_var = falcon_encode_var, + .get_par = falcon_get_par, + .set_par = falcon_set_par, + .set_screen_base = set_screen_base, + .blank = falcon_blank, + .pan_display = falcon_pan_display, }; #endif #ifdef ATAFB_STE static struct fb_hwswitch st_switch = { - stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var, - stste_get_par, stste_set_par, stste_getcolreg, - stste_set_screen_base, NULL, pan_display + .detect = stste_detect, + .encode_fix = stste_encode_fix, + .decode_var = stste_decode_var, + .encode_var = stste_encode_var, + .get_par = stste_get_par, + .set_par = stste_set_par, + .set_screen_base = stste_set_screen_base, + .pan_display = pan_display }; #endif #ifdef ATAFB_EXT static struct fb_hwswitch ext_switch = { - ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var, - ext_get_par, ext_set_par, ext_getcolreg, NULL, NULL, NULL + .detect = ext_detect, + .encode_fix = ext_encode_fix, + .decode_var = ext_decode_var, + .encode_var = ext_encode_var, + .get_par = ext_get_par, + .set_par = ext_set_par, }; #endif - - -static void atafb_get_par( struct atafb_par *par ) +static void ata_get_par(struct atafb_par *par) { - if (current_par_valid) { - *par=current_par; - } + if (current_par_valid) + *par = current_par; else fbhw->get_par(par); } - -static void atafb_set_par( struct atafb_par *par ) +static void ata_set_par(struct atafb_par *par) { fbhw->set_par(par); - current_par=*par; - current_par_valid=1; + current_par = *par; + current_par_valid = 1; } - /* =========================================================== */ /* ============== Hardware Independent Functions ============= */ /* =========================================================== */ - /* used for hardware scrolling */ -static int -fb_update_var(int con, struct fb_info *info) -{ - int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual* - fb_display[con].var.bits_per_pixel>>3; - - current_par.screen_base=screen_base + off; - - if (fbhw->set_screen_base) - fbhw->set_screen_base(current_par.screen_base); - return 0; -} - -static int -do_fb_set_var(struct fb_var_screeninfo *var, int isactive) +static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) { - int err,activate; + int err, activate; struct atafb_par par; - if ((err=fbhw->decode_var(var, &par))) + + err = fbhw->decode_var(var, &par); + if (err) return err; - activate=var->activate; + activate = var->activate; if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) - atafb_set_par(&par); + ata_set_par(&par); fbhw->encode_var(var, &par); - var->activate=activate; + var->activate = activate; return 0; } -static int -atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) +static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) { struct atafb_par par; - if (con == -1) - atafb_get_par(&par); - else { - int err; - if ((err=fbhw->decode_var(&fb_display[con].var,&par))) - return err; - } + int err; + // Get fix directly (case con == -1 before)?? + err = fbhw->decode_var(&info->var, &par); + if (err) + return err; memset(fix, 0, sizeof(struct fb_fix_screeninfo)); return fbhw->encode_fix(fix, &par); } - -static int -atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) + +static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct atafb_par par; - if (con == -1) { - atafb_get_par(&par); - fbhw->encode_var(var, &par); - } - else - *var=fb_display[con].var; + + ata_get_par(&par); + fbhw->encode_var(var, &par); + return 0; } -static void -atafb_set_disp(int con, struct fb_info *info) +// No longer called by fbcon! +// Still called by set_var internally + +static void atafb_set_disp(struct fb_info *info) { - struct fb_fix_screeninfo fix; - struct fb_var_screeninfo var; - struct display *display; + atafb_get_var(&info->var, info); + atafb_get_fix(&info->fix, info); - if (con >= 0) - display = &fb_display[con]; - else - display = &disp; /* used during initialization */ - - atafb_get_fix(&fix, con, info); - atafb_get_var(&var, con, info); - if (con == -1) - con=0; - info->screen_base = (void *)fix.smem_start; - display->visual = fix.visual; - display->type = fix.type; - display->type_aux = fix.type_aux; - display->ypanstep = fix.ypanstep; - display->ywrapstep = fix.ywrapstep; - display->line_length = fix.line_length; - if (fix.visual != FB_VISUAL_PSEUDOCOLOR && - fix.visual != FB_VISUAL_DIRECTCOLOR) - display->can_soft_blank = 0; - else - display->can_soft_blank = 1; - display->inverse = - (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse); - switch (fix.type) { - case FB_TYPE_INTERLEAVED_PLANES: - switch (var.bits_per_pixel) { -#ifdef FBCON_HAS_IPLAN2P2 - case 2: - display->dispsw = &fbcon_iplan2p2; + info->screen_base = (void *)info->fix.smem_start; + + switch (info->fix.type) { + case FB_TYPE_INTERLEAVED_PLANES: + switch (info->var.bits_per_pixel) { + case 2: + // display->dispsw = &fbcon_iplan2p2; break; -#endif -#ifdef FBCON_HAS_IPLAN2P4 - case 4: - display->dispsw = &fbcon_iplan2p4; + case 4: + // display->dispsw = &fbcon_iplan2p4; break; -#endif -#ifdef FBCON_HAS_IPLAN2P8 - case 8: - display->dispsw = &fbcon_iplan2p8; + case 8: + // display->dispsw = &fbcon_iplan2p8; break; -#endif } break; - case FB_TYPE_PACKED_PIXELS: - switch (var.bits_per_pixel) { + case FB_TYPE_PACKED_PIXELS: + switch (info->var.bits_per_pixel) { #ifdef FBCON_HAS_MFB - case 1: - display->dispsw = &fbcon_mfb; + case 1: + // display->dispsw = &fbcon_mfb; break; #endif #ifdef FBCON_HAS_CFB8 - case 8: - display->dispsw = &fbcon_cfb8; + case 8: + // display->dispsw = &fbcon_cfb8; break; #endif #ifdef FBCON_HAS_CFB16 - case 16: - display->dispsw = &fbcon_cfb16; - display->dispsw_data = fbcon_cfb16_cmap; + case 16: + // display->dispsw = &fbcon_cfb16; + // display->dispsw_data = fbcon_cfb16_cmap; break; #endif } @@ -2498,74 +2481,203 @@ atafb_set_disp(int con, struct fb_info *info) } } +static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + red >>= 8; + green >>= 8; + blue >>= 8; + + return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info); +} + static int -atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - int err,oldxres,oldyres,oldbpp,oldxres_virtual, - oldyres_virtual,oldyoffset; - if ((err=do_fb_set_var(var, con==info->currcon))) - return err; - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { - oldxres=fb_display[con].var.xres; - oldyres=fb_display[con].var.yres; - oldxres_virtual=fb_display[con].var.xres_virtual; - oldyres_virtual=fb_display[con].var.yres_virtual; - oldbpp=fb_display[con].var.bits_per_pixel; - oldyoffset=fb_display[con].var.yoffset; - fb_display[con].var=*var; - if (oldxres != var->xres || oldyres != var->yres - || oldxres_virtual != var->xres_virtual - || oldyres_virtual != var->yres_virtual - || oldbpp != var->bits_per_pixel - || oldyoffset != var->yoffset) { - atafb_set_disp(con, info); - (*fb_info.changevar)(con); - fb_alloc_cmap(&fb_display[con].cmap, 0, 0); - do_install_cmap(con, info); - } + int xoffset = var->xoffset; + int yoffset = var->yoffset; + int err; + + if (var->vmode & FB_VMODE_YWRAP) { + if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset) + return -EINVAL; + } else { + if (xoffset + info->var.xres > info->var.xres_virtual || + yoffset + info->var.yres > info->var.yres_virtual) + return -EINVAL; } - var->activate=0; + + if (fbhw->pan_display) { + err = fbhw->pan_display(var, info); + if (err) + return err; + } else + return -EINVAL; + + info->var.xoffset = xoffset; + info->var.yoffset = yoffset; + + if (var->vmode & FB_VMODE_YWRAP) + info->var.vmode |= FB_VMODE_YWRAP; + else + info->var.vmode &= ~FB_VMODE_YWRAP; + return 0; } +/* + * generic drawing routines; imageblit needs updating for image depth > 1 + */ +#if BITS_PER_LONG == 32 +#define BYTES_PER_LONG 4 +#define SHIFT_PER_LONG 5 +#elif BITS_PER_LONG == 64 +#define BYTES_PER_LONG 8 +#define SHIFT_PER_LONG 6 +#else +#define Please update me +#endif -static int -atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) + +static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - if (con == info->currcon) /* current console ? */ - return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info); + struct atafb_par *par = (struct atafb_par *)info->par; + int x2, y2; + u32 width, height; + + if (!rect->width || !rect->height) + 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 < info->var.xres_virtual ? x2 : info->var.xres_virtual; + y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; + width = x2 - rect->dx; + height = y2 - rect->dy; + + if (info->var.bits_per_pixel == 1) + atafb_mfb_fillrect(info, par->next_line, rect->color, + rect->dy, rect->dx, height, width); + else if (info->var.bits_per_pixel == 2) + atafb_iplan2p2_fillrect(info, par->next_line, rect->color, + rect->dy, rect->dx, height, width); + else if (info->var.bits_per_pixel == 4) + atafb_iplan2p4_fillrect(info, par->next_line, rect->color, + rect->dy, rect->dx, height, width); else - if (fb_display[con].cmap.len) /* non default colormap ? */ - fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); - else - fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), - cmap, kspc ? 0 : 2); - return 0; + atafb_iplan2p8_fillrect(info, par->next_line, rect->color, + rect->dy, rect->dx, height, width); + + return; } -static int -atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) +static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { - int xoffset = var->xoffset; - int yoffset = var->yoffset; - int err; + struct atafb_par *par = (struct atafb_par *)info->par; + int x2, y2; + u32 dx, dy, sx, sy, width, height; + int rev_copy = 0; + + /* clip the destination */ + 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 < info->var.xres_virtual ? x2 : info->var.xres_virtual; + y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; + width = x2 - dx; + height = y2 - dy; + + /* update sx,sy */ + sx = area->sx + (dx - area->dx); + sy = area->sy + (dy - area->dy); + + /* the source must be completely inside the virtual screen */ + if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual || + (sy + height) > info->var.yres_virtual) + return; - if ( xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual - || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual) - return -EINVAL; + if (dy > sy || (dy == sy && dx > sx)) { + dy += height; + sy += height; + rev_copy = 1; + } + + if (info->var.bits_per_pixel == 1) + atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); + else if (info->var.bits_per_pixel == 2) + atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); + else if (info->var.bits_per_pixel == 4) + atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); + else + atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); - if (con == info->currcon) { - if (fbhw->pan_display) { - if ((err = fbhw->pan_display(var, ¤t_par))) - return err; + return; +} + +static void atafb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct atafb_par *par = (struct atafb_par *)info->par; + int x2, y2; + unsigned long *dst; + int dst_idx; + const char *src; + u32 dx, dy, width, height, pitch; + + /* + * We could use hardware clipping but on many cards you get around + * hardware clipping by writing to framebuffer directly like we are + * doing here. + */ + x2 = image->dx + image->width; + y2 = image->dy + image->height; + dx = image->dx; + dy = image->dy; + x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; + y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; + width = x2 - dx; + height = y2 - dy; + + if (image->depth == 1) { + // used for font data + dst = (unsigned long *) + ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1)); + dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8; + dst_idx += dy * par->next_line * 8 + dx; + src = image->data; + pitch = (image->width + 7) / 8; + while (height--) { + + if (info->var.bits_per_pixel == 1) + atafb_mfb_linefill(info, par->next_line, + dy, dx, width, src, + image->bg_color, image->fg_color); + else if (info->var.bits_per_pixel == 2) + atafb_iplan2p2_linefill(info, par->next_line, + dy, dx, width, src, + image->bg_color, image->fg_color); + else if (info->var.bits_per_pixel == 4) + atafb_iplan2p4_linefill(info, par->next_line, + dy, dx, width, src, + image->bg_color, image->fg_color); + else + atafb_iplan2p8_linefill(info, par->next_line, + dy, dx, width, src, + image->bg_color, image->fg_color); + dy++; + src += pitch; } - else - return -EINVAL; + } else { + // only used for logo; broken + c2p(info->screen_base, image->data, dx, dy, width, height, + par->next_line, par->next_plane, image->width, + info->var.bits_per_pixel); } - fb_display[con].var.xoffset = var->xoffset; - fb_display[con].var.yoffset = var->yoffset; - return 0; } static int @@ -2584,7 +2696,7 @@ atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) if (copy_from_user((void *)¤t_par, (void *)arg, sizeof(struct atafb_par))) return -EFAULT; - atafb_set_par(¤t_par); + ata_set_par(¤t_par); return 0; #endif } @@ -2598,42 +2710,82 @@ atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) * 3 = suspend hsync * 4 = off */ -static int -atafb_blank(int blank, struct fb_info *info) +static int atafb_blank(int blank, struct fb_info *info) { unsigned short black[16]; struct fb_cmap cmap; if (fbhw->blank && !fbhw->blank(blank)) return 1; if (blank) { - memset(black, 0, 16*sizeof(unsigned short)); - cmap.red=black; - cmap.green=black; - cmap.blue=black; - cmap.transp=NULL; - cmap.start=0; - cmap.len=16; - fb_set_cmap(&cmap, 1, info); + memset(black, 0, 16 * sizeof(unsigned short)); + cmap.red = black; + cmap.green = black; + cmap.blue = black; + cmap.transp = NULL; + cmap.start = 0; + cmap.len = 16; + fb_set_cmap(&cmap, info); } +#if 0 else - do_install_cmap(info->currcon, info); + do_install_cmap(info); +#endif + return 0; +} + + /* + * New fbcon interface ... + */ + + /* check var by decoding var into hw par, rounding if necessary, + * then encoding hw par back into new, validated var */ +static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + int err; + struct atafb_par par; + + /* Validate wanted screen parameters */ + // if ((err = ata_decode_var(var, &par))) + err = fbhw->decode_var(var, &par); + if (err) + return err; + + /* Encode (possibly rounded) screen parameters */ + fbhw->encode_var(var, &par); + return 0; +} + + /* actually set hw par by decoding var, then setting hardware from + * hw par just decoded */ +static int atafb_set_par(struct fb_info *info) +{ + struct atafb_par *par = (struct atafb_par *)info->par; + + /* Decode wanted screen parameters */ + fbhw->decode_var(&info->var, par); + fbhw->encode_fix(&info->fix, par); + + /* Set new videomode */ + ata_set_par(par); + return 0; } + static struct fb_ops atafb_ops = { .owner = THIS_MODULE, - .fb_get_fix = atafb_get_fix, - .fb_get_var = atafb_get_var, - .fb_set_var = atafb_set_var, - .fb_get_cmap = atafb_get_cmap, - .fb_set_cmap = gen_set_cmap, - .fb_pan_display =atafb_pan_display, + .fb_check_var = atafb_check_var, + .fb_set_par = atafb_set_par, + .fb_setcolreg = atafb_setcolreg, .fb_blank = atafb_blank, + .fb_pan_display = atafb_pan_display, + .fb_fillrect = atafb_fillrect, + .fb_copyarea = atafb_copyarea, + .fb_imageblit = atafb_imageblit, .fb_ioctl = atafb_ioctl, }; -static void -check_default_par( int detected_mode ) +static void check_default_par(int detected_mode) { char default_name[10]; int i; @@ -2642,199 +2794,41 @@ check_default_par( int detected_mode ) /* First try the user supplied mode */ if (default_par) { - var=atafb_predefined[default_par-1]; + var = atafb_predefined[default_par - 1]; var.activate = FB_ACTIVATE_TEST; - if (do_fb_set_var(&var,1)) - default_par=0; /* failed */ + if (do_fb_set_var(&var, 1)) + default_par = 0; /* failed */ } /* Next is the autodetected one */ - if (! default_par) { - var=atafb_predefined[detected_mode-1]; /* autodetect */ + if (!default_par) { + var = atafb_predefined[detected_mode - 1]; /* autodetect */ var.activate = FB_ACTIVATE_TEST; - if (!do_fb_set_var(&var,1)) - default_par=detected_mode; + if (!do_fb_set_var(&var, 1)) + default_par = detected_mode; } /* If that also failed, try some default modes... */ - if (! default_par) { + if (!default_par) { /* try default1, default2... */ - for (i=1 ; i < 10 ; i++) { - sprintf(default_name,"default%d",i); - default_par=get_video_mode(default_name); - if (! default_par) + for (i = 1; i < 10; i++) { + sprintf(default_name,"default%d", i); + default_par = get_video_mode(default_name); + if (!default_par) panic("can't set default video mode"); - var=atafb_predefined[default_par-1]; + var = atafb_predefined[default_par - 1]; var.activate = FB_ACTIVATE_TEST; - if (! do_fb_set_var(&var,1)) + if (!do_fb_set_var(&var,1)) break; /* ok */ } } - min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8; + min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8; if (default_mem_req < min_mem) - default_mem_req=min_mem; -} - -static int -atafb_switch(int con, struct fb_info *info) -{ - /* Do we have to save the colormap ? */ - if (fb_display[info->currcon].cmap.len) - fb_get_cmap(&fb_display[info->currcon].cmap, 1, fbhw->getcolreg, - info); - do_fb_set_var(&fb_display[con].var,1); - info->currcon=con; - /* Install new colormap */ - do_install_cmap(con, info); - return 0; -} - -int __init atafb_init(void) -{ - int pad; - int detected_mode; - unsigned long mem_req; - - if (!MACH_IS_ATARI) - return -ENXIO; - - do { -#ifdef ATAFB_EXT - if (external_addr) { - fbhw = &ext_switch; - atafb_ops.fb_setcolreg = &ext_setcolreg; - break; - } -#endif -#ifdef ATAFB_TT - if (ATARIHW_PRESENT(TT_SHIFTER)) { - fbhw = &tt_switch; - atafb_ops.fb_setcolreg = &tt_setcolreg; - break; - } -#endif -#ifdef ATAFB_FALCON - if (ATARIHW_PRESENT(VIDEL_SHIFTER)) { - fbhw = &falcon_switch; - atafb_ops.fb_setcolreg = &falcon_setcolreg; - request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO, - "framebuffer/modeswitch", falcon_vbl_switcher); - break; - } -#endif -#ifdef ATAFB_STE - if (ATARIHW_PRESENT(STND_SHIFTER) || - ATARIHW_PRESENT(EXTD_SHIFTER)) { - fbhw = &st_switch; - atafb_ops.fb_setcolreg = &stste_setcolreg; - break; - } - fbhw = &st_switch; - atafb_ops.fb_setcolreg = &stste_setcolreg; - printk("Cannot determine video hardware; defaulting to ST(e)\n"); -#else /* ATAFB_STE */ - /* no default driver included */ - /* Nobody will ever see this message :-) */ - panic("Cannot initialize video hardware"); -#endif - } while (0); - - /* Multisync monitor capabilities */ - /* Atari-TOS defaults if no boot option present */ - if (fb_info.monspecs.hfmin == 0) { - fb_info.monspecs.hfmin = 31000; - fb_info.monspecs.hfmax = 32000; - fb_info.monspecs.vfmin = 58; - fb_info.monspecs.vfmax = 62; - } - - detected_mode = fbhw->detect(); - check_default_par(detected_mode); -#ifdef ATAFB_EXT - if (!external_addr) { -#endif /* ATAFB_EXT */ - mem_req = default_mem_req + ovsc_offset + ovsc_addlen; - mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE; - screen_base = atari_stram_alloc(mem_req, "atafb"); - if (!screen_base) - panic("Cannot allocate screen memory"); - memset(screen_base, 0, mem_req); - pad = -(unsigned long)screen_base & (PAGE_SIZE-1); - screen_base+=pad; - real_screen_base=screen_base+ovsc_offset; - screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK; - st_ovsc_switch(); - if (CPU_IS_040_OR_060) { - /* On a '040+, the cache mode of video RAM must be set to - * write-through also for internal video hardware! */ - cache_push(virt_to_phys(screen_base), screen_len); - kernel_set_cachemode(screen_base, screen_len, - IOMAP_WRITETHROUGH); - } -#ifdef ATAFB_EXT - } - else { - /* Map the video memory (physical address given) to somewhere - * in the kernel address space. - */ - external_addr = - ioremap_writethrough((unsigned long)external_addr, - external_len); - if (external_vgaiobase) - external_vgaiobase = - (unsigned long)ioremap(external_vgaiobase, 0x10000); - screen_base = - real_screen_base = external_addr; - screen_len = external_len & PAGE_MASK; - memset (screen_base, 0, external_len); - } -#endif /* ATAFB_EXT */ - - strcpy(fb_info.modename, "Atari Builtin "); - fb_info.changevar = NULL; - fb_info.fbops = &atafb_ops; - fb_info.disp = &disp; - fb_info.currcon = -1; - fb_info.switch_con = &atafb_switch; - fb_info.updatevar = &fb_update_var; - fb_info.flags = FBINFO_FLAG_DEFAULT; - do_fb_set_var(&atafb_predefined[default_par-1], 1); - strcat(fb_info.modename, fb_var_names[default_par-1][0]); - - atafb_get_var(&disp.var, -1, &fb_info); - atafb_set_disp(-1, &fb_info); - do_install_cmap(0, &fb_info); - - if (register_framebuffer(&fb_info) < 0) { -#ifdef ATAFB_EXT - if (external_addr) { - iounmap(external_addr); - external_addr = NULL; - } - if (external_vgaiobase) { - iounmap((void*)external_vgaiobase); - external_vgaiobase = 0; - } -#endif - return -EINVAL; - } - - printk("Determined %dx%d, depth %d\n", - disp.var.xres, disp.var.yres, disp.var.bits_per_pixel); - if ((disp.var.xres != disp.var.xres_virtual) || - (disp.var.yres != disp.var.yres_virtual)) - printk(" virtual %dx%d\n", - disp.var.xres_virtual, disp.var.yres_virtual); - printk("fb%d: %s frame buffer device, using %dK of video memory\n", - fb_info.node, fb_info.modename, screen_len>>10); - - /* TODO: This driver cannot be unloaded yet */ - return 0; + default_mem_req = min_mem; } - #ifdef ATAFB_EXT static void __init atafb_setup_ext(char *spec) { - int xres, xres_virtual, yres, depth, planes; + int xres, xres_virtual, yres, depth, planes; unsigned long addr, len; char *p; @@ -2848,27 +2842,31 @@ static void __init atafb_setup_ext(char *spec) * * Even xres_virtual is available, we neither support panning nor hw-scrolling! */ - if (!(p = strsep(&spec, ";")) || !*p) - return; + p = strsep(&spec, ";"); + if (!p || !*p) + return; xres_virtual = xres = simple_strtoul(p, NULL, 10); if (xres <= 0) - return; + return; - if (!(p = strsep(&spec, ";")) || !*p) - return; + p = strsep(&spec, ";"); + if (!p || !*p) + return; yres = simple_strtoul(p, NULL, 10); if (yres <= 0) - return; + return; - if (!(p = strsep(&spec, ";")) || !*p) - return; + p = strsep(&spec, ";"); + if (!p || !*p) + return; depth = simple_strtoul(p, NULL, 10); if (depth != 1 && depth != 2 && depth != 4 && depth != 8 && - depth != 16 && depth != 24) - return; + depth != 16 && depth != 24) + return; - if (!(p = strsep(&spec, ";")) || !*p) - return; + p = strsep(&spec, ";"); + if (!p || !*p) + return; if (*p == 'i') planes = FB_TYPE_INTERLEAVED_PLANES; else if (*p == 'p') @@ -2876,25 +2874,27 @@ static void __init atafb_setup_ext(char *spec) else if (*p == 'n') planes = FB_TYPE_PLANES; else if (*p == 't') - planes = -1; /* true color */ + planes = -1; /* true color */ else return; - - if (!(p = strsep(&spec, ";")) || !*p) + p = strsep(&spec, ";"); + if (!p || !*p) return; addr = simple_strtoul(p, NULL, 0); - if (!(p = strsep(&spec, ";")) || !*p) - len = xres*yres*depth/8; + p = strsep(&spec, ";"); + if (!p || !*p) + len = xres * yres * depth / 8; else len = simple_strtoul(p, NULL, 0); - if ((p = strsep(&spec, ";")) && *p) { - external_vgaiobase=simple_strtoul(p, NULL, 0); - } + p = strsep(&spec, ";"); + if (p && *p) + external_vgaiobase = simple_strtoul(p, NULL, 0); - if ((p = strsep(&spec, ";")) && *p) { + p = strsep(&spec, ";"); + if (p && *p) { external_bitspercol = simple_strtoul(p, NULL, 0); if (external_bitspercol > 8) external_bitspercol = 8; @@ -2902,59 +2902,61 @@ static void __init atafb_setup_ext(char *spec) external_bitspercol = 1; } - if ((p = strsep(&spec, ";")) && *p) { + p = strsep(&spec, ";"); + if (p && *p) { if (!strcmp(p, "vga")) external_card_type = IS_VGA; if (!strcmp(p, "mv300")) external_card_type = IS_MV300; } - if ((p = strsep(&spec, ";")) && *p) { + p = strsep(&spec, ";"); + if (p && *p) { xres_virtual = simple_strtoul(p, NULL, 10); if (xres_virtual < xres) xres_virtual = xres; - if (xres_virtual*yres*depth/8 > len) - len=xres_virtual*yres*depth/8; + if (xres_virtual * yres * depth / 8 > len) + len = xres_virtual * yres * depth / 8; } - external_xres = xres; - external_xres_virtual = xres_virtual; - external_yres = yres; + external_xres = xres; + external_xres_virtual = xres_virtual; + external_yres = yres; external_depth = depth; external_pmode = planes; - external_addr = (void *)addr; - external_len = len; - - if (external_card_type == IS_MV300) - switch (external_depth) { - case 1: - MV300_reg = MV300_reg_1bit; - break; - case 4: - MV300_reg = MV300_reg_4bit; - break; - case 8: - MV300_reg = MV300_reg_8bit; - break; - } + external_addr = (void *)addr; + external_len = len; + + if (external_card_type == IS_MV300) { + switch (external_depth) { + case 1: + MV300_reg = MV300_reg_1bit; + break; + case 4: + MV300_reg = MV300_reg_4bit; + break; + case 8: + MV300_reg = MV300_reg_8bit; + break; + } + } } #endif /* ATAFB_EXT */ - static void __init atafb_setup_int(char *spec) { /* Format to config extended internal video hardware like OverScan: - "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>" - Explanation: - <xres>: x-resolution - <yres>: y-resolution - The following are only needed if you have an overscan which - needs a black border: - <xres_max>: max. length of a line in pixels your OverScan hardware would allow - <yres_max>: max. number of lines your OverScan hardware would allow - <offset>: Offset from physical beginning to visible beginning - of screen in bytes - */ + * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>" + * Explanation: + * <xres>: x-resolution + * <yres>: y-resolution + * The following are only needed if you have an overscan which + * needs a black border: + * <xres_max>: max. length of a line in pixels your OverScan hardware would allow + * <yres_max>: max. number of lines your OverScan hardware would allow + * <offset>: Offset from physical beginning to visible beginning + * of screen in bytes + */ int xres; char *p; @@ -2963,23 +2965,19 @@ static void __init atafb_setup_int(char *spec) xres = simple_strtoul(p, NULL, 10); if (!(p = strsep(&spec, ";")) || !*p) return; - sttt_xres=xres; - tt_yres=st_yres=simple_strtoul(p, NULL, 10); - if ((p=strsep(&spec, ";")) && *p) { - sttt_xres_virtual=simple_strtoul(p, NULL, 10); - } - if ((p=strsep(&spec, ";")) && *p) { - sttt_yres_virtual=simple_strtoul(p, NULL, 0); - } - if ((p=strsep(&spec, ";")) && *p) { - ovsc_offset=simple_strtoul(p, NULL, 0); - } + sttt_xres = xres; + tt_yres = st_yres = simple_strtoul(p, NULL, 10); + if ((p = strsep(&spec, ";")) && *p) + sttt_xres_virtual = simple_strtoul(p, NULL, 10); + if ((p = strsep(&spec, ";")) && *p) + sttt_yres_virtual = simple_strtoul(p, NULL, 0); + if ((p = strsep(&spec, ";")) && *p) + ovsc_offset = simple_strtoul(p, NULL, 0); if (ovsc_offset || (sttt_yres_virtual != st_yres)) - use_hwscroll=0; + use_hwscroll = 0; } - #ifdef ATAFB_FALCON static void __init atafb_setup_mcap(char *spec) { @@ -3018,7 +3016,6 @@ static void __init atafb_setup_mcap(char *spec) } #endif /* ATAFB_FALCON */ - static void __init atafb_setup_user(char *spec) { /* Format of user defined video mode is: <xres>;<yres>;<depth> @@ -3026,81 +3023,257 @@ static void __init atafb_setup_user(char *spec) char *p; int xres, yres, depth, temp; - if (!(p = strsep(&spec, ";")) || !*p) + p = strsep(&spec, ";"); + if (!p || !*p) return; xres = simple_strtoul(p, NULL, 10); - if (!(p = strsep(&spec, ";")) || !*p) + p = strsep(&spec, ";"); + if (!p || !*p) return; yres = simple_strtoul(p, NULL, 10); - if (!(p = strsep(&spec, "")) || !*p) + p = strsep(&spec, ""); + if (!p || !*p) return; depth = simple_strtoul(p, NULL, 10); - if ((temp=get_video_mode("user0"))) { - default_par=temp; - atafb_predefined[default_par-1].xres = xres; - atafb_predefined[default_par-1].yres = yres; - atafb_predefined[default_par-1].bits_per_pixel = depth; + temp = get_video_mode("user0"); + if (temp) { + default_par = temp; + atafb_predefined[default_par - 1].xres = xres; + atafb_predefined[default_par - 1].yres = yres; + atafb_predefined[default_par - 1].bits_per_pixel = depth; } } -int __init atafb_setup( char *options ) +int __init atafb_setup(char *options) { - char *this_opt; - int temp; - - fb_info.fontname[0] = '\0'; + char *this_opt; + int temp; - if (!options || !*options) + if (!options || !*options) return 0; - - while ((this_opt = strsep(&options, ",")) != NULL) { - if (!*this_opt) continue; - if ((temp=get_video_mode(this_opt))) - default_par=temp; - else if (! strcmp(this_opt, "inverse")) - inverse=1; - else if (!strncmp(this_opt, "font:", 5)) - strcpy(fb_info.fontname, this_opt+5); - else if (! strncmp(this_opt, "hwscroll_",9)) { - hwscroll=simple_strtoul(this_opt+9, NULL, 10); - if (hwscroll < 0) - hwscroll = 0; - if (hwscroll > 200) - hwscroll = 200; - } + + while ((this_opt = strsep(&options, ",")) != NULL) { + if (!*this_opt) + continue; + if ((temp = get_video_mode(this_opt))) { + default_par = temp; + mode_option = this_opt; + } else if (!strcmp(this_opt, "inverse")) + inverse = 1; + else if (!strncmp(this_opt, "hwscroll_", 9)) { + hwscroll = simple_strtoul(this_opt + 9, NULL, 10); + if (hwscroll < 0) + hwscroll = 0; + if (hwscroll > 200) + hwscroll = 200; + } #ifdef ATAFB_EXT - else if (!strcmp(this_opt,"mv300")) { - external_bitspercol = 8; - external_card_type = IS_MV300; + else if (!strcmp(this_opt, "mv300")) { + external_bitspercol = 8; + external_card_type = IS_MV300; + } else if (!strncmp(this_opt, "external:", 9)) + atafb_setup_ext(this_opt + 9); +#endif + else if (!strncmp(this_opt, "internal:", 9)) + atafb_setup_int(this_opt + 9); +#ifdef ATAFB_FALCON + else if (!strncmp(this_opt, "eclock:", 7)) { + fext.f = simple_strtoul(this_opt + 7, NULL, 10); + /* external pixelclock in kHz --> ps */ + fext.t = 1000000000 / fext.f; + fext.f *= 1000; + } else if (!strncmp(this_opt, "monitorcap:", 11)) + atafb_setup_mcap(this_opt + 11); +#endif + else if (!strcmp(this_opt, "keep")) + DontCalcRes = 1; + else if (!strncmp(this_opt, "R", 1)) + atafb_setup_user(this_opt + 1); } - else if (!strncmp(this_opt,"external:",9)) - atafb_setup_ext(this_opt+9); + return 0; +} + +int __init atafb_init(void) +{ + int pad; + int detected_mode; + unsigned int defmode = 0; + unsigned long mem_req; + +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("atafb", &option)) + return -ENODEV; + atafb_setup(option); +#endif + printk("atafb_init: start\n"); + + if (!MACH_IS_ATARI) + return -ENXIO; + + do { +#ifdef ATAFB_EXT + if (external_addr) { + printk("atafb_init: initializing external hw\n"); + fbhw = &ext_switch; + atafb_ops.fb_setcolreg = &ext_setcolreg; + defmode = DEFMODE_EXT; + break; + } +#endif +#ifdef ATAFB_TT + if (ATARIHW_PRESENT(TT_SHIFTER)) { + printk("atafb_init: initializing TT hw\n"); + fbhw = &tt_switch; + atafb_ops.fb_setcolreg = &tt_setcolreg; + defmode = DEFMODE_TT; + break; + } #endif - else if (!strncmp(this_opt,"internal:",9)) - atafb_setup_int(this_opt+9); #ifdef ATAFB_FALCON - else if (!strncmp(this_opt, "eclock:", 7)) { - fext.f = simple_strtoul(this_opt+7, NULL, 10); - /* external pixelclock in kHz --> ps */ - fext.t = 1000000000/fext.f; - fext.f *= 1000; + if (ATARIHW_PRESENT(VIDEL_SHIFTER)) { + printk("atafb_init: initializing Falcon hw\n"); + fbhw = &falcon_switch; + atafb_ops.fb_setcolreg = &falcon_setcolreg; + request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO, + "framebuffer/modeswitch", falcon_vbl_switcher); + defmode = DEFMODE_F30; + break; + } +#endif +#ifdef ATAFB_STE + if (ATARIHW_PRESENT(STND_SHIFTER) || + ATARIHW_PRESENT(EXTD_SHIFTER)) { + printk("atafb_init: initializing ST/E hw\n"); + fbhw = &st_switch; + atafb_ops.fb_setcolreg = &stste_setcolreg; + defmode = DEFMODE_STE; + break; + } + fbhw = &st_switch; + atafb_ops.fb_setcolreg = &stste_setcolreg; + printk("Cannot determine video hardware; defaulting to ST(e)\n"); +#else /* ATAFB_STE */ + /* no default driver included */ + /* Nobody will ever see this message :-) */ + panic("Cannot initialize video hardware"); +#endif + } while (0); + + /* Multisync monitor capabilities */ + /* Atari-TOS defaults if no boot option present */ + if (fb_info.monspecs.hfmin == 0) { + fb_info.monspecs.hfmin = 31000; + fb_info.monspecs.hfmax = 32000; + fb_info.monspecs.vfmin = 58; + fb_info.monspecs.vfmax = 62; } - else if (!strncmp(this_opt, "monitorcap:", 11)) - atafb_setup_mcap(this_opt+11); + + detected_mode = fbhw->detect(); + check_default_par(detected_mode); +#ifdef ATAFB_EXT + if (!external_addr) { +#endif /* ATAFB_EXT */ + mem_req = default_mem_req + ovsc_offset + ovsc_addlen; + mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE; + screen_base = atari_stram_alloc(mem_req, "atafb"); + if (!screen_base) + panic("Cannot allocate screen memory"); + memset(screen_base, 0, mem_req); + pad = -(unsigned long)screen_base & (PAGE_SIZE - 1); + screen_base += pad; + real_screen_base = screen_base + ovsc_offset; + screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK; + st_ovsc_switch(); + if (CPU_IS_040_OR_060) { + /* On a '040+, the cache mode of video RAM must be set to + * write-through also for internal video hardware! */ + cache_push(virt_to_phys(screen_base), screen_len); + kernel_set_cachemode(screen_base, screen_len, + IOMAP_WRITETHROUGH); + } + printk("atafb: screen_base %p real_screen_base %p screen_len %d\n", + screen_base, real_screen_base, screen_len); +#ifdef ATAFB_EXT + } else { + /* Map the video memory (physical address given) to somewhere + * in the kernel address space. + */ + external_addr = ioremap_writethrough((unsigned long)external_addr, + external_len); + if (external_vgaiobase) + external_vgaiobase = + (unsigned long)ioremap(external_vgaiobase, 0x10000); + screen_base = + real_screen_base = external_addr; + screen_len = external_len & PAGE_MASK; + memset (screen_base, 0, external_len); + } +#endif /* ATAFB_EXT */ + +// strcpy(fb_info.mode->name, "Atari Builtin "); + fb_info.fbops = &atafb_ops; + // try to set default (detected; requested) var + do_fb_set_var(&atafb_predefined[default_par - 1], 1); + // reads hw state into current par, which may not be sane yet + ata_get_par(¤t_par); + fb_info.par = ¤t_par; + // tries to read from HW which may not be initialized yet + // so set sane var first, then call atafb_set_par + atafb_get_var(&fb_info.var, &fb_info); + fb_info.flags = FBINFO_FLAG_DEFAULT; + + if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb, + NUM_TOTAL_MODES, &atafb_modedb[defmode], + fb_info.var.bits_per_pixel)) { + return -EINVAL; + } + + atafb_set_disp(&fb_info); + + fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0); + + + printk("Determined %dx%d, depth %d\n", + fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel); + if ((fb_info.var.xres != fb_info.var.xres_virtual) || + (fb_info.var.yres != fb_info.var.yres_virtual)) + printk(" virtual %dx%d\n", fb_info.var.xres_virtual, + fb_info.var.yres_virtual); + + if (register_framebuffer(&fb_info) < 0) { +#ifdef ATAFB_EXT + if (external_addr) { + iounmap(external_addr); + external_addr = NULL; + } + if (external_vgaiobase) { + iounmap((void*)external_vgaiobase); + external_vgaiobase = 0; + } #endif - else if (!strcmp(this_opt, "keep")) - DontCalcRes = 1; - else if (!strncmp(this_opt, "R", 1)) - atafb_setup_user(this_opt+1); - } - return 0; + return -EINVAL; + } + + // FIXME: mode needs setting! + //printk("fb%d: %s frame buffer device, using %dK of video memory\n", + // fb_info.node, fb_info.mode->name, screen_len>>10); + printk("fb%d: frame buffer device, using %dK of video memory\n", + fb_info.node, screen_len >> 10); + + /* TODO: This driver cannot be unloaded yet */ + return 0; } +module_init(atafb_init); + #ifdef MODULE MODULE_LICENSE("GPL"); -int init_module(void) +int cleanup_module(void) { - return atafb_init(); + unregister_framebuffer(&fb_info); + return atafb_deinit(); } #endif /* MODULE */ diff --git a/drivers/video/atafb.h b/drivers/video/atafb.h new file mode 100644 index 0000000..014e059 --- /dev/null +++ b/drivers/video/atafb.h @@ -0,0 +1,36 @@ +#ifndef _VIDEO_ATAFB_H +#define _VIDEO_ATAFB_H + +void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, + int dx, int height, int width); +void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color, + int sy, int sx, int height, int width); +void atafb_mfb_linefill(struct fb_info *info, u_long next_line, + int dy, int dx, u32 width, + const u8 *data, u32 bgcolor, u32 fgcolor); + +void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, + int dx, int height, int width); +void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color, + int sy, int sx, int height, int width); +void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line, + int dy, int dx, u32 width, + const u8 *data, u32 bgcolor, u32 fgcolor); + +void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, + int dx, int height, int width); +void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color, + int sy, int sx, int height, int width); +void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line, + int dy, int dx, u32 width, + const u8 *data, u32 bgcolor, u32 fgcolor); + +void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, + int dx, int height, int width); +void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color, + int sy, int sx, int height, int width); +void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line, + int dy, int dx, u32 width, + const u8 *data, u32 bgcolor, u32 fgcolor); + +#endif /* _VIDEO_ATAFB_H */ diff --git a/drivers/video/atafb_iplan2p2.c b/drivers/video/atafb_iplan2p2.c new file mode 100644 index 0000000..8cc9c50 --- /dev/null +++ b/drivers/video/atafb_iplan2p2.c @@ -0,0 +1,293 @@ +/* + * linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for + * interleaved bitplanes à la Atari (2 + * planes, 2 bytes interleave) + * + * Created 5 Apr 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/string.h> +#include <linux/fb.h> + +#include <asm/setup.h> + +#include "atafb.h" + +#define BPL 2 +#include "atafb_utils.h" + +void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, + int sy, int sx, int dy, int dx, + int height, int width) +{ + /* bmove() has to distinguish two major cases: If both, source and + * destination, start at even addresses or both are at odd + * addresses, just the first odd and last even column (if present) + * require special treatment (memmove_col()). The rest between + * then can be copied by normal operations, because all adjacent + * bytes are affected and are to be stored in the same order. + * The pathological case is when the move should go from an odd + * address to an even or vice versa. Since the bytes in the plane + * words must be assembled in new order, it seems wisest to make + * all movements by memmove_col(). + */ + + u8 *src, *dst; + u32 *s, *d; + int w, l , i, j; + u_int colsize; + u_int upwards = (dy < sy) || (dy == sy && dx < sx); + + colsize = height; + if (!((sx ^ dx) & 15)) { + /* odd->odd or even->even */ + + if (upwards) { + src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); + if (sx & 15) { + memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); + src += BPL * 2; + dst += BPL * 2; + width -= 8; + } + w = width >> 4; + if (w) { + s = (u32 *)src; + d = (u32 *)dst; + w *= BPL / 2; + l = next_line - w * 4; + for (j = height; j > 0; j--) { + for (i = w; i > 0; i--) + *d++ = *s++; + s = (u32 *)((u8 *)s + l); + d = (u32 *)((u8 *)d + l); + } + } + if (width & 15) + memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), + 0xff00ff00, height, next_line - BPL * 2); + } else { + src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); + + if ((sx + width) & 15) { + src -= BPL * 2; + dst -= BPL * 2; + memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); + width -= 8; + } + w = width >> 4; + if (w) { + s = (u32 *)src; + d = (u32 *)dst; + w *= BPL / 2; + l = next_line - w * 4; + for (j = height; j > 0; j--) { + for (i = w; i > 0; i--) + *--d = *--s; + s = (u32 *)((u8 *)s - l); + d = (u32 *)((u8 *)d - l); + } + } + if (sx & 15) + memmove32_col(dst - (width - 16) / (8 / BPL), + src - (width - 16) / (8 / BPL), + 0xff00ff, colsize, -next_line - BPL * 2); + } + } else { + /* odd->even or even->odd */ + if (upwards) { + u32 *src32, *dst32; + u32 pval[4], v, v1, mask; + int i, j, w, f; + + src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); + + mask = 0xff00ff00; + f = 0; + w = width; + if (sx & 15) { + f = 1; + w += 8; + } + if ((sx + width) & 15) + f |= 2; + w >>= 4; + for (i = height; i; i--) { + src32 = (u32 *)src; + dst32 = (u32 *)dst; + + if (f & 1) { + pval[0] = (*src32++ << 8) & mask; + } else { + pval[0] = dst32[0] & mask; + } + + for (j = w; j > 0; j--) { + v = *src32++; + v1 = v & mask; + *dst32++ = pval[0] | (v1 >> 8); + pval[0] = (v ^ v1) << 8; + } + + if (f & 2) { + dst32[0] = (dst32[0] & mask) | pval[0]; + } + + src += next_line; + dst += next_line; + } + } else { + u32 *src32, *dst32; + u32 pval[4], v, v1, mask; + int i, j, w, f; + + src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); + + mask = 0xff00ff; + f = 0; + w = width; + if ((dx + width) & 15) + f = 1; + if (sx & 15) { + f |= 2; + w += 8; + } + w >>= 4; + for (i = height; i; i--) { + src32 = (u32 *)src; + dst32 = (u32 *)dst; + + if (f & 1) { + pval[0] = dst32[-1] & mask; + } else { + pval[0] = (*--src32 >> 8) & mask; + } + + for (j = w; j > 0; j--) { + v = *--src32; + v1 = v & mask; + *--dst32 = pval[0] | (v1 << 8); + pval[0] = (v ^ v1) >> 8; + } + + if (!(f & 2)) { + dst32[-1] = (dst32[-1] & mask) | pval[0]; + } + + src -= next_line; + dst -= next_line; + } + } + } +} + +void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color, + int sy, int sx, int height, int width) +{ + u32 *dest; + int rows, i; + u32 cval[4]; + + dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); + if (sx & 15) { + u8 *dest8 = (u8 *)dest + 1; + + expand8_col2mask(color, cval); + + for (i = height; i; i--) { + fill8_col(dest8, cval); + dest8 += next_line; + } + dest += BPL / 2; + width -= 8; + } + + expand16_col2mask(color, cval); + rows = width >> 4; + if (rows) { + u32 *d = dest; + u32 off = next_line - rows * BPL * 2; + for (i = height; i; i--) { + d = fill16_col(d, rows, cval); + d = (u32 *)((long)d + off); + } + dest += rows * BPL / 2; + width &= 15; + } + + if (width) { + u8 *dest8 = (u8 *)dest; + + expand8_col2mask(color, cval); + + for (i = height; i; i--) { + fill8_col(dest8, cval); + dest8 += next_line; + } + } +} + +void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line, + int dy, int dx, u32 width, + const u8 *data, u32 bgcolor, u32 fgcolor) +{ + u32 *dest; + const u16 *data16; + int rows; + u32 fgm[4], bgm[4], m; + + dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); + if (dx & 15) { + fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); + dest += BPL / 2; + width -= 8; + } + + if (width >= 16) { + data16 = (const u16 *)data; + expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); + + for (rows = width / 16; rows; rows--) { + u16 d = *data16++; + m = d | ((u32)d << 16); + *dest++ = (m & fgm[0]) ^ bgm[0]; + } + + data = (const u8 *)data16; + width &= 15; + } + + if (width) + fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); +} + +#ifdef MODULE +MODULE_LICENSE("GPL"); + +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{ +} +#endif /* MODULE */ + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(atafb_iplan2p2_copyarea); +EXPORT_SYMBOL(atafb_iplan2p2_fillrect); +EXPORT_SYMBOL(atafb_iplan2p2_linefill); diff --git a/drivers/video/atafb_iplan2p4.c b/drivers/video/atafb_iplan2p4.c new file mode 100644 index 0000000..bee0d89 --- /dev/null +++ b/drivers/video/atafb_iplan2p4.c @@ -0,0 +1,308 @@ +/* + * linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for + * interleaved bitplanes à la Atari (4 + * planes, 2 bytes interleave) + * + * Created 5 Apr 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/string.h> +#include <linux/fb.h> + +#include <asm/setup.h> + +#include "atafb.h" + +#define BPL 4 +#include "atafb_utils.h" + +void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, + int sy, int sx, int dy, int dx, + int height, int width) +{ + /* bmove() has to distinguish two major cases: If both, source and + * destination, start at even addresses or both are at odd + * addresses, just the first odd and last even column (if present) + * require special treatment (memmove_col()). The rest between + * then can be copied by normal operations, because all adjacent + * bytes are affected and are to be stored in the same order. + * The pathological case is when the move should go from an odd + * address to an even or vice versa. Since the bytes in the plane + * words must be assembled in new order, it seems wisest to make + * all movements by memmove_col(). + */ + + u8 *src, *dst; + u32 *s, *d; + int w, l , i, j; + u_int colsize; + u_int upwards = (dy < sy) || (dy == sy && dx < sx); + + colsize = height; + if (!((sx ^ dx) & 15)) { + /* odd->odd or even->even */ + + if (upwards) { + src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); + if (sx & 15) { + memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); + src += BPL * 2; + dst += BPL * 2; + width -= 8; + } + w = width >> 4; + if (w) { + s = (u32 *)src; + d = (u32 *)dst; + w *= BPL / 2; + l = next_line - w * 4; + for (j = height; j > 0; j--) { + for (i = w; i > 0; i--) + *d++ = *s++; + s = (u32 *)((u8 *)s + l); + d = (u32 *)((u8 *)d + l); + } + } + if (width & 15) + memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), + 0xff00ff00, height, next_line - BPL * 2); + } else { + src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); + + if ((sx + width) & 15) { + src -= BPL * 2; + dst -= BPL * 2; + memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); + width -= 8; + } + w = width >> 4; + if (w) { + s = (u32 *)src; + d = (u32 *)dst; + w *= BPL / 2; + l = next_line - w * 4; + for (j = height; j > 0; j--) { + for (i = w; i > 0; i--) + *--d = *--s; + s = (u32 *)((u8 *)s - l); + d = (u32 *)((u8 *)d - l); + } + } + if (sx & 15) + memmove32_col(dst - (width - 16) / (8 / BPL), + src - (width - 16) / (8 / BPL), + 0xff00ff, colsize, -next_line - BPL * 2); + } + } else { + /* odd->even or even->odd */ + if (upwards) { + u32 *src32, *dst32; + u32 pval[4], v, v1, mask; + int i, j, w, f; + + src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); + + mask = 0xff00ff00; + f = 0; + w = width; + if (sx & 15) { + f = 1; + w += 8; + } + if ((sx + width) & 15) + f |= 2; + w >>= 4; + for (i = height; i; i--) { + src32 = (u32 *)src; + dst32 = (u32 *)dst; + + if (f & 1) { + pval[0] = (*src32++ << 8) & mask; + pval[1] = (*src32++ << 8) & mask; + } else { + pval[0] = dst32[0] & mask; + pval[1] = dst32[1] & mask; + } + + for (j = w; j > 0; j--) { + v = *src32++; + v1 = v & mask; + *dst32++ = pval[0] | (v1 >> 8); + pval[0] = (v ^ v1) << 8; + v = *src32++; + v1 = v & mask; + *dst32++ = pval[1] | (v1 >> 8); + pval[1] = (v ^ v1) << 8; + } + + if (f & 2) { + dst32[0] = (dst32[0] & mask) | pval[0]; + dst32[1] = (dst32[1] & mask) | pval[1]; + } + + src += next_line; + dst += next_line; + } + } else { + u32 *src32, *dst32; + u32 pval[4], v, v1, mask; + int i, j, w, f; + + src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); + + mask = 0xff00ff; + f = 0; + w = width; + if ((dx + width) & 15) + f = 1; + if (sx & 15) { + f |= 2; + w += 8; + } + w >>= 4; + for (i = height; i; i--) { + src32 = (u32 *)src; + dst32 = (u32 *)dst; + + if (f & 1) { + pval[0] = dst32[-1] & mask; + pval[1] = dst32[-2] & mask; + } else { + pval[0] = (*--src32 >> 8) & mask; + pval[1] = (*--src32 >> 8) & mask; + } + + for (j = w; j > 0; j--) { + v = *--src32; + v1 = v & mask; + *--dst32 = pval[0] | (v1 << 8); + pval[0] = (v ^ v1) >> 8; + v = *--src32; + v1 = v & mask; + *--dst32 = pval[1] | (v1 << 8); + pval[1] = (v ^ v1) >> 8; + } + + if (!(f & 2)) { + dst32[-1] = (dst32[-1] & mask) | pval[0]; + dst32[-2] = (dst32[-2] & mask) | pval[1]; + } + + src -= next_line; + dst -= next_line; + } + } + } +} + +void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color, + int sy, int sx, int height, int width) +{ + u32 *dest; + int rows, i; + u32 cval[4]; + + dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); + if (sx & 15) { + u8 *dest8 = (u8 *)dest + 1; + + expand8_col2mask(color, cval); + + for (i = height; i; i--) { + fill8_col(dest8, cval); + dest8 += next_line; + } + dest += BPL / 2; + width -= 8; + } + + expand16_col2mask(color, cval); + rows = width >> 4; + if (rows) { + u32 *d = dest; + u32 off = next_line - rows * BPL * 2; + for (i = height; i; i--) { + d = fill16_col(d, rows, cval); + d = (u32 *)((long)d + off); + } + dest += rows * BPL / 2; + width &= 15; + } + + if (width) { + u8 *dest8 = (u8 *)dest; + + expand8_col2mask(color, cval); + + for (i = height; i; i--) { + fill8_col(dest8, cval); + dest8 += next_line; + } + } +} + +void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line, + int dy, int dx, u32 width, + const u8 *data, u32 bgcolor, u32 fgcolor) +{ + u32 *dest; + const u16 *data16; + int rows; + u32 fgm[4], bgm[4], m; + + dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); + if (dx & 15) { + fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); + dest += BPL / 2; + width -= 8; + } + + if (width >= 16) { + data16 = (const u16 *)data; + expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); + + for (rows = width / 16; rows; rows--) { + u16 d = *data16++; + m = d | ((u32)d << 16); + *dest++ = (m & fgm[0]) ^ bgm[0]; + *dest++ = (m & fgm[1]) ^ bgm[1]; + } + + data = (const u8 *)data16; + width &= 15; + } + + if (width) + fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); +} + +#ifdef MODULE +MODULE_LICENSE("GPL"); + +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{ +} +#endif /* MODULE */ + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(atafb_iplan2p4_copyarea); +EXPORT_SYMBOL(atafb_iplan2p4_fillrect); +EXPORT_SYMBOL(atafb_iplan2p4_linefill); diff --git a/drivers/video/atafb_iplan2p8.c b/drivers/video/atafb_iplan2p8.c new file mode 100644 index 0000000..356fb52 --- /dev/null +++ b/drivers/video/atafb_iplan2p8.c @@ -0,0 +1,345 @@ +/* + * linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for + * interleaved bitplanes à la Atari (8 + * planes, 2 bytes interleave) + * + * Created 5 Apr 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/string.h> +#include <linux/fb.h> + +#include <asm/setup.h> + +#include "atafb.h" + +#define BPL 8 +#include "atafb_utils.h" + + +/* Copies a 8 plane column from 's', height 'h', to 'd'. */ + +/* This expands a 8 bit color into two longs for two movepl (8 plane) + * operations. + */ + +void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, + int sy, int sx, int dy, int dx, + int height, int width) +{ + /* bmove() has to distinguish two major cases: If both, source and + * destination, start at even addresses or both are at odd + * addresses, just the first odd and last even column (if present) + * require special treatment (memmove_col()). The rest between + * then can be copied by normal operations, because all adjacent + * bytes are affected and are to be stored in the same order. + * The pathological case is when the move should go from an odd + * address to an even or vice versa. Since the bytes in the plane + * words must be assembled in new order, it seems wisest to make + * all movements by memmove_col(). + */ + + u8 *src, *dst; + u32 *s, *d; + int w, l , i, j; + u_int colsize; + u_int upwards = (dy < sy) || (dy == sy && dx < sx); + + colsize = height; + if (!((sx ^ dx) & 15)) { + /* odd->odd or even->even */ + + if (upwards) { + src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); + if (sx & 15) { + memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); + src += BPL * 2; + dst += BPL * 2; + width -= 8; + } + w = width >> 4; + if (w) { + s = (u32 *)src; + d = (u32 *)dst; + w *= BPL / 2; + l = next_line - w * 4; + for (j = height; j > 0; j--) { + for (i = w; i > 0; i--) + *d++ = *s++; + s = (u32 *)((u8 *)s + l); + d = (u32 *)((u8 *)d + l); + } + } + if (width & 15) + memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), + 0xff00ff00, height, next_line - BPL * 2); + } else { + src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); + + if ((sx + width) & 15) { + src -= BPL * 2; + dst -= BPL * 2; + memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); + width -= 8; + } + w = width >> 4; + if (w) { + s = (u32 *)src; + d = (u32 *)dst; + w *= BPL / 2; + l = next_line - w * 4; + for (j = height; j > 0; j--) { + for (i = w; i > 0; i--) + *--d = *--s; + s = (u32 *)((u8 *)s - l); + d = (u32 *)((u8 *)d - l); + } + } + if (sx & 15) + memmove32_col(dst - (width - 16) / (8 / BPL), + src - (width - 16) / (8 / BPL), + 0xff00ff, colsize, -next_line - BPL * 2); + } + } else { + /* odd->even or even->odd */ + if (upwards) { + u32 *src32, *dst32; + u32 pval[4], v, v1, mask; + int i, j, w, f; + + src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); + + mask = 0xff00ff00; + f = 0; + w = width; + if (sx & 15) { + f = 1; + w += 8; + } + if ((sx + width) & 15) + f |= 2; + w >>= 4; + for (i = height; i; i--) { + src32 = (u32 *)src; + dst32 = (u32 *)dst; + + if (f & 1) { + pval[0] = (*src32++ << 8) & mask; + pval[1] = (*src32++ << 8) & mask; + pval[2] = (*src32++ << 8) & mask; + pval[3] = (*src32++ << 8) & mask; + } else { + pval[0] = dst32[0] & mask; + pval[1] = dst32[1] & mask; + pval[2] = dst32[2] & mask; + pval[3] = dst32[3] & mask; + } + + for (j = w; j > 0; j--) { + v = *src32++; + v1 = v & mask; + *dst32++ = pval[0] | (v1 >> 8); + pval[0] = (v ^ v1) << 8; + v = *src32++; + v1 = v & mask; + *dst32++ = pval[1] | (v1 >> 8); + pval[1] = (v ^ v1) << 8; + v = *src32++; + v1 = v & mask; + *dst32++ = pval[2] | (v1 >> 8); + pval[2] = (v ^ v1) << 8; + v = *src32++; + v1 = v & mask; + *dst32++ = pval[3] | (v1 >> 8); + pval[3] = (v ^ v1) << 8; + } + + if (f & 2) { + dst32[0] = (dst32[0] & mask) | pval[0]; + dst32[1] = (dst32[1] & mask) | pval[1]; + dst32[2] = (dst32[2] & mask) | pval[2]; + dst32[3] = (dst32[3] & mask) | pval[3]; + } + + src += next_line; + dst += next_line; + } + } else { + u32 *src32, *dst32; + u32 pval[4], v, v1, mask; + int i, j, w, f; + + src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); + dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); + + mask = 0xff00ff; + f = 0; + w = width; + if ((dx + width) & 15) + f = 1; + if (sx & 15) { + f |= 2; + w += 8; + } + w >>= 4; + for (i = height; i; i--) { + src32 = (u32 *)src; + dst32 = (u32 *)dst; + + if (f & 1) { + pval[0] = dst32[-1] & mask; + pval[1] = dst32[-2] & mask; + pval[2] = dst32[-3] & mask; + pval[3] = dst32[-4] & mask; + } else { + pval[0] = (*--src32 >> 8) & mask; + pval[1] = (*--src32 >> 8) & mask; + pval[2] = (*--src32 >> 8) & mask; + pval[3] = (*--src32 >> 8) & mask; + } + + for (j = w; j > 0; j--) { + v = *--src32; + v1 = v & mask; + *--dst32 = pval[0] | (v1 << 8); + pval[0] = (v ^ v1) >> 8; + v = *--src32; + v1 = v & mask; + *--dst32 = pval[1] | (v1 << 8); + pval[1] = (v ^ v1) >> 8; + v = *--src32; + v1 = v & mask; + *--dst32 = pval[2] | (v1 << 8); + pval[2] = (v ^ v1) >> 8; + v = *--src32; + v1 = v & mask; + *--dst32 = pval[3] | (v1 << 8); + pval[3] = (v ^ v1) >> 8; + } + + if (!(f & 2)) { + dst32[-1] = (dst32[-1] & mask) | pval[0]; + dst32[-2] = (dst32[-2] & mask) | pval[1]; + dst32[-3] = (dst32[-3] & mask) | pval[2]; + dst32[-4] = (dst32[-4] & mask) | pval[3]; + } + + src -= next_line; + dst -= next_line; + } + } + } +} + +void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color, + int sy, int sx, int height, int width) +{ + u32 *dest; + int rows, i; + u32 cval[4]; + + dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); + if (sx & 15) { + u8 *dest8 = (u8 *)dest + 1; + + expand8_col2mask(color, cval); + + for (i = height; i; i--) { + fill8_col(dest8, cval); + dest8 += next_line; + } + dest += BPL / 2; + width -= 8; + } + + expand16_col2mask(color, cval); + rows = width >> 4; + if (rows) { + u32 *d = dest; + u32 off = next_line - rows * BPL * 2; + for (i = height; i; i--) { + d = fill16_col(d, rows, cval); + d = (u32 *)((long)d + off); + } + dest += rows * BPL / 2; + width &= 15; + } + + if (width) { + u8 *dest8 = (u8 *)dest; + + expand8_col2mask(color, cval); + + for (i = height; i; i--) { + fill8_col(dest8, cval); + dest8 += next_line; + } + } +} + +void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line, + int dy, int dx, u32 width, + const u8 *data, u32 bgcolor, u32 fgcolor) +{ + u32 *dest; + const u16 *data16; + int rows; + u32 fgm[4], bgm[4], m; + + dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); + if (dx & 15) { + fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); + dest += BPL / 2; + width -= 8; + } + + if (width >= 16) { + data16 = (const u16 *)data; + expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); + + for (rows = width / 16; rows; rows--) { + u16 d = *data16++; + m = d | ((u32)d << 16); + *dest++ = (m & fgm[0]) ^ bgm[0]; + *dest++ = (m & fgm[1]) ^ bgm[1]; + *dest++ = (m & fgm[2]) ^ bgm[2]; + *dest++ = (m & fgm[3]) ^ bgm[3]; + } + + data = (const u8 *)data16; + width &= 15; + } + + if (width) + fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); +} + +#ifdef MODULE +MODULE_LICENSE("GPL"); + +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{ +} +#endif /* MODULE */ + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(atafb_iplan2p8_copyarea); +EXPORT_SYMBOL(atafb_iplan2p8_fillrect); +EXPORT_SYMBOL(atafb_iplan2p8_linefill); diff --git a/drivers/video/atafb_mfb.c b/drivers/video/atafb_mfb.c new file mode 100644 index 0000000..6a352d6 --- /dev/null +++ b/drivers/video/atafb_mfb.c @@ -0,0 +1,112 @@ +/* + * linux/drivers/video/mfb.c -- Low level frame buffer operations for + * monochrome + * + * Created 5 Apr 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/string.h> +#include <linux/fb.h> + +#include "atafb.h" +#include "atafb_utils.h" + + + /* + * Monochrome + */ + +void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, + int sy, int sx, int dy, int dx, + int height, int width) +{ + u8 *src, *dest; + u_int rows; + + if (sx == 0 && dx == 0 && width == next_line) { + src = (u8 *)info->screen_base + sy * (width >> 3); + dest = (u8 *)info->screen_base + dy * (width >> 3); + fb_memmove(dest, src, height * (width >> 3)); + } else if (dy <= sy) { + src = (u8 *)info->screen_base + sy * next_line + (sx >> 3); + dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3); + for (rows = height; rows--;) { + fb_memmove(dest, src, width >> 3); + src += next_line; + dest += next_line; + } + } else { + src = (u8 *)info->screen_base + (sy + height - 1) * next_line + (sx >> 3); + dest = (u8 *)info->screen_base + (dy + height - 1) * next_line + (dx >> 3); + for (rows = height; rows--;) { + fb_memmove(dest, src, width >> 3); + src -= next_line; + dest -= next_line; + } + } +} + +void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color, + int sy, int sx, int height, int width) +{ + u8 *dest; + u_int rows; + + dest = (u8 *)info->screen_base + sy * next_line + (sx >> 3); + + if (sx == 0 && width == next_line) { + if (color) + fb_memset255(dest, height * (width >> 3)); + else + fb_memclear(dest, height * (width >> 3)); + } else { + for (rows = height; rows--; dest += next_line) { + if (color) + fb_memset255(dest, width >> 3); + else + fb_memclear_small(dest, width >> 3); + } + } +} + +void atafb_mfb_linefill(struct fb_info *info, u_long next_line, + int dy, int dx, u32 width, + const u8 *data, u32 bgcolor, u32 fgcolor) +{ + u8 *dest; + u_int rows; + + dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3); + + for (rows = width / 8; rows--; /* check margins */ ) { + // use fast_memmove or fb_memmove + *dest++ = *data++; + } +} + +#ifdef MODULE +MODULE_LICENSE("GPL"); + +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{ +} +#endif /* MODULE */ + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(atafb_mfb_copyarea); +EXPORT_SYMBOL(atafb_mfb_fillrect); +EXPORT_SYMBOL(atafb_mfb_linefill); diff --git a/drivers/video/atafb_utils.h b/drivers/video/atafb_utils.h new file mode 100644 index 0000000..ac9e19d --- /dev/null +++ b/drivers/video/atafb_utils.h @@ -0,0 +1,400 @@ +#ifndef _VIDEO_ATAFB_UTILS_H +#define _VIDEO_ATAFB_UTILS_H + +/* ================================================================= */ +/* Utility Assembler Functions */ +/* ================================================================= */ + +/* ====================================================================== */ + +/* Those of a delicate disposition might like to skip the next couple of + * pages. + * + * These functions are drop in replacements for memmove and + * memset(_, 0, _). However their five instances add at least a kilobyte + * to the object file. You have been warned. + * + * Not a great fan of assembler for the sake of it, but I think + * that these routines are at least 10 times faster than their C + * equivalents for large blits, and that's important to the lowest level of + * a graphics driver. Question is whether some scheme with the blitter + * would be faster. I suspect not for simple text system - not much + * asynchrony. + * + * Code is very simple, just gruesome expansion. Basic strategy is to + * increase data moved/cleared at each step to 16 bytes to reduce + * instruction per data move overhead. movem might be faster still + * For more than 15 bytes, we try to align the write direction on a + * longword boundary to get maximum speed. This is even more gruesome. + * Unaligned read/write used requires 68020+ - think this is a problem? + * + * Sorry! + */ + + +/* ++roman: I've optimized Robert's original versions in some minor + * aspects, e.g. moveq instead of movel, let gcc choose the registers, + * use movem in some places... + * For other modes than 1 plane, lots of more such assembler functions + * were needed (e.g. the ones using movep or expanding color values). + */ + +/* ++andreas: more optimizations: + subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc + addal is faster than addaw + movep is rather expensive compared to ordinary move's + some functions rewritten in C for clarity, no speed loss */ + +static inline void *fb_memclear_small(void *s, size_t count) +{ + if (!count) + return 0; + + asm volatile ("\n" + " lsr.l #1,%1 ; jcc 1f ; move.b %2,-(%0)\n" + "1: lsr.l #1,%1 ; jcc 1f ; move.w %2,-(%0)\n" + "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0)\n" + "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n" + "1:" + : "=a" (s), "=d" (count) + : "d" (0), "0" ((char *)s + count), "1" (count)); + asm volatile ("\n" + " subq.l #1,%1\n" + " jcs 3f\n" + " move.l %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n" + "2: movem.l %2/%%d4/%%d5/%%d6,-(%0)\n" + " dbra %1,2b\n" + "3:" + : "=a" (s), "=d" (count) + : "d" (0), "0" (s), "1" (count) + : "d4", "d5", "d6" + ); + + return 0; +} + + +static inline void *fb_memclear(void *s, size_t count) +{ + if (!count) + return 0; + + if (count < 16) { + asm volatile ("\n" + " lsr.l #1,%1 ; jcc 1f ; clr.b (%0)+\n" + "1: lsr.l #1,%1 ; jcc 1f ; clr.w (%0)+\n" + "1: lsr.l #1,%1 ; jcc 1f ; clr.l (%0)+\n" + "1: lsr.l #1,%1 ; jcc 1f ; clr.l (%0)+ ; clr.l (%0)+\n" + "1:" + : "=a" (s), "=d" (count) + : "0" (s), "1" (count)); + } else { + long tmp; + asm volatile ("\n" + " move.l %1,%2\n" + " lsr.l #1,%2 ; jcc 1f ; clr.b (%0)+ ; subq.w #1,%1\n" + " lsr.l #1,%2 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/ + " clr.w (%0)+ ; subq.w #2,%1 ; jra 2f\n" + "1: lsr.l #1,%2 ; jcc 2f\n" + " clr.w (%0)+ ; subq.w #2,%1\n" + "2: move.w %1,%2; lsr.l #2,%1 ; jeq 6f\n" + " lsr.l #1,%1 ; jcc 3f ; clr.l (%0)+\n" + "3: lsr.l #1,%1 ; jcc 4f ; clr.l (%0)+ ; clr.l (%0)+\n" + "4: subq.l #1,%1 ; jcs 6f\n" + "5: clr.l (%0)+; clr.l (%0)+ ; clr.l (%0)+ ; clr.l (%0)+\n" + " dbra %1,5b ; clr.w %1; subq.l #1,%1; jcc 5b\n" + "6: move.w %2,%1; btst #1,%1 ; jeq 7f ; clr.w (%0)+\n" + "7: btst #0,%1 ; jeq 8f ; clr.b (%0)+\n" + "8:" + : "=a" (s), "=d" (count), "=d" (tmp) + : "0" (s), "1" (count)); + } + + return 0; +} + + +static inline void *fb_memset255(void *s, size_t count) +{ + if (!count) + return 0; + + asm volatile ("\n" + " lsr.l #1,%1 ; jcc 1f ; move.b %2,-(%0)\n" + "1: lsr.l #1,%1 ; jcc 1f ; move.w %2,-(%0)\n" + "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0)\n" + "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n" + "1:" + : "=a" (s), "=d" (count) + : "d" (-1), "0" ((char *)s+count), "1" (count)); + asm volatile ("\n" + " subq.l #1,%1 ; jcs 3f\n" + " move.l %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n" + "2: movem.l %2/%%d4/%%d5/%%d6,-(%0)\n" + " dbra %1,2b\n" + "3:" + : "=a" (s), "=d" (count) + : "d" (-1), "0" (s), "1" (count) + : "d4", "d5", "d6"); + + return 0; +} + + +static inline void *fb_memmove(void *d, const void *s, size_t count) +{ + if (d < s) { + if (count < 16) { + asm volatile ("\n" + " lsr.l #1,%2 ; jcc 1f ; move.b (%1)+,(%0)+\n" + "1: lsr.l #1,%2 ; jcc 1f ; move.w (%1)+,(%0)+\n" + "1: lsr.l #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+\n" + "1: lsr.l #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n" + "1:" + : "=a" (d), "=a" (s), "=d" (count) + : "0" (d), "1" (s), "2" (count)); + } else { + long tmp; + asm volatile ("\n" + " move.l %0,%3\n" + " lsr.l #1,%3 ; jcc 1f ; move.b (%1)+,(%0)+ ; subqw #1,%2\n" + " lsr.l #1,%3 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/ + " move.w (%1)+,(%0)+ ; subqw #2,%2 ; jra 2f\n" + "1: lsr.l #1,%3 ; jcc 2f\n" + " move.w (%1)+,(%0)+ ; subqw #2,%2\n" + "2: move.w %2,%-; lsr.l #2,%2 ; jeq 6f\n" + " lsr.l #1,%2 ; jcc 3f ; move.l (%1)+,(%0)+\n" + "3: lsr.l #1,%2 ; jcc 4f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n" + "4: subq.l #1,%2 ; jcs 6f\n" + "5: move.l (%1)+,(%0)+; move.l (%1)+,(%0)+\n" + " move.l (%1)+,(%0)+; move.l (%1)+,(%0)+\n" + " dbra %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n" + "6: move.w %+,%2; btst #1,%2 ; jeq 7f ; move.w (%1)+,(%0)+\n" + "7: btst #0,%2 ; jeq 8f ; move.b (%1)+,(%0)+\n" + "8:" + : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp) + : "0" (d), "1" (s), "2" (count)); + } + } else { + if (count < 16) { + asm volatile ("\n" + " lsr.l #1,%2 ; jcc 1f ; move.b -(%1),-(%0)\n" + "1: lsr.l #1,%2 ; jcc 1f ; move.w -(%1),-(%0)\n" + "1: lsr.l #1,%2 ; jcc 1f ; move.l -(%1),-(%0)\n" + "1: lsr.l #1,%2 ; jcc 1f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n" + "1:" + : "=a" (d), "=a" (s), "=d" (count) + : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)); + } else { + long tmp; + + asm volatile ("\n" + " move.l %0,%3\n" + " lsr.l #1,%3 ; jcc 1f ; move.b -(%1),-(%0) ; subqw #1,%2\n" + " lsr.l #1,%3 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/ + " move.w -(%1),-(%0) ; subqw #2,%2 ; jra 2f\n" + "1: lsr.l #1,%3 ; jcc 2f\n" + " move.w -(%1),-(%0) ; subqw #2,%2\n" + "2: move.w %2,%-; lsr.l #2,%2 ; jeq 6f\n" + " lsr.l #1,%2 ; jcc 3f ; move.l -(%1),-(%0)\n" + "3: lsr.l #1,%2 ; jcc 4f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n" + "4: subq.l #1,%2 ; jcs 6f\n" + "5: move.l -(%1),-(%0); move.l -(%1),-(%0)\n" + " move.l -(%1),-(%0); move.l -(%1),-(%0)\n" + " dbra %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n" + "6: move.w %+,%2; btst #1,%2 ; jeq 7f ; move.w -(%1),-(%0)\n" + "7: btst #0,%2 ; jeq 8f ; move.b -(%1),-(%0)\n" + "8:" + : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp) + : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)); + } + } + + return 0; +} + + +/* ++andreas: Simple and fast version of memmove, assumes size is + divisible by 16, suitable for moving the whole screen bitplane */ +static inline void fast_memmove(char *dst, const char *src, size_t size) +{ + if (!size) + return; + if (dst < src) + asm volatile ("\n" + "1: movem.l (%0)+,%%d0/%%d1/%%a0/%%a1\n" + " movem.l %%d0/%%d1/%%a0/%%a1,%1@\n" + " addq.l #8,%1; addq.l #8,%1\n" + " dbra %2,1b\n" + " clr.w %2; subq.l #1,%2\n" + " jcc 1b" + : "=a" (src), "=a" (dst), "=d" (size) + : "0" (src), "1" (dst), "2" (size / 16 - 1) + : "d0", "d1", "a0", "a1", "memory"); + else + asm volatile ("\n" + "1: subq.l #8,%0; subq.l #8,%0\n" + " movem.l %0@,%%d0/%%d1/%%a0/%%a1\n" + " movem.l %%d0/%%d1/%%a0/%%a1,-(%1)\n" + " dbra %2,1b\n" + " clr.w %2; subq.l #1,%2\n" + " jcc 1b" + : "=a" (src), "=a" (dst), "=d" (size) + : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1) + : "d0", "d1", "a0", "a1", "memory"); +} + +#ifdef BPL + +/* + * This expands a up to 8 bit color into two longs + * for movel operations. + */ +static const u32 four2long[] = { + 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, + 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, + 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, + 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff, +}; + +static inline void expand8_col2mask(u8 c, u32 m[]) +{ + m[0] = four2long[c & 15]; +#if BPL > 4 + m[1] = four2long[c >> 4]; +#endif +} + +static inline void expand8_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[]) +{ + fgm[0] = four2long[fg & 15] ^ (bgm[0] = four2long[bg & 15]); +#if BPL > 4 + fgm[1] = four2long[fg >> 4] ^ (bgm[1] = four2long[bg >> 4]); +#endif +} + +/* + * set an 8bit value to a color + */ +static inline void fill8_col(u8 *dst, u32 m[]) +{ + u32 tmp = m[0]; + dst[0] = tmp; + dst[2] = (tmp >>= 8); +#if BPL > 2 + dst[4] = (tmp >>= 8); + dst[6] = tmp >> 8; +#endif +#if BPL > 4 + tmp = m[1]; + dst[8] = tmp; + dst[10] = (tmp >>= 8); + dst[12] = (tmp >>= 8); + dst[14] = tmp >> 8; +#endif +} + +/* + * set an 8bit value according to foreground/background color + */ +static inline void fill8_2col(u8 *dst, u8 fg, u8 bg, u32 mask) +{ + u32 fgm[2], bgm[2], tmp; + + expand8_2col2mask(fg, bg, fgm, bgm); + + mask |= mask << 8; +#if BPL > 2 + mask |= mask << 16; +#endif + tmp = (mask & fgm[0]) ^ bgm[0]; + dst[0] = tmp; + dst[2] = (tmp >>= 8); +#if BPL > 2 + dst[4] = (tmp >>= 8); + dst[6] = tmp >> 8; +#endif +#if BPL > 4 + tmp = (mask & fgm[1]) ^ bgm[1]; + dst[8] = tmp; + dst[10] = (tmp >>= 8); + dst[12] = (tmp >>= 8); + dst[14] = tmp >> 8; +#endif +} + +static const u32 two2word[] = { + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff +}; + +static inline void expand16_col2mask(u8 c, u32 m[]) +{ + m[0] = two2word[c & 3]; +#if BPL > 2 + m[1] = two2word[(c >> 2) & 3]; +#endif +#if BPL > 4 + m[2] = two2word[(c >> 4) & 3]; + m[3] = two2word[c >> 6]; +#endif +} + +static inline void expand16_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[]) +{ + bgm[0] = two2word[bg & 3]; + fgm[0] = two2word[fg & 3] ^ bgm[0]; +#if BPL > 2 + bgm[1] = two2word[(bg >> 2) & 3]; + fgm[1] = two2word[(fg >> 2) & 3] ^ bgm[1]; +#endif +#if BPL > 4 + bgm[2] = two2word[(bg >> 4) & 3]; + fgm[2] = two2word[(fg >> 4) & 3] ^ bgm[2]; + bgm[3] = two2word[bg >> 6]; + fgm[3] = two2word[fg >> 6] ^ bgm[3]; +#endif +} + +static inline u32 *fill16_col(u32 *dst, int rows, u32 m[]) +{ + while (rows) { + *dst++ = m[0]; +#if BPL > 2 + *dst++ = m[1]; +#endif +#if BPL > 4 + *dst++ = m[2]; + *dst++ = m[3]; +#endif + rows--; + } + return dst; +} + +static inline void memmove32_col(void *dst, void *src, u32 mask, u32 h, u32 bytes) +{ + u32 *s, *d, v; + + s = src; + d = dst; + do { + v = (*s++ & mask) | (*d & ~mask); + *d++ = v; +#if BPL > 2 + v = (*s++ & mask) | (*d & ~mask); + *d++ = v; +#endif +#if BPL > 4 + v = (*s++ & mask) | (*d & ~mask); + *d++ = v; + v = (*s++ & mask) | (*d & ~mask); + *d++ = v; +#endif + d = (u32 *)((u8 *)d + bytes); + s = (u32 *)((u8 *)s + bytes); + } while (--h); +} + +#endif + +#endif /* _VIDEO_ATAFB_UTILS_H */ diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c new file mode 100644 index 0000000..e1d5bd0 --- /dev/null +++ b/drivers/video/atmel_lcdfb.c @@ -0,0 +1,752 @@ +/* + * Driver for AT91/AT32 LCD Controller + * + * Copyright (C) 2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/clk.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include <asm/arch/board.h> +#include <asm/arch/cpu.h> +#include <asm/arch/gpio.h> + +#include <video/atmel_lcdc.h> + +#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg)) +#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg)) + +/* configurable parameters */ +#define ATMEL_LCDC_CVAL_DEFAULT 0xc8 +#define ATMEL_LCDC_DMA_BURST_LEN 8 + +#if defined(CONFIG_ARCH_AT91SAM9263) +#define ATMEL_LCDC_FIFO_SIZE 2048 +#else +#define ATMEL_LCDC_FIFO_SIZE 512 +#endif + +#if defined(CONFIG_ARCH_AT91) +#define ATMEL_LCDFB_FBINFO_DEFAULT FBINFO_DEFAULT + +static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, + struct fb_var_screeninfo *var) +{ + +} +#elif defined(CONFIG_AVR32) +#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ + | FBINFO_PARTIAL_PAN_OK \ + | FBINFO_HWACCEL_XPAN \ + | FBINFO_HWACCEL_YPAN) + +static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, + struct fb_var_screeninfo *var) +{ + u32 dma2dcfg; + u32 pixeloff; + + pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f; + + dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8; + dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; + lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); + + /* Update configuration */ + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, + lcdc_readl(sinfo, ATMEL_LCDC_DMACON) + | ATMEL_LCDC_DMAUPDT); +} +#endif + + +static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + + +static void atmel_lcdfb_update_dma(struct fb_info *info, + struct fb_var_screeninfo *var) +{ + struct atmel_lcdfb_info *sinfo = info->par; + struct fb_fix_screeninfo *fix = &info->fix; + unsigned long dma_addr; + + dma_addr = (fix->smem_start + var->yoffset * fix->line_length + + var->xoffset * var->bits_per_pixel / 8); + + dma_addr &= ~3UL; + + /* Set framebuffer DMA base address and pixel offset */ + lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); + + atmel_lcdfb_update_dma2d(sinfo, var); +} + +static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) +{ + struct fb_info *info = sinfo->info; + + dma_free_writecombine(info->device, info->fix.smem_len, + info->screen_base, info->fix.smem_start); +} + +/** + * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory + * @sinfo: the frame buffer to allocate memory for + */ +static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) +{ + struct fb_info *info = sinfo->info; + struct fb_var_screeninfo *var = &info->var; + + info->fix.smem_len = (var->xres_virtual * var->yres_virtual + * ((var->bits_per_pixel + 7) / 8)); + + info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, + (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); + + if (!info->screen_base) { + return -ENOMEM; + } + + return 0; +} + +/** + * atmel_lcdfb_check_var - Validates a var passed in. + * @var: frame buffer variable screen structure + * @info: frame buffer structure that represents a single frame buffer + * + * Checks to see if the hardware supports the state requested by + * var passed in. This function does not alter the hardware + * state!!! This means the data stored in struct fb_info and + * struct atmel_lcdfb_info do not change. This includes the var + * inside of struct fb_info. Do NOT change these. This function + * can be called on its own if we intent to only test a mode and + * not actually set it. The stuff in modedb.c is a example of + * this. If the var passed in is slightly off by what the + * hardware can support then we alter the var PASSED in to what + * we can do. If the hardware doesn't support mode change a + * -EINVAL will be returned by the upper layers. You don't need + * to implement this function then. If you hardware doesn't + * support changing the resolution then this function is not + * needed. In this case the driver would just provide a var that + * represents the static state the screen is in. + * + * Returns negative errno on error, or zero on success. + */ +static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct device *dev = info->device; + struct atmel_lcdfb_info *sinfo = info->par; + unsigned long clk_value_khz; + + clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; + + dev_dbg(dev, "%s:\n", __func__); + dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); + dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock)); + dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); + dev_dbg(dev, " clk: %lu KHz\n", clk_value_khz); + + if ((PICOS2KHZ(var->pixclock) * var->bits_per_pixel / 8) > clk_value_khz) { + dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock)); + return -EINVAL; + } + + /* Force same alignment for each line */ + var->xres = (var->xres + 3) & ~3UL; + var->xres_virtual = (var->xres_virtual + 3) & ~3UL; + + var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0; + var->transp.msb_right = 0; + var->transp.offset = var->transp.length = 0; + var->xoffset = var->yoffset = 0; + + switch (var->bits_per_pixel) { + case 2: + case 4: + case 8: + var->red.offset = var->green.offset = var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length + = var->bits_per_pixel; + break; + case 15: + case 16: + var->red.offset = 0; + var->green.offset = 5; + var->blue.offset = 10; + var->red.length = var->green.length = var->blue.length = 5; + break; + case 24: + case 32: + var->red.offset = 0; + var->green.offset = 8; + var->blue.offset = 16; + var->red.length = var->green.length = var->blue.length = 8; + break; + default: + dev_err(dev, "color depth %d not supported\n", + var->bits_per_pixel); + return -EINVAL; + } + + return 0; +} + +/** + * atmel_lcdfb_set_par - Alters the hardware state. + * @info: frame buffer structure that represents a single frame buffer + * + * Using the fb_var_screeninfo in fb_info we set the resolution + * of the this particular framebuffer. This function alters the + * par AND the fb_fix_screeninfo stored in fb_info. It doesn't + * not alter var in fb_info since we are using that data. This + * means we depend on the data in var inside fb_info to be + * supported by the hardware. atmel_lcdfb_check_var is always called + * before atmel_lcdfb_set_par to ensure this. Again if you can't + * change the resolution you don't need this function. + * + */ +static int atmel_lcdfb_set_par(struct fb_info *info) +{ + struct atmel_lcdfb_info *sinfo = info->par; + unsigned long value; + unsigned long clk_value_khz; + + dev_dbg(info->device, "%s:\n", __func__); + dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", + info->var.xres, info->var.yres, + info->var.xres_virtual, info->var.yres_virtual); + + /* Turn off the LCD controller and the DMA controller */ + lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); + + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); + + if (info->var.bits_per_pixel <= 8) + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + else + info->fix.visual = FB_VISUAL_TRUECOLOR; + + info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8); + + /* Re-initialize the DMA engine... */ + dev_dbg(info->device, " * update DMA engine\n"); + atmel_lcdfb_update_dma(info, &info->var); + + /* ...set frame size and burst length = 8 words (?) */ + value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32; + value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET); + lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value); + + /* Now, the LCDC core... */ + + /* Set pixel clock */ + clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; + + value = clk_value_khz / PICOS2KHZ(info->var.pixclock); + + if (clk_value_khz % PICOS2KHZ(info->var.pixclock)) + value++; + + value = (value / 2) - 1; + + if (value <= 0) { + dev_notice(info->device, "Bypassing pixel clock divider\n"); + lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS); + } else + lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET); + + /* Initialize control register 2 */ + value = sinfo->default_lcdcon2; + + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) + value |= ATMEL_LCDC_INVLINE_INVERTED; + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) + value |= ATMEL_LCDC_INVFRAME_INVERTED; + + switch (info->var.bits_per_pixel) { + case 1: value |= ATMEL_LCDC_PIXELSIZE_1; break; + case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break; + case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break; + case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break; + case 15: /* fall through */ + case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break; + case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break; + case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break; + default: BUG(); break; + } + dev_dbg(info->device, " * LCDCON2 = %08lx\n", value); + lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value); + + /* Vertical timing */ + value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET; + value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET; + value |= info->var.lower_margin; + dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value); + lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value); + + /* Horizontal timing */ + value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET; + value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET; + value |= (info->var.left_margin - 1); + dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value); + lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); + + /* Display size */ + value = (info->var.xres - 1) << ATMEL_LCDC_HOZVAL_OFFSET; + value |= info->var.yres - 1; + lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value); + + /* FIFO Threshold: Use formula from data sheet */ + value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3); + lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value); + + /* Toggle LCD_MODE every frame */ + lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0); + + /* Disable all interrupts */ + lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); + + /* Set contrast */ + value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE; + lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value); + lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); + /* ...wait for DMA engine to become idle... */ + while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) + msleep(10); + + dev_dbg(info->device, " * re-enable DMA engine\n"); + /* ...and enable it with updated configuration */ + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); + + dev_dbg(info->device, " * re-enable LCDC core\n"); + lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, + (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); + + dev_dbg(info->device, " * DONE\n"); + + return 0; +} + +static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +/** + * atmel_lcdfb_setcolreg - Optional function. Sets a color register. + * @regno: Which register in the CLUT we are programming + * @red: The red value which can be up to 16 bits wide + * @green: The green value which can be up to 16 bits wide + * @blue: The blue value which can be up to 16 bits wide. + * @transp: If supported the alpha value which can be up to 16 bits wide. + * @info: frame buffer info structure + * + * Set a single color register. The values supplied have a 16 bit + * magnitude which needs to be scaled in this function for the hardware. + * Things to take into consideration are how many color registers, if + * any, are supported with the current color visual. With truecolor mode + * no color palettes are supported. Here a psuedo palette is created + * which we store the value in pseudo_palette in struct fb_info. For + * pseudocolor mode we have a limited color palette. To deal with this + * we can program what color is displayed for a particular pixel value. + * DirectColor is similar in that we can program each color field. If + * we have a static colormap we don't need to implement this function. + * + * Returns negative errno on error, or zero on success. In an + * ideal world, this would have been the case, but as it turns + * out, the other drivers return 1 on failure, so that's what + * we're going to do. + */ +static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) +{ + struct atmel_lcdfb_info *sinfo = info->par; + unsigned int val; + u32 *pal; + int ret = 1; + + if (info->var.grayscale) + red = green = blue = (19595 * red + 38470 * green + + 7471 * blue) >> 16; + + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + if (regno < 16) { + pal = info->pseudo_palette; + + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue, &info->var.blue); + + pal[regno] = val; + ret = 0; + } + break; + + case FB_VISUAL_PSEUDOCOLOR: + if (regno < 256) { + val = ((red >> 11) & 0x001f); + val |= ((green >> 6) & 0x03e0); + val |= ((blue >> 1) & 0x7c00); + + /* + * TODO: intensity bit. Maybe something like + * ~(red[10] ^ green[10] ^ blue[10]) & 1 + */ + + lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); + ret = 0; + } + break; + } + + return ret; +} + +static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + dev_dbg(info->device, "%s\n", __func__); + + atmel_lcdfb_update_dma(info, var); + + return 0; +} + +static struct fb_ops atmel_lcdfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = atmel_lcdfb_check_var, + .fb_set_par = atmel_lcdfb_set_par, + .fb_setcolreg = atmel_lcdfb_setcolreg, + .fb_pan_display = atmel_lcdfb_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id) +{ + struct fb_info *info = dev_id; + struct atmel_lcdfb_info *sinfo = info->par; + u32 status; + + status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); + lcdc_writel(sinfo, ATMEL_LCDC_IDR, status); + return IRQ_HANDLED; +} + +static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) +{ + struct fb_info *info = sinfo->info; + int ret = 0; + + memset_io(info->screen_base, 0, info->fix.smem_len); + info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; + + dev_info(info->device, + "%luKiB frame buffer at %08lx (mapped at %p)\n", + (unsigned long)info->fix.smem_len / 1024, + (unsigned long)info->fix.smem_start, + info->screen_base); + + /* Allocate colormap */ + ret = fb_alloc_cmap(&info->cmap, 256, 0); + if (ret < 0) + dev_err(info->device, "Alloc color map failed\n"); + + return ret; +} + +static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) +{ + if (sinfo->bus_clk) + clk_enable(sinfo->bus_clk); + clk_enable(sinfo->lcdc_clk); +} + +static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) +{ + if (sinfo->bus_clk) + clk_disable(sinfo->bus_clk); + clk_disable(sinfo->lcdc_clk); +} + + +static int __init atmel_lcdfb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct fb_info *info; + struct atmel_lcdfb_info *sinfo; + struct atmel_lcdfb_info *pdata_sinfo; + struct resource *regs = NULL; + struct resource *map = NULL; + int ret; + + dev_dbg(dev, "%s BEGIN\n", __func__); + + ret = -ENOMEM; + info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev); + if (!info) { + dev_err(dev, "cannot allocate memory\n"); + goto out; + } + + sinfo = info->par; + + if (dev->platform_data) { + pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data; + sinfo->default_bpp = pdata_sinfo->default_bpp; + sinfo->default_dmacon = pdata_sinfo->default_dmacon; + sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2; + sinfo->default_monspecs = pdata_sinfo->default_monspecs; + sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; + sinfo->guard_time = pdata_sinfo->guard_time; + } else { + dev_err(dev, "cannot get default configuration\n"); + goto free_info; + } + sinfo->info = info; + sinfo->pdev = pdev; + + strcpy(info->fix.id, sinfo->pdev->name); + info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; + info->pseudo_palette = sinfo->pseudo_palette; + info->fbops = &atmel_lcdfb_ops; + + memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs)); + info->fix = atmel_lcdfb_fix; + + /* Enable LCDC Clocks */ + if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) { + sinfo->bus_clk = clk_get(dev, "hck1"); + if (IS_ERR(sinfo->bus_clk)) { + ret = PTR_ERR(sinfo->bus_clk); + goto free_info; + } + } + sinfo->lcdc_clk = clk_get(dev, "lcdc_clk"); + if (IS_ERR(sinfo->lcdc_clk)) { + ret = PTR_ERR(sinfo->lcdc_clk); + goto put_bus_clk; + } + atmel_lcdfb_start_clock(sinfo); + + ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb, + info->monspecs.modedb_len, info->monspecs.modedb, + sinfo->default_bpp); + if (!ret) { + dev_err(dev, "no suitable video mode found\n"); + goto stop_clk; + } + + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(dev, "resources unusable\n"); + ret = -ENXIO; + goto stop_clk; + } + + sinfo->irq_base = platform_get_irq(pdev, 0); + if (sinfo->irq_base < 0) { + dev_err(dev, "unable to get irq\n"); + ret = sinfo->irq_base; + goto stop_clk; + } + + /* Initialize video memory */ + map = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (map) { + /* use a pre-allocated memory buffer */ + info->fix.smem_start = map->start; + info->fix.smem_len = map->end - map->start + 1; + if (!request_mem_region(info->fix.smem_start, + info->fix.smem_len, pdev->name)) { + ret = -EBUSY; + goto stop_clk; + } + + info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); + if (!info->screen_base) + goto release_intmem; + } else { + /* alocate memory buffer */ + ret = atmel_lcdfb_alloc_video_memory(sinfo); + if (ret < 0) { + dev_err(dev, "cannot allocate framebuffer: %d\n", ret); + goto stop_clk; + } + } + + /* LCDC registers */ + info->fix.mmio_start = regs->start; + info->fix.mmio_len = regs->end - regs->start + 1; + + if (!request_mem_region(info->fix.mmio_start, + info->fix.mmio_len, pdev->name)) { + ret = -EBUSY; + goto free_fb; + } + + sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); + if (!sinfo->mmio) { + dev_err(dev, "cannot map LCDC registers\n"); + goto release_mem; + } + + /* interrupt */ + ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); + if (ret) { + dev_err(dev, "request_irq failed: %d\n", ret); + goto unmap_mmio; + } + + ret = atmel_lcdfb_init_fbinfo(sinfo); + if (ret < 0) { + dev_err(dev, "init fbinfo failed: %d\n", ret); + goto unregister_irqs; + } + + /* + * This makes sure that our colour bitfield + * descriptors are correctly initialised. + */ + atmel_lcdfb_check_var(&info->var, info); + + ret = fb_set_var(info, &info->var); + if (ret) { + dev_warn(dev, "unable to set display parameters\n"); + goto free_cmap; + } + + dev_set_drvdata(dev, info); + + /* + * Tell the world that we're ready to go + */ + ret = register_framebuffer(info); + if (ret < 0) { + dev_err(dev, "failed to register framebuffer device: %d\n", ret); + goto free_cmap; + } + + /* Power up the LCDC screen */ + if (sinfo->atmel_lcdfb_power_control) + sinfo->atmel_lcdfb_power_control(1); + + dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n", + info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base); + + return 0; + + +free_cmap: + fb_dealloc_cmap(&info->cmap); +unregister_irqs: + free_irq(sinfo->irq_base, info); +unmap_mmio: + iounmap(sinfo->mmio); +release_mem: + release_mem_region(info->fix.mmio_start, info->fix.mmio_len); +free_fb: + if (map) + iounmap(info->screen_base); + else + atmel_lcdfb_free_video_memory(sinfo); + +release_intmem: + if (map) + release_mem_region(info->fix.smem_start, info->fix.smem_len); +stop_clk: + atmel_lcdfb_stop_clock(sinfo); + clk_put(sinfo->lcdc_clk); +put_bus_clk: + if (sinfo->bus_clk) + clk_put(sinfo->bus_clk); +free_info: + framebuffer_release(info); +out: + dev_dbg(dev, "%s FAILED\n", __func__); + return ret; +} + +static int __exit atmel_lcdfb_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct fb_info *info = dev_get_drvdata(dev); + struct atmel_lcdfb_info *sinfo = info->par; + + if (!sinfo) + return 0; + + if (sinfo->atmel_lcdfb_power_control) + sinfo->atmel_lcdfb_power_control(0); + unregister_framebuffer(info); + atmel_lcdfb_stop_clock(sinfo); + clk_put(sinfo->lcdc_clk); + if (sinfo->bus_clk) + clk_put(sinfo->bus_clk); + fb_dealloc_cmap(&info->cmap); + free_irq(sinfo->irq_base, info); + iounmap(sinfo->mmio); + release_mem_region(info->fix.mmio_start, info->fix.mmio_len); + if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) { + iounmap(info->screen_base); + release_mem_region(info->fix.smem_start, info->fix.smem_len); + } else { + atmel_lcdfb_free_video_memory(sinfo); + } + + dev_set_drvdata(dev, NULL); + framebuffer_release(info); + + return 0; +} + +static struct platform_driver atmel_lcdfb_driver = { + .remove = __exit_p(atmel_lcdfb_remove), + .driver = { + .name = "atmel_lcdfb", + .owner = THIS_MODULE, + }, +}; + +static int __init atmel_lcdfb_init(void) +{ + return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe); +} + +static void __exit atmel_lcdfb_exit(void) +{ + platform_driver_unregister(&atmel_lcdfb_driver); +} + +module_init(atmel_lcdfb_init); +module_exit(atmel_lcdfb_exit); + +MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); +MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@rfo.atmel.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h index 39ab483..90e7df2 100644 --- a/drivers/video/aty/ati_ids.h +++ b/drivers/video/aty/ati_ids.h @@ -209,4 +209,4 @@ #define PCI_CHIP_R423_5D57 0x5D57 #define PCI_CHIP_RS350_7834 0x7834 #define PCI_CHIP_RS350_7835 0x7835 - +#define PCI_CHIP_RS480_5955 0x5955 diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index e86d7e0..7fea4d8 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -2165,18 +2165,29 @@ static void __devexit aty128_remove(struct pci_dev *pdev) static int aty128fb_blank(int blank, struct fb_info *fb) { struct aty128fb_par *par = fb->par; - u8 state = 0; + u8 state; if (par->lock_blank || par->asleep) return 0; - if (blank & FB_BLANK_VSYNC_SUSPEND) - state |= 2; - if (blank & FB_BLANK_HSYNC_SUSPEND) - state |= 1; - if (blank & FB_BLANK_POWERDOWN) - state |= 4; - + switch (blank) { + case FB_BLANK_NORMAL: + state = 4; + break; + case FB_BLANK_VSYNC_SUSPEND: + state = 6; + break; + case FB_BLANK_HSYNC_SUSPEND: + state = 5; + break; + case FB_BLANK_POWERDOWN: + state = 7; + break; + case FB_BLANK_UNBLANK: + default: + state = 0; + break; + } aty_st_8(CRTC_EXT_CNTL+1, state); if (par->chip_gen == rage_M3) { @@ -2430,7 +2441,7 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) wait_for_idle(par); /* Blank display and LCD */ - aty128fb_blank(VESA_POWERDOWN, info); + aty128fb_blank(FB_BLANK_POWERDOWN, info); /* Sleep */ par->asleep = 1; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 8514f2a..8d3455d 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -80,8 +80,9 @@ #include "../macmodes.h" #endif #ifdef __sparc__ -#include <asm/pbm.h> #include <asm/fbio.h> +#include <asm/oplib.h> +#include <asm/prom.h> #endif #ifdef CONFIG_ADB_PMU @@ -2297,20 +2298,6 @@ static int __devinit aty_init(struct fb_info *info) par->pll_limits.xclk = 53; } #endif - if (pll) - par->pll_limits.pll_max = pll; - if (mclk) - par->pll_limits.mclk = mclk; - if (xclk) - par->pll_limits.xclk = xclk; - - aty_calc_mem_refresh(par, par->pll_limits.xclk); - par->pll_per = 1000000/par->pll_limits.pll_max; - par->mclk_per = 1000000/par->pll_limits.mclk; - par->xclk_per = 1000000/par->pll_limits.xclk; - - par->ref_clk_per = 1000000000000ULL / 14318180; - xtal = "14.31818"; #ifdef CONFIG_FB_ATY_GX if (!M64_HAS(INTEGRATED)) { @@ -2338,6 +2325,7 @@ static int __devinit aty_init(struct fb_info *info) case DAC_IBMRGB514: par->dac_ops = &aty_dac_ibm514; break; +#ifdef CONFIG_ATARI case DAC_ATI68860_B: case DAC_ATI68860_C: par->dac_ops = &aty_dac_ati68860b; @@ -2346,6 +2334,7 @@ static int __devinit aty_init(struct fb_info *info) case DAC_ATT21C498: par->dac_ops = &aty_dac_att21c498; break; +#endif default: PRINTKI("aty_init: DAC type not implemented yet!\n"); par->dac_ops = &aty_dac_unsupported; @@ -2389,8 +2378,29 @@ static int __devinit aty_init(struct fb_info *info) /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) par->pll_limits.mclk = 63; + /* Mobility + 32bit memory interface need halved XCLK. */ + if (M64_HAS(MOBIL_BUS) && par->ram_type == SDRAM32) + par->pll_limits.xclk = (par->pll_limits.xclk + 1) >> 1; } +#endif + /* Allow command line to override clocks. */ + if (pll) + par->pll_limits.pll_max = pll; + if (mclk) + par->pll_limits.mclk = mclk; + if (xclk) + par->pll_limits.xclk = xclk; + + aty_calc_mem_refresh(par, par->pll_limits.xclk); + par->pll_per = 1000000/par->pll_limits.pll_max; + par->mclk_per = 1000000/par->pll_limits.mclk; + par->xclk_per = 1000000/par->pll_limits.xclk; + + par->ref_clk_per = 1000000000000ULL / 14318180; + xtal = "14.31818"; + +#ifdef CONFIG_FB_ATY_CT if (M64_HAS(GTB_DSP)) { u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par); diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c index 1fdcfdb..cc9e977 100644 --- a/drivers/video/aty/mach64_ct.c +++ b/drivers/video/aty/mach64_ct.c @@ -608,12 +608,10 @@ static void aty_resume_pll_ct(const struct fb_info *info, aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par); aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par); /* - * The sclk has been started. However, I believe the first clock - * ticks it generates are not very stable. Hope this primitive loop - * helps for Rage Mobilities that sometimes crash when - * we switch to sclk. (Daniel Mantione, 13-05-2003) + * SCLK has been started. Wait for the PLL to lock. 5 ms + * should be enough according to mach64 programmer's guide. */ - udelay(500); + mdelay(5); } aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par); diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c index 2a7f381..fe2c6ad 100644 --- a/drivers/video/aty/mach64_cursor.c +++ b/drivers/video/aty/mach64_cursor.c @@ -11,7 +11,6 @@ #include <asm/uaccess.h> #ifdef __sparc__ -#include <asm/pbm.h> #include <asm/fbio.h> #endif diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index a4b3fd1..2ce0501 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -100,6 +100,8 @@ { PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) } static struct pci_device_id radeonfb_pci_table[] = { + /* Radeon Xpress 200m */ + CHIP_DEF(PCI_CHIP_RS480_5955, RS480, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), /* Mobility M6 */ CHIP_DEF(PCI_CHIP_RADEON_LY, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), CHIP_DEF(PCI_CHIP_RADEON_LZ, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), @@ -422,7 +424,7 @@ static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo) if (dp == NULL) return -ENODEV; - val = get_property(dp, "ATY,RefCLK", NULL); + val = of_get_property(dp, "ATY,RefCLK", NULL); if (!val || !*val) { printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n"); return -EINVAL; @@ -430,11 +432,11 @@ static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo) rinfo->pll.ref_clk = (*val) / 10; - val = get_property(dp, "ATY,SCLK", NULL); + val = of_get_property(dp, "ATY,SCLK", NULL); if (val && *val) rinfo->pll.sclk = (*val) / 10; - val = get_property(dp, "ATY,MCLK", NULL); + val = of_get_property(dp, "ATY,MCLK", NULL); if (val && *val) rinfo->pll.mclk = (*val) / 10; @@ -1994,7 +1996,8 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo) /* framebuffer size */ if ((rinfo->family == CHIP_FAMILY_RS100) || (rinfo->family == CHIP_FAMILY_RS200) || - (rinfo->family == CHIP_FAMILY_RS300)) { + (rinfo->family == CHIP_FAMILY_RS300) || + (rinfo->family == CHIP_FAMILY_RS480) ) { u32 tom = INREG(NB_TOM); tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 5084799..7db9de6 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c @@ -1,7 +1,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/pci.h> #include <linux/fb.h> diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c index 737b5c0..2030ed8 100644 --- a/drivers/video/aty/radeon_monitor.c +++ b/drivers/video/aty/radeon_monitor.c @@ -70,7 +70,7 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_ int i, mt = MT_NONE; RTRACE("analyzing OF properties...\n"); - pmt = get_property(dp, "display-type", NULL); + pmt = of_get_property(dp, "display-type", NULL); if (!pmt) return MT_NONE; RTRACE("display-type: %s\n", pmt); @@ -89,7 +89,7 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_ } for (i = 0; propnames[i] != NULL; ++i) { - pedid = get_property(dp, propnames[i], NULL); + pedid = of_get_property(dp, propnames[i], NULL); if (pedid != NULL) break; } @@ -98,9 +98,10 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_ * single-head cards have hdno == -1 and skip this step */ if (pedid == NULL && dp->parent && (hdno != -1)) - pedid = get_property(dp->parent, (hdno == 0) ? "EDID1" : "EDID2", NULL); + pedid = of_get_property(dp->parent, + (hdno == 0) ? "EDID1" : "EDID2", NULL); if (pedid == NULL && dp->parent && (hdno == 0)) - pedid = get_property(dp->parent, "EDID", NULL); + pedid = of_get_property(dp->parent, "EDID", NULL); if (pedid == NULL) return mt; @@ -130,7 +131,7 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_ do { if (!dp) return MT_NONE; - pname = get_property(dp, "name", NULL); + pname = of_get_property(dp, "name", NULL); if (!pname) return MT_NONE; len = strlen(pname); diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index c411293..be1d57b 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -1290,7 +1290,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo) if (rinfo->of_node != NULL) { int size; - mrtable = get_property(rinfo->of_node, "ATY,MRT", &size); + mrtable = of_get_property(rinfo->of_node, "ATY,MRT", &size); if (mrtable) mrtable_size = size >> 2; else @@ -2826,11 +2826,15 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM); /* Enable/Disable dynamic clocks: TODO add sysfs access */ - rinfo->dynclk = dynclk; - if (dynclk == 1) { + if (rinfo->family == CHIP_FAMILY_RS480) + rinfo->dynclk = -1; + else + rinfo->dynclk = dynclk; + + if (rinfo->dynclk == 1) { radeon_pm_enable_dynamic_mode(rinfo); printk("radeonfb: Dynamic Clock Power Management enabled\n"); - } else if (dynclk == 0) { + } else if (rinfo->dynclk == 0) { radeon_pm_disable_dynamic_mode(rinfo); printk("radeonfb: Dynamic Clock Power Management disabled\n"); } diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 3190003..7ebffcd 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -48,6 +48,7 @@ enum radeon_family { CHIP_FAMILY_RV350, CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */ CHIP_FAMILY_R420, /* R420/R423/M18 */ + CHIP_FAMILY_RS480, CHIP_FAMILY_LAST, }; @@ -64,7 +65,8 @@ enum radeon_family { ((rinfo)->family == CHIP_FAMILY_RV350) || \ ((rinfo)->family == CHIP_FAMILY_R350) || \ ((rinfo)->family == CHIP_FAMILY_RV380) || \ - ((rinfo)->family == CHIP_FAMILY_R420)) + ((rinfo)->family == CHIP_FAMILY_R420) || \ + ((rinfo)->family == CHIP_FAMILY_RS480) ) /* * Chip flags diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 47d15b5..fbef663 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -63,3 +63,11 @@ config BACKLIGHT_PROGEAR help If you have a Frontpath ProGear say Y to enable the backlight driver. + +config BACKLIGHT_CARILLO_RANCH + tristate "Intel Carillo Ranch Backlight Driver" + depends on BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 + default n + help + If you have a Intel LE80578 (Carillo Ranch) say Y to enable the + backlight driver. diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 0c3ce46..c6e2266 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o +obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c new file mode 100644 index 0000000..e9bbc34 --- /dev/null +++ b/drivers/video/backlight/cr_bllcd.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * This file is part of the Carillo Ranch video subsystem driver. + * The Carillo Ranch video subsystem driver is free software; + * you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The Carillo Ranch video subsystem driver is distributed + * in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this driver; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> + * Alan Hourihane <alanh-at-tungstengraphics-dot-com> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/mutex.h> +#include <linux/fb.h> +#include <linux/backlight.h> +#include <linux/lcd.h> +#include <linux/pci.h> +#include <asm/uaccess.h> + +/* The LVDS- and panel power controls sits on the + * GPIO port of the ISA bridge. + */ + +#define CRVML_DEVICE_LPC 0x27B8 +#define CRVML_REG_GPIOBAR 0x48 +#define CRVML_REG_GPIOEN 0x4C +#define CRVML_GPIOEN_BIT (1 << 4) +#define CRVML_PANEL_PORT 0x38 +#define CRVML_LVDS_ON 0x00000001 +#define CRVML_PANEL_ON 0x00000002 +#define CRVML_BACKLIGHT_OFF 0x00000004 + +/* The PLL Clock register sits on Host bridge */ +#define CRVML_DEVICE_MCH 0x5001 +#define CRVML_REG_MCHBAR 0x44 +#define CRVML_REG_MCHEN 0x54 +#define CRVML_MCHEN_BIT (1 << 28) +#define CRVML_MCHMAP_SIZE 4096 +#define CRVML_REG_CLOCK 0xc3c +#define CRVML_CLOCK_SHIFT 8 +#define CRVML_CLOCK_MASK 0x00000f00 + +static struct pci_dev *lpc_dev; +static u32 gpio_bar; + +struct cr_panel { + struct backlight_device *cr_backlight_device; + struct lcd_device *cr_lcd_device; +}; + +static int cr_backlight_set_intensity(struct backlight_device *bd) +{ + int intensity = bd->props.brightness; + u32 addr = gpio_bar + CRVML_PANEL_PORT; + u32 cur = inl(addr); + + if (bd->props.power == FB_BLANK_UNBLANK) + intensity = FB_BLANK_UNBLANK; + if (bd->props.fb_blank == FB_BLANK_UNBLANK) + intensity = FB_BLANK_UNBLANK; + if (bd->props.power == FB_BLANK_POWERDOWN) + intensity = FB_BLANK_POWERDOWN; + if (bd->props.fb_blank == FB_BLANK_POWERDOWN) + intensity = FB_BLANK_POWERDOWN; + + if (intensity == FB_BLANK_UNBLANK) { /* FULL ON */ + cur &= ~CRVML_BACKLIGHT_OFF; + outl(cur, addr); + } else if (intensity == FB_BLANK_POWERDOWN) { /* OFF */ + cur |= CRVML_BACKLIGHT_OFF; + outl(cur, addr); + } /* anything else, don't bother */ + + return 0; +} + +static int cr_backlight_get_intensity(struct backlight_device *bd) +{ + u32 addr = gpio_bar + CRVML_PANEL_PORT; + u32 cur = inl(addr); + u8 intensity; + + if (cur & CRVML_BACKLIGHT_OFF) + intensity = FB_BLANK_POWERDOWN; + else + intensity = FB_BLANK_UNBLANK; + + return intensity; +} + +static struct backlight_ops cr_backlight_ops = { + .get_brightness = cr_backlight_get_intensity, + .update_status = cr_backlight_set_intensity, +}; + +static void cr_panel_on(void) +{ + u32 addr = gpio_bar + CRVML_PANEL_PORT; + u32 cur = inl(addr); + + if (!(cur & CRVML_PANEL_ON)) { + /* Make sure LVDS controller is down. */ + if (cur & 0x00000001) { + cur &= ~CRVML_LVDS_ON; + outl(cur, addr); + } + /* Power up Panel */ + schedule_timeout(HZ / 10); + cur |= CRVML_PANEL_ON; + outl(cur, addr); + } + + /* Power up LVDS controller */ + + if (!(cur & CRVML_LVDS_ON)) { + schedule_timeout(HZ / 10); + outl(cur | CRVML_LVDS_ON, addr); + } +} + +static void cr_panel_off(void) +{ + u32 addr = gpio_bar + CRVML_PANEL_PORT; + u32 cur = inl(addr); + + /* Power down LVDS controller first to avoid high currents */ + if (cur & CRVML_LVDS_ON) { + cur &= ~CRVML_LVDS_ON; + outl(cur, addr); + } + if (cur & CRVML_PANEL_ON) { + schedule_timeout(HZ / 10); + outl(cur & ~CRVML_PANEL_ON, addr); + } +} + +static int cr_lcd_set_power(struct lcd_device *ld, int power) +{ + if (power == FB_BLANK_UNBLANK) + cr_panel_on(); + if (power == FB_BLANK_POWERDOWN) + cr_panel_off(); + + return 0; +} + +static struct lcd_ops cr_lcd_ops = { + .set_power = cr_lcd_set_power, +}; + +static int cr_backlight_probe(struct platform_device *pdev) +{ + struct cr_panel *crp; + u8 dev_en; + + crp = kzalloc(sizeof(crp), GFP_KERNEL); + if (crp == NULL) + return -ENOMEM; + + lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL, + CRVML_DEVICE_LPC, NULL); + if (!lpc_dev) { + printk("INTEL CARILLO RANCH LPC not found.\n"); + return -ENODEV; + } + + pci_read_config_byte(lpc_dev, CRVML_REG_GPIOEN, &dev_en); + if (!(dev_en & CRVML_GPIOEN_BIT)) { + printk(KERN_ERR + "Carillo Ranch GPIO device was not enabled.\n"); + pci_dev_put(lpc_dev); + return -ENODEV; + } + + crp->cr_backlight_device = backlight_device_register("cr-backlight", + &pdev->dev, NULL, + &cr_backlight_ops); + if (IS_ERR(crp->cr_backlight_device)) { + pci_dev_put(lpc_dev); + return PTR_ERR(crp->cr_backlight_device); + } + + crp->cr_lcd_device = lcd_device_register("cr-lcd", + &pdev->dev, + &cr_lcd_ops); + + if (IS_ERR(crp->cr_lcd_device)) { + pci_dev_put(lpc_dev); + return PTR_ERR(crp->cr_backlight_device); + } + + pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR, + &gpio_bar); + gpio_bar &= ~0x3F; + + crp->cr_backlight_device->props.power = FB_BLANK_UNBLANK; + crp->cr_backlight_device->props.brightness = 0; + crp->cr_backlight_device->props.max_brightness = 0; + cr_backlight_set_intensity(crp->cr_backlight_device); + + cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_UNBLANK); + + platform_set_drvdata(pdev, crp); + + return 0; +} + +static int cr_backlight_remove(struct platform_device *pdev) +{ + struct cr_panel *crp = platform_get_drvdata(pdev); + crp->cr_backlight_device->props.power = FB_BLANK_POWERDOWN; + crp->cr_backlight_device->props.brightness = 0; + crp->cr_backlight_device->props.max_brightness = 0; + cr_backlight_set_intensity(crp->cr_backlight_device); + cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_POWERDOWN); + backlight_device_unregister(crp->cr_backlight_device); + lcd_device_unregister(crp->cr_lcd_device); + pci_dev_put(lpc_dev); + + return 0; +} + +static struct platform_driver cr_backlight_driver = { + .probe = cr_backlight_probe, + .remove = cr_backlight_remove, + .driver = { + .name = "cr_backlight", + }, +}; + +static struct platform_device *crp; + +static int __init cr_backlight_init(void) +{ + int ret = platform_driver_register(&cr_backlight_driver); + + if (!ret) { + crp = platform_device_alloc("cr_backlight", -1); + if (!crp) + return -ENOMEM; + + ret = platform_device_add(crp); + + if (ret) { + platform_device_put(crp); + platform_driver_unregister(&cr_backlight_driver); + } + } + + printk("Carillo Ranch Backlight Driver Initialized.\n"); + + return ret; +} + +static void __exit cr_backlight_exit(void) +{ + platform_device_unregister(crp); + platform_driver_unregister(&cr_backlight_driver); +} + +module_init(cr_backlight_init); +module_exit(cr_backlight_exit); + +MODULE_AUTHOR("Tungsten Graphics Inc."); +MODULE_DESCRIPTION("Carillo Ranch Backlight Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c index 6faea40..032210f 100644 --- a/drivers/video/cfbcopyarea.c +++ b/drivers/video/cfbcopyarea.c @@ -22,8 +22,6 @@ * help moving some redundant computations and branches out of the loop, too. */ - - #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> @@ -31,6 +29,7 @@ #include <linux/slab.h> #include <asm/types.h> #include <asm/io.h> +#include "fb_draw.h" #if BITS_PER_LONG == 32 # define FB_WRITEL fb_writel @@ -41,17 +40,6 @@ #endif /* - * Compose two values, using a bitmask as decision value - * This is equivalent to (a & mask) | (b & ~mask) - */ - -static inline unsigned long -comp(unsigned long a, unsigned long b, unsigned long mask) -{ - return ((a ^ b) & mask) ^ b; -} - - /* * Generic bitwise copy algorithm */ diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c index f00b50a..71623b4 100644 --- a/drivers/video/cfbfillrect.c +++ b/drivers/video/cfbfillrect.c @@ -21,6 +21,7 @@ #include <linux/string.h> #include <linux/fb.h> #include <asm/types.h> +#include "fb_draw.h" #if BITS_PER_LONG == 32 # define FB_WRITEL fb_writel @@ -31,73 +32,6 @@ #endif /* - * Compose two values, using a bitmask as decision value - * This is equivalent to (a & mask) | (b & ~mask) - */ - -static inline unsigned long -comp(unsigned long a, unsigned long b, unsigned long mask) -{ - return ((a ^ b) & mask) ^ b; -} - - /* - * Create a pattern with the given pixel's color - */ - -#if BITS_PER_LONG == 64 -static inline unsigned long -pixel_to_pat( u32 bpp, u32 pixel) -{ - switch (bpp) { - case 1: - return 0xfffffffffffffffful*pixel; - case 2: - return 0x5555555555555555ul*pixel; - case 4: - return 0x1111111111111111ul*pixel; - case 8: - return 0x0101010101010101ul*pixel; - case 12: - return 0x0001001001001001ul*pixel; - case 16: - return 0x0001000100010001ul*pixel; - case 24: - return 0x0000000001000001ul*pixel; - case 32: - return 0x0000000100000001ul*pixel; - default: - panic("pixel_to_pat(): unsupported pixelformat\n"); - } -} -#else -static inline unsigned long -pixel_to_pat( u32 bpp, u32 pixel) -{ - switch (bpp) { - case 1: - return 0xfffffffful*pixel; - case 2: - return 0x55555555ul*pixel; - case 4: - return 0x11111111ul*pixel; - case 8: - return 0x01010101ul*pixel; - case 12: - return 0x00001001ul*pixel; - case 16: - return 0x00010001ul*pixel; - case 24: - return 0x00000001ul*pixel; - case 32: - return 0x00000001ul*pixel; - default: - panic("pixel_to_pat(): unsupported pixelformat\n"); - } -} -#endif - - /* * Aligned pattern fill using 32/64-bit memory accesses */ diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 2c4bc62..8269d70 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -98,15 +98,6 @@ #define assert(expr) #endif -#ifdef TRUE -#undef TRUE -#endif -#ifdef FALSE -#undef FALSE -#endif -#define TRUE 1 -#define FALSE 0 - #define MB_ (1024*1024) #define KB_ (1024) @@ -146,9 +137,9 @@ static const struct cirrusfb_board_info_rec { char *name; /* ASCII name of chipset */ long maxclock[5]; /* maximum video clock */ /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */ - unsigned init_sr07 : 1; /* init SR07 during init_vgachip() */ - unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */ - unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */ + bool init_sr07 : 1; /* init SR07 during init_vgachip() */ + bool init_sr1f : 1; /* write SR1F during init_vgachip() */ + bool scrn_start_bit19 : 1; /* construct bit 19 of screen start address */ /* initial SR07 value, then for each mode */ unsigned char sr07; @@ -166,9 +157,9 @@ static const struct cirrusfb_board_info_rec { /* the SD64/P4 have a higher max. videoclock */ 140000, 140000, 140000, 140000, 140000, }, - .init_sr07 = TRUE, - .init_sr1f = TRUE, - .scrn_start_bit19 = TRUE, + .init_sr07 = true, + .init_sr1f = true, + .scrn_start_bit19 = true, .sr07 = 0xF0, .sr07_1bpp = 0xF0, .sr07_8bpp = 0xF1, @@ -180,9 +171,9 @@ static const struct cirrusfb_board_info_rec { /* guess */ 90000, 90000, 90000, 90000, 90000 }, - .init_sr07 = TRUE, - .init_sr1f = TRUE, - .scrn_start_bit19 = FALSE, + .init_sr07 = true, + .init_sr1f = true, + .scrn_start_bit19 = false, .sr07 = 0x80, .sr07_1bpp = 0x80, .sr07_8bpp = 0x81, @@ -194,9 +185,9 @@ static const struct cirrusfb_board_info_rec { /* guess */ 90000, 90000, 90000, 90000, 90000 }, - .init_sr07 = TRUE, - .init_sr1f = TRUE, - .scrn_start_bit19 = FALSE, + .init_sr07 = true, + .init_sr1f = true, + .scrn_start_bit19 = false, .sr07 = 0x20, .sr07_1bpp = 0x20, .sr07_8bpp = 0x21, @@ -208,9 +199,9 @@ static const struct cirrusfb_board_info_rec { /* guess */ 90000, 90000, 90000, 90000, 90000 }, - .init_sr07 = TRUE, - .init_sr1f = TRUE, - .scrn_start_bit19 = FALSE, + .init_sr07 = true, + .init_sr1f = true, + .scrn_start_bit19 = false, .sr07 = 0x80, .sr07_1bpp = 0x80, .sr07_8bpp = 0x81, @@ -221,9 +212,9 @@ static const struct cirrusfb_board_info_rec { .maxclock = { 135100, 135100, 85500, 85500, 0 }, - .init_sr07 = TRUE, - .init_sr1f = FALSE, - .scrn_start_bit19 = TRUE, + .init_sr07 = true, + .init_sr1f = false, + .scrn_start_bit19 = true, .sr07 = 0x20, .sr07_1bpp = 0x20, .sr07_8bpp = 0x21, @@ -235,9 +226,9 @@ static const struct cirrusfb_board_info_rec { /* for the GD5430. GD5446 can do more... */ 85500, 85500, 50000, 28500, 0 }, - .init_sr07 = TRUE, - .init_sr1f = TRUE, - .scrn_start_bit19 = TRUE, + .init_sr07 = true, + .init_sr1f = true, + .scrn_start_bit19 = true, .sr07 = 0xA0, .sr07_1bpp = 0xA1, .sr07_1bpp_mux = 0xA7, @@ -250,9 +241,9 @@ static const struct cirrusfb_board_info_rec { .maxclock = { 135100, 200000, 200000, 135100, 135100 }, - .init_sr07 = TRUE, - .init_sr1f = TRUE, - .scrn_start_bit19 = TRUE, + .init_sr07 = true, + .init_sr1f = true, + .scrn_start_bit19 = true, .sr07 = 0x10, .sr07_1bpp = 0x11, .sr07_8bpp = 0x11, @@ -264,9 +255,9 @@ static const struct cirrusfb_board_info_rec { /* guess */ 135100, 135100, 135100, 135100, 135100, }, - .init_sr07 = FALSE, - .init_sr1f = FALSE, - .scrn_start_bit19 = TRUE, + .init_sr07 = false, + .init_sr1f = false, + .scrn_start_bit19 = true, } }; @@ -815,7 +806,7 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, default: DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel); - assert (FALSE); + assert(false); /* should never occur */ break; } @@ -886,7 +877,7 @@ static int cirrusfb_decode_var (const struct fb_var_screeninfo *var, default: DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel); - assert (FALSE); + assert(false); /* should never occur */ break; } @@ -3203,7 +3194,7 @@ void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_clas break; default: /* should never occur */ - assert (FALSE); + assert(false); break; } diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index aa3935d..63b85bf 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -19,13 +19,6 @@ config VGA_CONSOLE Say Y. -# if [ "$CONFIG_PCI" = "y" -a "$CONFIG_VGA_CONSOLE" = "y" ]; then -# bool ' Allow VGA on any bus?' CONFIG_VGA_HOSE -# if [ "$CONFIG_VGA_HOSE" = "y" ]; then -# define_bool CONFIG_DUMMY_CONSOLE y -# fi -# fi - config VGACON_SOFT_SCROLLBACK bool "Enable Scrollback Buffer in System RAM" depends on VGA_CONSOLE diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 0429fd2..73813c6 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -107,7 +107,9 @@ 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]; +#ifndef MODULE static int logo_height; +#endif static int logo_lines; /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO enums. */ @@ -576,6 +578,13 @@ static int fbcon_takeover(int show_logo) return err; } +#ifdef MODULE +static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, + int cols, int rows, int new_cols, int new_rows) +{ + logo_shown = FBCON_LOGO_DONTSHOW; +} +#else static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, int cols, int rows, int new_cols, int new_rows) { @@ -584,6 +593,11 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, int cnt, erase = vc->vc_video_erase_char, step; unsigned short *save = NULL, *r, *q; + if (info->flags & FBINFO_MODULE) { + logo_shown = FBCON_LOGO_DONTSHOW; + return; + } + /* * remove underline attribute from erase character * if black and white framebuffer. @@ -618,8 +632,13 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, r -= cols; } if (!save) { - vc->vc_y += logo_lines; - vc->vc_pos += logo_lines * vc->vc_size_row; + int lines; + if (vc->vc_y + logo_lines >= rows) + lines = rows - vc->vc_y - 1; + else + lines = logo_lines; + vc->vc_y += lines; + vc->vc_pos += lines * vc->vc_size_row; } } scr_memsetw((unsigned short *) vc->vc_origin, @@ -650,6 +669,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, vc->vc_top = logo_lines; } } +#endif /* MODULE */ #ifdef CONFIG_FB_TILEBLITTING static void set_blitting_type(struct vc_data *vc, struct fb_info *info) @@ -665,6 +685,17 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info) fbcon_set_bitops(ops); } } + +static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount) +{ + int err = 0; + + if (info->flags & FBINFO_MISC_TILEBLITTING && + info->tileops->fb_get_tilemax(info) < charcount) + err = 1; + + return err; +} #else static void set_blitting_type(struct vc_data *vc, struct fb_info *info) { @@ -675,6 +706,12 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info) fbcon_set_rotation(info); fbcon_set_bitops(ops); } + +static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount) +{ + return 0; +} + #endif /* CONFIG_MISC_TILEBLITTING */ @@ -968,7 +1005,9 @@ static const char *fbcon_startup(void) if (!p->fontdata) { if (!fontname[0] || !(font = find_font(fontname))) font = get_default_font(info->var.xres, - info->var.yres); + info->var.yres, + info->pixmap.blit_x, + info->pixmap.blit_y); vc->vc_font.width = font->width; vc->vc_font.height = font->height; vc->vc_font.data = (void *)(p->fontdata = font->data); @@ -1088,7 +1127,9 @@ static void fbcon_init(struct vc_data *vc, int init) if (!fontname[0] || !(font = find_font(fontname))) font = get_default_font(info->var.xres, - info->var.yres); + info->var.yres, + info->pixmap.blit_x, + info->pixmap.blit_y); vc->vc_font.width = font->width; vc->vc_font.height = font->height; vc->vc_font.data = (void *)(p->fontdata = font->data); @@ -1305,7 +1346,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode) int y; int c = scr_readw((u16 *) vc->vc_pos); - if (fbcon_is_inactive(vc, info)) + if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1) return; ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1; @@ -2475,6 +2516,7 @@ static int fbcon_copy_font(struct vc_data *vc, int con) static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigned flags) { + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; unsigned charcount = font->charcount; int w = font->width; int h = font->height; @@ -2488,6 +2530,15 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne if (charcount != 256 && charcount != 512) return -EINVAL; + /* Make sure drawing engine can handle the font */ + if (!(info->pixmap.blit_x & (1 << (font->width - 1))) || + !(info->pixmap.blit_y & (1 << (font->height - 1)))) + return -EINVAL; + + /* Make sure driver can handle the font length */ + if (fbcon_invalid_charcount(info, charcount)) + return -EINVAL; + size = h * pitch * charcount; new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER); @@ -2532,7 +2583,8 @@ static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, cha const struct font_desc *f; if (!name) - f = get_default_font(info->var.xres, info->var.yres); + f = get_default_font(info->var.xres, info->var.yres, + info->pixmap.blit_x, info->pixmap.blit_y); else if (!(f = find_font(name))) return -ENOENT; @@ -2829,7 +2881,7 @@ static void fbcon_set_all_vcs(struct fb_info *info) struct fbcon_ops *ops = info->fbcon_par; struct vc_data *vc; struct display *p; - int i, rows, cols; + int i, rows, cols, fg = -1; if (!ops || ops->currcon < 0) return; @@ -2840,34 +2892,23 @@ static void fbcon_set_all_vcs(struct fb_info *info) registered_fb[con2fb_map[i]] != info) continue; + if (CON_IS_VISIBLE(vc)) { + fg = i; + continue; + } + p = &fb_display[vc->vc_num]; set_blitting_type(vc, info); var_to_display(p, &info->var, info); - cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(p->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; - - if (!fbcon_is_inactive(vc, 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) - fbcon_update_softback(vc); - } } - ops->p = &fb_display[ops->currcon]; + if (fg != -1) + fbcon_modechanged(info); } static int fbcon_mode_deleted(struct fb_info *info, @@ -3002,6 +3043,42 @@ static void fbcon_new_modelist(struct fb_info *info) } } +static void fbcon_get_requirement(struct fb_info *info, + struct fb_blit_caps *caps) +{ + struct vc_data *vc; + struct display *p; + + if (caps->flags) { + int i, charcnt; + + for (i = first_fb_vc; i <= last_fb_vc; i++) { + vc = vc_cons[i].d; + if (vc && vc->vc_mode == KD_TEXT && + info->node == con2fb_map[i]) { + p = &fb_display[i]; + caps->x |= 1 << (vc->vc_font.width - 1); + caps->y |= 1 << (vc->vc_font.height - 1); + charcnt = (p->userfont) ? + FNTCHARCNT(p->fontdata) : 256; + if (caps->len < charcnt) + caps->len = charcnt; + } + } + } else { + vc = vc_cons[fg_console].d; + + if (vc && vc->vc_mode == KD_TEXT && + info->node == con2fb_map[fg_console]) { + p = &fb_display[fg_console]; + caps->x = 1 << (vc->vc_font.width - 1); + caps->y = 1 << (vc->vc_font.height - 1); + caps->len = (p->userfont) ? + FNTCHARCNT(p->fontdata) : 256; + } + } +} + static int fbcon_event_notify(struct notifier_block *self, unsigned long action, void *data) { @@ -3009,6 +3086,7 @@ static int fbcon_event_notify(struct notifier_block *self, struct fb_info *info = event->info; struct fb_videomode *mode; struct fb_con2fbmap *con2fb; + struct fb_blit_caps *caps; int ret = 0; /* @@ -3057,6 +3135,10 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_NEW_MODELIST: fbcon_new_modelist(info); break; + case FB_EVENT_GET_REQ: + caps = event->data; + fbcon_get_requirement(info, caps); + break; } done: diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index c960728..a6828d0 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c @@ -98,6 +98,8 @@ const struct font_desc *find_font(const char *name) * get_default_font - get default font * @xres: screen size of X * @yres: screen size of Y + * @font_w: bit array of supported widths (1 - 32) + * @font_h: bit array of supported heights (1 - 32) * * Get the default font for a specified screen size. * Dimensions are in pixels. @@ -107,7 +109,8 @@ const struct font_desc *find_font(const char *name) * */ -const struct font_desc *get_default_font(int xres, int yres) +const struct font_desc *get_default_font(int xres, int yres, u32 font_w, + u32 font_h) { int i, c, cc; const struct font_desc *f, *g; @@ -129,6 +132,11 @@ const struct font_desc *get_default_font(int xres, int yres) #endif if ((yres < 400) == (f->height <= 8)) c += 1000; + + if (!(font_w & (1 << (f->width - 1))) || + !(font_w & (1 << (f->height - 1)))) + c += 1000; + if (c > cc) { cc = c; g = f; diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 124ecbe..bd8d995 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -384,7 +384,7 @@ static inline u16 mda_convert_attr(u16 ch) } static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, - u8 blink, u8 underline, u8 reverse) + u8 blink, u8 underline, u8 reverse, u8 italic) { /* The attribute is just a bit vector: * @@ -397,6 +397,7 @@ static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, return (intensity & 3) | ((underline & 1) << 2) | ((reverse & 1) << 3) | + (!!italic << 4) | ((blink & 1) << 7); } diff --git a/drivers/video/console/promcon.c b/drivers/video/console/promcon.c index b78eac6..ae02e4e 100644 --- a/drivers/video/console/promcon.c +++ b/drivers/video/console/promcon.c @@ -548,7 +548,8 @@ promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count) } #if !(PROMCON_COLOR) -static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse) +static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity, + u8 _blink, u8 _underline, u8 _reverse, u8 _italic) { return (_reverse) ? 0xf : 0x7; } diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c index f577bd8..03cfb7a 100644 --- a/drivers/video/console/softcursor.c +++ b/drivers/video/console/softcursor.c @@ -1,5 +1,5 @@ /* - * linux/drivers/video/softcursor.c + * linux/drivers/video/console/softcursor.c * * Generic software cursor for frame buffer devices * diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 57b21e5..67a682d 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -314,7 +314,7 @@ static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, } static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, - u8 blink, u8 underline, u8 reverse) + u8 blink, u8 underline, u8 reverse, u8 italic) { u8 attr = ((color & 0x70) >> 1) | ((color & 7)); diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 88e7038..717b360 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -495,7 +495,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) return NULL; fbfont = find_font(fbfont_name); if (!fbfont) - fbfont = get_default_font(1024,768); + fbfont = get_default_font(1024,768, ~(u32)0, ~(u32)0); if (!fbfont) return NULL; diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 91a2078..2460b82 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -86,8 +86,6 @@ static int vgacon_set_origin(struct vc_data *c); static void vgacon_save_screen(struct vc_data *c); static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines); -static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, - u8 blink, u8 underline, u8 reverse); static void vgacon_invert_region(struct vc_data *c, u16 * p, int count); static unsigned long vgacon_uni_pagedir[2]; @@ -371,7 +369,8 @@ static const char *vgacon_startup(void) } /* VGA16 modes are not handled by VGACON */ - if ((ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */ + if ((ORIG_VIDEO_MODE == 0x00) || /* SCREEN_INFO not initialized */ + (ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */ (ORIG_VIDEO_MODE == 0x0E) || /* 640x200/4 */ (ORIG_VIDEO_MODE == 0x10) || /* 640x350/4 */ (ORIG_VIDEO_MODE == 0x12) || /* 640x480/4 */ @@ -577,12 +576,14 @@ static void vgacon_deinit(struct vc_data *c) } static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, - u8 blink, u8 underline, u8 reverse) + u8 blink, u8 underline, u8 reverse, u8 italic) { u8 attr = color; if (vga_can_do_color) { - if (underline) + if (italic) + attr = (attr & 0xF0) | c->vc_itcolor; + else if (underline) attr = (attr & 0xf0) | c->vc_ulcolor; else if (intensity == 0) attr = (attr & 0xf0) | c->vc_halfcolor; @@ -596,7 +597,9 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, if (intensity == 2) attr ^= 0x08; if (!vga_can_do_color) { - if (underline) + if (italic) + attr = (attr & 0xF8) | 0x02; + else if (underline) attr = (attr & 0xf8) | 0x01; else if (intensity == 0) attr = (attr & 0xf0) | 0x08; @@ -657,6 +660,9 @@ static void vgacon_set_cursor_size(int xpos, int from, int to) static void vgacon_cursor(struct vc_data *c, int mode) { + if (c->vc_mode != KD_TEXT) + return; + vgacon_restore_screen(c); switch (mode) { @@ -1315,7 +1321,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, unsigned long oldo; unsigned int delta; - if (t || b != c->vc_rows || vga_is_gfx) + if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT) return 0; if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2) diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig new file mode 100644 index 0000000..f99af93 --- /dev/null +++ b/drivers/video/display/Kconfig @@ -0,0 +1,24 @@ +# +# Display drivers configuration +# + +menu "Display device support" + +config DISPLAY_SUPPORT + tristate "Display panel/monitor support" + ---help--- + This framework adds support for low-level control of a display. + This includes support for power. + + Enable this to be able to choose the drivers for controlling the + physical display panel/monitor on some platforms. This not only + covers LCD displays for PDAs but also other types of displays + such as CRT, TVout etc. + + To have support for your specific display panel you will have to + select the proper drivers which depend on this option. + +comment "Display hardware drivers" + depends on DISPLAY_SUPPORT + +endmenu diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile new file mode 100644 index 0000000..c0ea832 --- /dev/null +++ b/drivers/video/display/Makefile @@ -0,0 +1,6 @@ +# Display drivers + +display-objs := display-sysfs.o + +obj-$(CONFIG_DISPLAY_SUPPORT) += display.o + diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c new file mode 100644 index 0000000..3547717 --- /dev/null +++ b/drivers/video/display/display-sysfs.c @@ -0,0 +1,217 @@ +/* + * display-sysfs.c - Display output driver sysfs interface + * + * Copyright (C) 2007 James Simmons <jsimmons@infradead.org> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include <linux/module.h> +#include <linux/display.h> +#include <linux/ctype.h> +#include <linux/idr.h> +#include <linux/err.h> + +static ssize_t display_show_name(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct display_device *dsp = dev_get_drvdata(dev); + return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name); +} + +static ssize_t display_show_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct display_device *dsp = dev_get_drvdata(dev); + return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type); +} + +static ssize_t display_show_contrast(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct display_device *dsp = dev_get_drvdata(dev); + ssize_t rc = -ENXIO; + + mutex_lock(&dsp->lock); + if (likely(dsp->driver) && dsp->driver->get_contrast) + rc = sprintf(buf, "%d\n", dsp->driver->get_contrast(dsp)); + mutex_unlock(&dsp->lock); + return rc; +} + +static ssize_t display_store_contrast(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct display_device *dsp = dev_get_drvdata(dev); + ssize_t ret = -EINVAL, size; + int contrast; + char *endp; + + contrast = simple_strtoul(buf, &endp, 0); + size = endp - buf; + + if (*endp && isspace(*endp)) + size++; + + if (size != count) + return ret; + + mutex_lock(&dsp->lock); + if (likely(dsp->driver && dsp->driver->set_contrast)) { + pr_debug("display: set contrast to %d\n", contrast); + dsp->driver->set_contrast(dsp, contrast); + ret = count; + } + mutex_unlock(&dsp->lock); + return ret; +} + +static ssize_t display_show_max_contrast(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct display_device *dsp = dev_get_drvdata(dev); + ssize_t rc = -ENXIO; + + mutex_lock(&dsp->lock); + if (likely(dsp->driver)) + rc = sprintf(buf, "%d\n", dsp->driver->max_contrast); + mutex_unlock(&dsp->lock); + return rc; +} + +static struct device_attribute display_attrs[] = { + __ATTR(name, S_IRUGO, display_show_name, NULL), + __ATTR(type, S_IRUGO, display_show_type, NULL), + __ATTR(contrast, S_IRUGO | S_IWUSR, display_show_contrast, display_store_contrast), + __ATTR(max_contrast, S_IRUGO, display_show_max_contrast, NULL), +}; + +static int display_suspend(struct device *dev, pm_message_t state) +{ + struct display_device *dsp = dev_get_drvdata(dev); + + mutex_lock(&dsp->lock); + if (likely(dsp->driver->suspend)) + dsp->driver->suspend(dsp, state); + mutex_unlock(&dsp->lock); + return 0; +}; + +static int display_resume(struct device *dev) +{ + struct display_device *dsp = dev_get_drvdata(dev); + + mutex_lock(&dsp->lock); + if (likely(dsp->driver->resume)) + dsp->driver->resume(dsp); + mutex_unlock(&dsp->lock); + return 0; +}; + +static struct mutex allocated_dsp_lock; +static DEFINE_IDR(allocated_dsp); +static struct class *display_class; + +struct display_device *display_device_register(struct display_driver *driver, + struct device *parent, void *devdata) +{ + struct display_device *new_dev = NULL; + int ret = -EINVAL; + + if (unlikely(!driver)) + return ERR_PTR(ret); + + mutex_lock(&allocated_dsp_lock); + ret = idr_pre_get(&allocated_dsp, GFP_KERNEL); + mutex_unlock(&allocated_dsp_lock); + if (!ret) + return ERR_PTR(ret); + + new_dev = kzalloc(sizeof(struct display_device), GFP_KERNEL); + if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) { + // Reserve the index for this display + mutex_lock(&allocated_dsp_lock); + ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx); + mutex_unlock(&allocated_dsp_lock); + + if (!ret) { + new_dev->dev = device_create(display_class, parent, 0, + "display%d", new_dev->idx); + if (!IS_ERR(new_dev->dev)) { + dev_set_drvdata(new_dev->dev, new_dev); + new_dev->parent = parent; + new_dev->driver = driver; + mutex_init(&new_dev->lock); + return new_dev; + } + mutex_lock(&allocated_dsp_lock); + idr_remove(&allocated_dsp, new_dev->idx); + mutex_unlock(&allocated_dsp_lock); + ret = -EINVAL; + } + } + kfree(new_dev); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(display_device_register); + +void display_device_unregister(struct display_device *ddev) +{ + if (!ddev) + return; + // Free device + mutex_lock(&ddev->lock); + device_unregister(ddev->dev); + mutex_unlock(&ddev->lock); + // Mark device index as avaliable + mutex_lock(&allocated_dsp_lock); + idr_remove(&allocated_dsp, ddev->idx); + mutex_unlock(&allocated_dsp_lock); + kfree(ddev); +} +EXPORT_SYMBOL(display_device_unregister); + +static int __init display_class_init(void) +{ + display_class = class_create(THIS_MODULE, "display"); + if (IS_ERR(display_class)) { + printk(KERN_ERR "Failed to create display class\n"); + display_class = NULL; + return -EINVAL; + } + display_class->dev_attrs = display_attrs; + display_class->suspend = display_suspend; + display_class->resume = display_resume; + mutex_init(&allocated_dsp_lock); + return 0; +} + +static void __exit display_class_exit(void) +{ + class_destroy(display_class); +} + +module_init(display_class_init); +module_exit(display_class_exit); + +MODULE_DESCRIPTION("Display Hardware handling"); +MODULE_AUTHOR("James Simmons <jsimmons@infradead.org>"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 29e07c1..ca2c54c 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -403,17 +403,10 @@ static inline unsigned long copy_to_user16(void *to, const void *from, static ssize_t -epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos) +epson1355fb_read(struct fb_info *info, char *buf, size_t count, loff_t * ppos) { - struct inode *inode = file->f_path.dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info = registered_fb[fbidx]; unsigned long p = *ppos; - /* from fbmem.c except for our own copy_*_user */ - if (!info || !info->screen_base) - return -ENODEV; - if (p >= info->fix.smem_len) return 0; if (count >= info->fix.smem_len) @@ -434,20 +427,13 @@ epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos) } static ssize_t -epson1355fb_write(struct file *file, const char *buf, +epson1355fb_write(struct fb_info *info, const char *buf, size_t count, loff_t * ppos) { - struct inode *inode = file->f_path.dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info = registered_fb[fbidx]; unsigned long p = *ppos; int err; /* from fbmem.c except for our own copy_*_user */ - if (!info || !info->screen_base) - return -ENODEV; - - /* from fbmem.c except for our own copy_*_user */ if (p > info->fix.smem_len) return -ENOSPC; if (count >= info->fix.smem_len) @@ -650,9 +636,10 @@ int __init epson1355fb_probe(struct platform_device *dev) } info = framebuffer_alloc(sizeof(struct epson1355_par) + sizeof(u32) * 256, &dev->dev); - if (!info) + if (!info) { rc = -ENOMEM; goto bail; + } default_par = info->par; default_par->reg_addr = (unsigned long) ioremap(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN); diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c new file mode 100644 index 0000000..1a8643f --- /dev/null +++ b/drivers/video/fb_defio.c @@ -0,0 +1,151 @@ +/* + * linux/drivers/video/fb_defio.c + * + * Copyright (C) 2006 Jaya Kumar + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/list.h> +#include <asm/uaccess.h> + +/* to support deferred IO */ +#include <linux/rmap.h> +#include <linux/pagemap.h> + +/* this is to find and return the vmalloc-ed fb pages */ +static struct page* fb_deferred_io_nopage(struct vm_area_struct *vma, + unsigned long vaddr, int *type) +{ + unsigned long offset; + struct page *page; + struct fb_info *info = vma->vm_private_data; + /* info->screen_base is in System RAM */ + void *screen_base = (void __force *) info->screen_base; + + offset = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); + if (offset >= info->fix.smem_len) + return NOPAGE_SIGBUS; + + page = vmalloc_to_page(screen_base + offset); + if (!page) + return NOPAGE_OOM; + + get_page(page); + if (type) + *type = VM_FAULT_MINOR; + return page; +} + +int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) +{ + struct fb_info *info = file->private_data; + + /* Kill off the delayed work */ + cancel_rearming_delayed_work(&info->deferred_work); + + /* Run it immediately */ + return schedule_delayed_work(&info->deferred_work, 0); +} +EXPORT_SYMBOL_GPL(fb_deferred_io_fsync); + +/* vm_ops->page_mkwrite handler */ +static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, + struct page *page) +{ + struct fb_info *info = vma->vm_private_data; + struct fb_deferred_io *fbdefio = info->fbdefio; + + /* this is a callback we get when userspace first tries to + write to the page. we schedule a workqueue. that workqueue + will eventually mkclean the touched pages and execute the + deferred framebuffer IO. then if userspace touches a page + again, we repeat the same scheme */ + + /* protect against the workqueue changing the page list */ + mutex_lock(&fbdefio->lock); + list_add(&page->lru, &fbdefio->pagelist); + mutex_unlock(&fbdefio->lock); + + /* come back after delay to process the deferred IO */ + schedule_delayed_work(&info->deferred_work, fbdefio->delay); + return 0; +} + +static struct vm_operations_struct fb_deferred_io_vm_ops = { + .nopage = fb_deferred_io_nopage, + .page_mkwrite = fb_deferred_io_mkwrite, +}; + +static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + vma->vm_ops = &fb_deferred_io_vm_ops; + vma->vm_flags |= ( VM_IO | VM_RESERVED | VM_DONTEXPAND ); + vma->vm_private_data = info; + return 0; +} + +/* workqueue callback */ +static void fb_deferred_io_work(struct work_struct *work) +{ + struct fb_info *info = container_of(work, struct fb_info, + deferred_work.work); + struct list_head *node, *next; + struct page *cur; + struct fb_deferred_io *fbdefio = info->fbdefio; + + /* here we mkclean the pages, then do all deferred IO */ + mutex_lock(&fbdefio->lock); + list_for_each_entry(cur, &fbdefio->pagelist, lru) { + lock_page(cur); + page_mkclean(cur); + unlock_page(cur); + } + + /* driver's callback with pagelist */ + fbdefio->deferred_io(info, &fbdefio->pagelist); + + /* clear the list */ + list_for_each_safe(node, next, &fbdefio->pagelist) { + list_del(node); + } + mutex_unlock(&fbdefio->lock); +} + +void fb_deferred_io_init(struct fb_info *info) +{ + struct fb_deferred_io *fbdefio = info->fbdefio; + + BUG_ON(!fbdefio); + mutex_init(&fbdefio->lock); + info->fbops->fb_mmap = fb_deferred_io_mmap; + INIT_DELAYED_WORK(&info->deferred_work, fb_deferred_io_work); + INIT_LIST_HEAD(&fbdefio->pagelist); + if (fbdefio->delay == 0) /* set a default of 1 s */ + fbdefio->delay = HZ; +} +EXPORT_SYMBOL_GPL(fb_deferred_io_init); + +void fb_deferred_io_cleanup(struct fb_info *info) +{ + struct fb_deferred_io *fbdefio = info->fbdefio; + + BUG_ON(!fbdefio); + cancel_delayed_work(&info->deferred_work); + flush_scheduled_work(); +} +EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h new file mode 100644 index 0000000..c5c4520 --- /dev/null +++ b/drivers/video/fb_draw.h @@ -0,0 +1,72 @@ +#ifndef _FB_DRAW_H +#define _FB_DRAW_H + +#include <asm/types.h> + + /* + * Compose two values, using a bitmask as decision value + * This is equivalent to (a & mask) | (b & ~mask) + */ + +static inline unsigned long +comp(unsigned long a, unsigned long b, unsigned long mask) +{ + return ((a ^ b) & mask) ^ b; +} + + /* + * Create a pattern with the given pixel's color + */ + +#if BITS_PER_LONG == 64 +static inline unsigned long +pixel_to_pat( u32 bpp, u32 pixel) +{ + switch (bpp) { + case 1: + return 0xfffffffffffffffful*pixel; + case 2: + return 0x5555555555555555ul*pixel; + case 4: + return 0x1111111111111111ul*pixel; + case 8: + return 0x0101010101010101ul*pixel; + case 12: + return 0x0001001001001001ul*pixel; + case 16: + return 0x0001000100010001ul*pixel; + case 24: + return 0x0000000001000001ul*pixel; + case 32: + return 0x0000000100000001ul*pixel; + default: + panic("pixel_to_pat(): unsupported pixelformat\n"); + } +} +#else +static inline unsigned long +pixel_to_pat( u32 bpp, u32 pixel) +{ + switch (bpp) { + case 1: + return 0xfffffffful*pixel; + case 2: + return 0x55555555ul*pixel; + case 4: + return 0x11111111ul*pixel; + case 8: + return 0x01010101ul*pixel; + case 12: + return 0x00001001ul*pixel; + case 16: + return 0x00010001ul*pixel; + case 24: + return 0x00000001ul*pixel; + case 32: + return 0x00000001ul*pixel; + default: + panic("pixel_to_pat(): unsupported pixelformat\n"); + } +} +#endif +#endif /* FB_DRAW_H */ diff --git a/drivers/video/fb_sys_fops.c b/drivers/video/fb_sys_fops.c new file mode 100644 index 0000000..cf2538d --- /dev/null +++ b/drivers/video/fb_sys_fops.c @@ -0,0 +1,104 @@ +/* + * linux/drivers/video/fb_sys_read.c - Generic file operations where + * framebuffer is in system RAM + * + * Copyright (C) 2007 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/fb.h> +#include <linux/module.h> +#include <asm/uaccess.h> + +ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count, + loff_t *ppos) +{ + unsigned long p = *ppos; + void *src; + int err = 0; + unsigned long total_size; + + if (info->state != FBINFO_STATE_RUNNING) + return -EPERM; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p >= total_size) + return 0; + + if (count >= total_size) + count = total_size; + + if (count + p > total_size) + count = total_size - p; + + src = (void __force *)(info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + if (copy_to_user(buf, src, count)) + err = -EFAULT; + + if (!err) + *ppos += count; + + return (err) ? err : count; +} +EXPORT_SYMBOL_GPL(fb_sys_read); + +ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + void *dst; + int err = 0; + unsigned long total_size; + + if (info->state != FBINFO_STATE_RUNNING) + return -EPERM; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p > total_size) + return -EFBIG; + + if (count > total_size) { + err = -EFBIG; + count = total_size; + } + + if (count + p > total_size) { + if (!err) + err = -ENOSPC; + + count = total_size - p; + } + + dst = (void __force *) (info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + if (copy_from_user(dst, buf, count)) + err = -EFAULT; + + if (!err) + *ppos += count; + + return (err) ? err : count; +} +EXPORT_SYMBOL_GPL(fb_sys_write); + +MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); +MODULE_DESCRIPTION("Generic file read (fb in system RAM)"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 2822526..38c2e25 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -354,59 +354,59 @@ static void fb_rotate_logo(struct fb_info *info, u8 *dst, if (rotate == FB_ROTATE_UD) { fb_rotate_logo_ud(image->data, dst, image->width, image->height); - image->dx = info->var.xres - image->width; - image->dy = info->var.yres - image->height; + image->dx = info->var.xres - image->width - image->dx; + image->dy = info->var.yres - image->height - image->dy; } else if (rotate == FB_ROTATE_CW) { fb_rotate_logo_cw(image->data, dst, image->width, image->height); tmp = image->width; image->width = image->height; image->height = tmp; - image->dx = info->var.xres - image->width; + tmp = image->dy; + image->dy = image->dx; + image->dx = info->var.xres - image->width - tmp; } else if (rotate == FB_ROTATE_CCW) { fb_rotate_logo_ccw(image->data, dst, image->width, image->height); tmp = image->width; image->width = image->height; image->height = tmp; - image->dy = info->var.yres - image->height; + tmp = image->dx; + image->dx = image->dy; + image->dy = info->var.yres - image->height - tmp; } image->data = dst; } static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, - int rotate) + int rotate, unsigned int num) { - int x; + unsigned 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++) { + for (x = 0; + x < num && image->dx + image->width <= info->var.xres; + x++) { info->fbops->fb_imageblit(info, image); - image->dx += fb_logo.logo->width + 8; + image->dx += image->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++) { + for (x = 0; x < num && image->dx >= 0; x++) { info->fbops->fb_imageblit(info, image); - image->dx -= fb_logo.logo->width + 8; + image->dx -= image->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++) { + for (x = 0; + x < num && image->dy + image->height <= info->var.yres; + x++) { info->fbops->fb_imageblit(info, image); - image->dy += fb_logo.logo->width + 8; + image->dy += image->height + 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++) { + for (x = 0; x < num && image->dy >= 0; x++) { info->fbops->fb_imageblit(info, image); - image->dy -= fb_logo.logo->width + 8; + image->dy -= image->height + 8; } } } @@ -418,7 +418,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate) memset(&fb_logo, 0, sizeof(struct logo_data)); - if (info->flags & FBINFO_MISC_TILEBLITTING) + if (info->flags & FBINFO_MISC_TILEBLITTING || + info->flags & FBINFO_MODULE) return 0; if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { @@ -483,7 +484,8 @@ int fb_show_logo(struct fb_info *info, int rotate) struct fb_image image; /* Return if the frame buffer is not mapped or suspended */ - if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) + if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING || + info->flags & FBINFO_MODULE) return 0; image.depth = 8; @@ -532,7 +534,7 @@ int fb_show_logo(struct fb_info *info, int rotate) fb_rotate_logo(info, logo_rotate, &image, rotate); } - fb_do_show_logo(info, &image, rotate); + fb_do_show_logo(info, &image, rotate, num_online_cpus()); kfree(palette); if (saved_pseudo_palette != NULL) @@ -586,7 +588,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) return -EPERM; if (info->fbops->fb_read) - return info->fbops->fb_read(file, buf, count, ppos); + return info->fbops->fb_read(info, buf, count, ppos); total_size = info->screen_size; @@ -661,7 +663,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) return -EPERM; if (info->fbops->fb_write) - return info->fbops->fb_write(file, buf, count, ppos); + return info->fbops->fb_write(info, buf, count, ppos); total_size = info->screen_size; @@ -771,14 +773,37 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) return 0; } +static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, + u32 activate) +{ + struct fb_event event; + struct fb_blit_caps caps, fbcaps; + int err = 0; + + memset(&caps, 0, sizeof(caps)); + memset(&fbcaps, 0, sizeof(fbcaps)); + caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0; + event.info = info; + event.data = ∩︀ + fb_notifier_call_chain(FB_EVENT_GET_REQ, &event); + info->fbops->fb_get_caps(info, &fbcaps, var); + + if (((fbcaps.x ^ caps.x) & caps.x) || + ((fbcaps.y ^ caps.y) & caps.y) || + (fbcaps.len < caps.len)) + err = -EINVAL; + + return err; +} + int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) { - int err, flags = info->flags; + int flags = info->flags; + int ret = 0; if (var->activate & FB_ACTIVATE_INV_MODE) { struct fb_videomode mode1, mode2; - int ret = 0; fb_var_to_videomode(&mode1, var); fb_var_to_videomode(&mode2, &info->var); @@ -796,40 +821,51 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) if (!ret) fb_delete_videomode(&mode1, &info->modelist); - return ret; + + ret = (ret) ? -EINVAL : 0; + goto done; } if ((var->activate & FB_ACTIVATE_FORCE) || memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { + u32 activate = var->activate; + if (!info->fbops->fb_check_var) { *var = info->var; - return 0; + goto done; } - if ((err = info->fbops->fb_check_var(var, info))) - return err; + ret = info->fbops->fb_check_var(var, info); + + if (ret) + goto done; if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { struct fb_videomode mode; - int err = 0; + + if (info->fbops->fb_get_caps) { + ret = fb_check_caps(info, var, activate); + + if (ret) + goto done; + } info->var = *var; + if (info->fbops->fb_set_par) info->fbops->fb_set_par(info); fb_pan_display(info, &info->var); - fb_set_cmap(&info->cmap, info); - fb_var_to_videomode(&mode, &info->var); if (info->modelist.prev && info->modelist.next && !list_empty(&info->modelist)) - err = fb_add_videomode(&mode, &info->modelist); + ret = fb_add_videomode(&mode, &info->modelist); - if (!err && (flags & FBINFO_MISC_USEREVENT)) { + if (!ret && (flags & FBINFO_MISC_USEREVENT)) { struct fb_event event; - int evnt = (var->activate & FB_ACTIVATE_ALL) ? + int evnt = (activate & FB_ACTIVATE_ALL) ? FB_EVENT_MODE_CHANGE_ALL : FB_EVENT_MODE_CHANGE; @@ -839,7 +875,9 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) } } } - return 0; + + done: + return ret; } int @@ -1198,6 +1236,10 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; #elif defined(__arm__) || defined(__sh__) || defined(__m32r__) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); +#elif defined(__avr32__) + vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot) + & ~_PAGE_CACHABLE) + | (_PAGE_BUFFER | _PAGE_DIRTY)); #elif defined(__ia64__) if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); @@ -1266,6 +1308,9 @@ static const struct file_operations fb_fops = { #ifdef HAVE_ARCH_FB_UNMAPPED_AREA .get_unmapped_area = get_fb_unmapped_area, #endif +#ifdef CONFIG_FB_DEFERRED_IO + .fsync = fb_deferred_io_fsync, +#endif }; struct class *fb_class; @@ -1316,6 +1361,12 @@ register_framebuffer(struct fb_info *fb_info) } fb_info->pixmap.offset = 0; + if (!fb_info->pixmap.blit_x) + fb_info->pixmap.blit_x = ~(u32)0; + + if (!fb_info->pixmap.blit_y) + fb_info->pixmap.blit_y = ~(u32)0; + if (!fb_info->modelist.prev || !fb_info->modelist.next) INIT_LIST_HEAD(&fb_info->modelist); diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 6b385c3..438b941 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -48,8 +48,9 @@ #define DPRINTK(fmt, args...) #endif -#define FBMON_FIX_HEADER 1 -#define FBMON_FIX_INPUT 2 +#define FBMON_FIX_HEADER 1 +#define FBMON_FIX_INPUT 2 +#define FBMON_FIX_TIMINGS 3 #ifdef CONFIG_FB_MODE_HELPERS struct broken_edid { @@ -71,6 +72,12 @@ static const struct broken_edid brokendb[] = { .model = 0x5a44, .fix = FBMON_FIX_INPUT, }, + /* Sharp UXGA? */ + { + .manufacturer = "SHP", + .model = 0x138e, + .fix = FBMON_FIX_TIMINGS, + }, }; static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff, @@ -87,6 +94,55 @@ static void copy_string(unsigned char *c, unsigned char *s) while (i-- && (*--s == 0x20)) *s = 0; } +static int edid_is_serial_block(unsigned char *block) +{ + if ((block[0] == 0x00) && (block[1] == 0x00) && + (block[2] == 0x00) && (block[3] == 0xff) && + (block[4] == 0x00)) + return 1; + else + return 0; +} + +static int edid_is_ascii_block(unsigned char *block) +{ + if ((block[0] == 0x00) && (block[1] == 0x00) && + (block[2] == 0x00) && (block[3] == 0xfe) && + (block[4] == 0x00)) + return 1; + else + return 0; +} + +static int edid_is_limits_block(unsigned char *block) +{ + if ((block[0] == 0x00) && (block[1] == 0x00) && + (block[2] == 0x00) && (block[3] == 0xfd) && + (block[4] == 0x00)) + return 1; + else + return 0; +} + +static int edid_is_monitor_block(unsigned char *block) +{ + if ((block[0] == 0x00) && (block[1] == 0x00) && + (block[2] == 0x00) && (block[3] == 0xfc) && + (block[4] == 0x00)) + return 1; + else + return 0; +} + +static int edid_is_timing_block(unsigned char *block) +{ + if ((block[0] != 0x00) || (block[1] != 0x00) || + (block[2] != 0x00) || (block[4] != 0x00)) + return 1; + else + return 0; +} + static int check_edid(unsigned char *edid) { unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4]; @@ -104,9 +160,6 @@ static int check_edid(unsigned char *edid) for (i = 0; i < ARRAY_SIZE(brokendb); i++) { if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) && brokendb[i].model == model) { - printk("fbmon: The EDID Block of " - "Manufacturer: %s Model: 0x%x is known to " - "be broken,\n", manufacturer, model); fix = brokendb[i].fix; break; } @@ -115,8 +168,10 @@ static int check_edid(unsigned char *edid) switch (fix) { case FBMON_FIX_HEADER: for (i = 0; i < 8; i++) { - if (edid[i] != edid_v1_header[i]) + if (edid[i] != edid_v1_header[i]) { ret = fix; + break; + } } break; case FBMON_FIX_INPUT: @@ -126,14 +181,34 @@ static int check_edid(unsigned char *edid) if (b[4] & 0x01 && b[0] & 0x80) ret = fix; break; + case FBMON_FIX_TIMINGS: + b = edid + DETAILED_TIMING_DESCRIPTIONS_START; + ret = fix; + + for (i = 0; i < 4; i++) { + if (edid_is_limits_block(b)) { + ret = 0; + break; + } + + b += DETAILED_TIMING_DESCRIPTION_SIZE; + } + + break; } + if (ret) + printk("fbmon: The EDID Block of " + "Manufacturer: %s Model: 0x%x is known to " + "be broken,\n", manufacturer, model); + return ret; } static void fix_edid(unsigned char *edid, int fix) { - unsigned char *b; + int i; + unsigned char *b, csum = 0; switch (fix) { case FBMON_FIX_HEADER: @@ -145,6 +220,37 @@ static void fix_edid(unsigned char *edid, int fix) b = edid + EDID_STRUCT_DISPLAY; b[0] &= ~0x80; edid[127] += 0x80; + break; + case FBMON_FIX_TIMINGS: + printk("fbmon: trying to fix monitor timings\n"); + b = edid + DETAILED_TIMING_DESCRIPTIONS_START; + for (i = 0; i < 4; i++) { + if (!(edid_is_serial_block(b) || + edid_is_ascii_block(b) || + edid_is_monitor_block(b) || + edid_is_timing_block(b))) { + b[0] = 0x00; + b[1] = 0x00; + b[2] = 0x00; + b[3] = 0xfd; + b[4] = 0x00; + b[5] = 60; /* vfmin */ + b[6] = 60; /* vfmax */ + b[7] = 30; /* hfmin */ + b[8] = 75; /* hfmax */ + b[9] = 17; /* pixclock - 170 MHz*/ + b[10] = 0; /* GTF */ + break; + } + + b += DETAILED_TIMING_DESCRIPTION_SIZE; + } + + for (i = 0; i < EDID_LENGTH - 1; i++) + csum += edid[i]; + + edid[127] = 256 - csum; + break; } } @@ -273,46 +379,6 @@ static void get_chroma(unsigned char *block, struct fb_monspecs *specs) DPRINTK("WhiteY: 0.%03d\n", specs->chroma.whitey); } -static int edid_is_serial_block(unsigned char *block) -{ - if ((block[0] == 0x00) && (block[1] == 0x00) && - (block[2] == 0x00) && (block[3] == 0xff) && - (block[4] == 0x00)) - return 1; - else - return 0; -} - -static int edid_is_ascii_block(unsigned char *block) -{ - if ((block[0] == 0x00) && (block[1] == 0x00) && - (block[2] == 0x00) && (block[3] == 0xfe) && - (block[4] == 0x00)) - return 1; - else - return 0; -} - -static int edid_is_limits_block(unsigned char *block) -{ - if ((block[0] == 0x00) && (block[1] == 0x00) && - (block[2] == 0x00) && (block[3] == 0xfd) && - (block[4] == 0x00)) - return 1; - else - return 0; -} - -static int edid_is_monitor_block(unsigned char *block) -{ - if ((block[0] == 0x00) && (block[1] == 0x00) && - (block[2] == 0x00) && (block[3] == 0xfc) && - (block[4] == 0x00)) - return 1; - else - return 0; -} - static void calc_mode_timings(int xres, int yres, int refresh, struct fb_videomode *mode) { @@ -795,15 +861,6 @@ static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs) } } -static int edid_is_timing_block(unsigned char *block) -{ - if ((block[0] != 0x00) || (block[1] != 0x00) || - (block[2] != 0x00) || (block[4] != 0x00)) - return 1; - else - return 0; -} - int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) { int i; diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 40c80c8..d4a2c11 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -376,7 +376,7 @@ static ssize_t show_pan(struct device *device, { struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset, - fb_info->var.xoffset); + fb_info->var.yoffset); } static ssize_t show_name(struct device *device, diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index ca93a75..b7655c0 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c @@ -26,7 +26,6 @@ #include <linux/interrupt.h> #include <linux/fb.h> #include <linux/init.h> -#include <linux/pci.h> #include <asm/io.h> #include <asm/jazz.h> diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c new file mode 100644 index 0000000..abfcb50 --- /dev/null +++ b/drivers/video/hecubafb.c @@ -0,0 +1,471 @@ +/* + * linux/drivers/video/hecubafb.c -- FB driver for Hecuba controller + * + * Copyright (C) 2006, Jaya Kumar + * This work was sponsored by CIS(M) Sdn Bhd + * + * 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. + * + * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. + * This work was possible because of apollo display code from E-Ink's website + * http://support.eink.com/community + * All information used to write this code is from public material made + * available by E-Ink on its support site. Some commands such as 0xA4 + * were found by looping through cmd=0x00 thru 0xFF and supplying random + * values. There are other commands that the display is capable of, + * beyond the 5 used here but they are more complex. + * + * This driver is written to be used with the Hecuba display controller + * board, and tested with the EInk 800x600 display in 1 bit mode. + * The interface between Hecuba and the host is TTL based GPIO. The + * GPIO requirements are 8 writable data lines and 6 lines for control. + * Only 4 of the controls are actually used here but 6 for future use. + * The driver requires the IO addresses for data and control GPIO at + * load time. It is also possible to use this display with a standard + * PC parallel port. + * + * General notes: + * - User must set hecubafb_enable=1 to enable it + * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/list.h> +#include <asm/uaccess.h> + +/* Apollo controller specific defines */ +#define APOLLO_START_NEW_IMG 0xA0 +#define APOLLO_STOP_IMG_DATA 0xA1 +#define APOLLO_DISPLAY_IMG 0xA2 +#define APOLLO_ERASE_DISPLAY 0xA3 +#define APOLLO_INIT_DISPLAY 0xA4 + +/* Hecuba interface specific defines */ +/* WUP is inverted, CD is inverted, DS is inverted */ +#define HCB_NWUP_BIT 0x01 +#define HCB_NDS_BIT 0x02 +#define HCB_RW_BIT 0x04 +#define HCB_NCD_BIT 0x08 +#define HCB_ACK_BIT 0x80 + +/* Display specific information */ +#define DPY_W 600 +#define DPY_H 800 + +struct hecubafb_par { + unsigned long dio_addr; + unsigned long cio_addr; + unsigned long c2io_addr; + unsigned char ctl; + struct fb_info *info; + unsigned int irq; +}; + +static struct fb_fix_screeninfo hecubafb_fix __devinitdata = { + .id = "hecubafb", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_MONO01, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + +static struct fb_var_screeninfo hecubafb_var __devinitdata = { + .xres = DPY_W, + .yres = DPY_H, + .xres_virtual = DPY_W, + .yres_virtual = DPY_H, + .bits_per_pixel = 1, + .nonstd = 1, +}; + +static unsigned long dio_addr; +static unsigned long cio_addr; +static unsigned long c2io_addr; +static unsigned long splashval; +static unsigned int nosplash; +static unsigned int hecubafb_enable; +static unsigned int irq; + +static DECLARE_WAIT_QUEUE_HEAD(hecubafb_waitq); + +static void hcb_set_ctl(struct hecubafb_par *par) +{ + outb(par->ctl, par->cio_addr); +} + +static unsigned char hcb_get_ctl(struct hecubafb_par *par) +{ + return inb(par->c2io_addr); +} + +static void hcb_set_data(struct hecubafb_par *par, unsigned char value) +{ + outb(value, par->dio_addr); +} + +static int __devinit apollo_init_control(struct hecubafb_par *par) +{ + unsigned char ctl; + /* for init, we want the following setup to be set: + WUP = lo + ACK = hi + DS = hi + RW = hi + CD = lo + */ + + /* write WUP to lo, DS to hi, RW to hi, CD to lo */ + par->ctl = HCB_NWUP_BIT | HCB_RW_BIT | HCB_NCD_BIT ; + par->ctl &= ~HCB_NDS_BIT; + hcb_set_ctl(par); + + /* check ACK is not lo */ + ctl = hcb_get_ctl(par); + if ((ctl & HCB_ACK_BIT)) { + printk(KERN_ERR "Fail because ACK is already low\n"); + return -ENXIO; + } + + return 0; +} + +static void hcb_wait_for_ack(struct hecubafb_par *par) +{ + + int timeout; + unsigned char ctl; + + timeout=500; + do { + ctl = hcb_get_ctl(par); + if ((ctl & HCB_ACK_BIT)) + return; + udelay(1); + } while (timeout--); + printk(KERN_ERR "timed out waiting for ack\n"); +} + +static void hcb_wait_for_ack_clear(struct hecubafb_par *par) +{ + + int timeout; + unsigned char ctl; + + timeout=500; + do { + ctl = hcb_get_ctl(par); + if (!(ctl & HCB_ACK_BIT)) + return; + udelay(1); + } while (timeout--); + printk(KERN_ERR "timed out waiting for clear\n"); +} + +static void apollo_send_data(struct hecubafb_par *par, unsigned char data) +{ + /* set data */ + hcb_set_data(par, data); + + /* set DS low */ + par->ctl |= HCB_NDS_BIT; + hcb_set_ctl(par); + + hcb_wait_for_ack(par); + + /* set DS hi */ + par->ctl &= ~(HCB_NDS_BIT); + hcb_set_ctl(par); + + hcb_wait_for_ack_clear(par); +} + +static void apollo_send_command(struct hecubafb_par *par, unsigned char data) +{ + /* command so set CD to high */ + par->ctl &= ~(HCB_NCD_BIT); + hcb_set_ctl(par); + + /* actually strobe with command */ + apollo_send_data(par, data); + + /* clear CD back to low */ + par->ctl |= (HCB_NCD_BIT); + hcb_set_ctl(par); +} + +/* main hecubafb functions */ + +static void hecubafb_dpy_update(struct hecubafb_par *par) +{ + int i; + unsigned char *buf = (unsigned char __force *)par->info->screen_base; + + apollo_send_command(par, 0xA0); + + for (i=0; i < (DPY_W*DPY_H/8); i++) { + apollo_send_data(par, *(buf++)); + } + + apollo_send_command(par, 0xA1); + apollo_send_command(par, 0xA2); +} + +/* this is called back from the deferred io workqueue */ +static void hecubafb_dpy_deferred_io(struct fb_info *info, + struct list_head *pagelist) +{ + hecubafb_dpy_update(info->par); +} + +static void hecubafb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + struct hecubafb_par *par = info->par; + + sys_fillrect(info, rect); + + hecubafb_dpy_update(par); +} + +static void hecubafb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + struct hecubafb_par *par = info->par; + + sys_copyarea(info, area); + + hecubafb_dpy_update(par); +} + +static void hecubafb_imageblit(struct fb_info *info, + const struct fb_image *image) +{ + struct hecubafb_par *par = info->par; + + sys_imageblit(info, image); + + hecubafb_dpy_update(par); +} + +/* + * this is the slow path from userspace. they can seek and write to + * the fb. it's inefficient to do anything less than a full screen draw + */ +static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned long p; + int err=-EINVAL; + struct hecubafb_par *par; + unsigned int xres; + unsigned int fbmemlength; + + p = *ppos; + par = info->par; + xres = info->var.xres; + fbmemlength = (xres * info->var.yres)/8; + + if (p > fbmemlength) + return -ENOSPC; + + err = 0; + if ((count + p) > fbmemlength) { + count = fbmemlength - p; + err = -ENOSPC; + } + + if (count) { + char *base_addr; + + base_addr = (char __force *)info->screen_base; + count -= copy_from_user(base_addr + p, buf, count); + *ppos += count; + err = -EFAULT; + } + + hecubafb_dpy_update(par); + + if (count) + return count; + + return err; +} + +static struct fb_ops hecubafb_ops = { + .owner = THIS_MODULE, + .fb_read = fb_sys_read, + .fb_write = hecubafb_write, + .fb_fillrect = hecubafb_fillrect, + .fb_copyarea = hecubafb_copyarea, + .fb_imageblit = hecubafb_imageblit, +}; + +static struct fb_deferred_io hecubafb_defio = { + .delay = HZ, + .deferred_io = hecubafb_dpy_deferred_io, +}; + +static int __devinit hecubafb_probe(struct platform_device *dev) +{ + struct fb_info *info; + int retval = -ENOMEM; + int videomemorysize; + unsigned char *videomemory; + struct hecubafb_par *par; + + videomemorysize = (DPY_W*DPY_H)/8; + + if (!(videomemory = vmalloc(videomemorysize))) + return retval; + + memset(videomemory, 0, videomemorysize); + + info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev); + if (!info) + goto err; + + info->screen_base = (char __iomem *) videomemory; + info->fbops = &hecubafb_ops; + + info->var = hecubafb_var; + info->fix = hecubafb_fix; + info->fix.smem_len = videomemorysize; + par = info->par; + par->info = info; + + if (!dio_addr || !cio_addr || !c2io_addr) { + printk(KERN_WARNING "no IO addresses supplied\n"); + goto err1; + } + par->dio_addr = dio_addr; + par->cio_addr = cio_addr; + par->c2io_addr = c2io_addr; + info->flags = FBINFO_FLAG_DEFAULT; + + info->fbdefio = &hecubafb_defio; + fb_deferred_io_init(info); + + retval = register_framebuffer(info); + if (retval < 0) + goto err1; + platform_set_drvdata(dev, info); + + printk(KERN_INFO + "fb%d: Hecuba frame buffer device, using %dK of video memory\n", + info->node, videomemorysize >> 10); + + /* this inits the dpy */ + apollo_init_control(par); + + apollo_send_command(par, APOLLO_INIT_DISPLAY); + apollo_send_data(par, 0x81); + + /* have to wait while display resets */ + udelay(1000); + + /* if we were told to splash the screen, we just clear it */ + if (!nosplash) { + apollo_send_command(par, APOLLO_ERASE_DISPLAY); + apollo_send_data(par, splashval); + } + + return 0; +err1: + framebuffer_release(info); +err: + vfree(videomemory); + return retval; +} + +static int __devexit hecubafb_remove(struct platform_device *dev) +{ + struct fb_info *info = platform_get_drvdata(dev); + + if (info) { + fb_deferred_io_cleanup(info); + unregister_framebuffer(info); + vfree((void __force *)info->screen_base); + framebuffer_release(info); + } + return 0; +} + +static struct platform_driver hecubafb_driver = { + .probe = hecubafb_probe, + .remove = hecubafb_remove, + .driver = { + .name = "hecubafb", + }, +}; + +static struct platform_device *hecubafb_device; + +static int __init hecubafb_init(void) +{ + int ret; + + if (!hecubafb_enable) { + printk(KERN_ERR "Use hecubafb_enable to enable the device\n"); + return -ENXIO; + } + + ret = platform_driver_register(&hecubafb_driver); + if (!ret) { + hecubafb_device = platform_device_alloc("hecubafb", 0); + if (hecubafb_device) + ret = platform_device_add(hecubafb_device); + else + ret = -ENOMEM; + + if (ret) { + platform_device_put(hecubafb_device); + platform_driver_unregister(&hecubafb_driver); + } + } + return ret; + +} + +static void __exit hecubafb_exit(void) +{ + platform_device_unregister(hecubafb_device); + platform_driver_unregister(&hecubafb_driver); +} + +module_param(nosplash, uint, 0); +MODULE_PARM_DESC(nosplash, "Disable doing the splash screen"); +module_param(hecubafb_enable, uint, 0); +MODULE_PARM_DESC(hecubafb_enable, "Enable communication with Hecuba board"); +module_param(dio_addr, ulong, 0); +MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480"); +module_param(cio_addr, ulong, 0); +MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400"); +module_param(c2io_addr, ulong, 0); +MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408"); +module_param(splashval, ulong, 0); +MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white"); +module_param(irq, uint, 0); +MODULE_PARM_DESC(irq, "IRQ for the Hecuba board"); + +module_init(hecubafb_init); +module_exit(hecubafb_exit); + +MODULE_DESCRIPTION("fbdev driver for Hecuba board"); +MODULE_AUTHOR("Jaya Kumar"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h index aa65ffc..889e4ea 100644 --- a/drivers/video/i810/i810.h +++ b/drivers/video/i810/i810.h @@ -133,7 +133,7 @@ /* Masks (AND ops) and OR's */ #define FB_START_MASK (0x3f << (32 - 6)) #define MMIO_ADDR_MASK (0x1FFF << (32 - 13)) -#define FREQ_MASK 0x1EF +#define FREQ_MASK (1 << 4) #define SCR_OFF 0x20 #define DRAM_ON 0x08 #define DRAM_OFF 0xE7 diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 7e76019..1a7d778 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1717,7 +1717,7 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info) * @info: pointer to device specific info structure * * DESCRIPTION: - * Sets the the user monitor's horizontal and vertical + * Sets the user monitor's horizontal and vertical * frequency limits */ static void __devinit i810_init_monspecs(struct fb_info *info) diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c index f4ede5f..61e4c87 100644 --- a/drivers/video/intelfb/intelfb_i2c.c +++ b/drivers/video/intelfb/intelfb_i2c.c @@ -104,7 +104,8 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo, chan->dinfo = dinfo; chan->reg = reg; - snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name); + snprintf(chan->adapter.name, sizeof(chan->adapter.name), + "intelfb %s", name); chan->adapter.owner = THIS_MODULE; chan->adapter.id = I2C_HW_B_INTELFB; chan->adapter.algo_data = &chan->algo; diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index c1eb18b..16bc8d7 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -1428,6 +1428,24 @@ static void refresh_ring(struct intelfb_info *dinfo); static void reset_state(struct intelfb_info *dinfo); static void do_flush(struct intelfb_info *dinfo); +static u32 get_ring_space(struct intelfb_info *dinfo) +{ + u32 ring_space; + + if (dinfo->ring_tail >= dinfo->ring_head) + ring_space = dinfo->ring.size - + (dinfo->ring_tail - dinfo->ring_head); + else + ring_space = dinfo->ring_head - dinfo->ring_tail; + + if (ring_space > RING_MIN_FREE) + ring_space -= RING_MIN_FREE; + else + ring_space = 0; + + return ring_space; +} + static int wait_ring(struct intelfb_info *dinfo, int n) { @@ -1442,13 +1460,8 @@ wait_ring(struct intelfb_info *dinfo, int n) end = jiffies + (HZ * 3); while (dinfo->ring_space < n) { dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK; - if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head) - dinfo->ring_space = dinfo->ring_head - - (dinfo->ring_tail + RING_MIN_FREE); - else - dinfo->ring_space = (dinfo->ring.size + - dinfo->ring_head) - - (dinfo->ring_tail + RING_MIN_FREE); + dinfo->ring_space = get_ring_space(dinfo); + if (dinfo->ring_head != last_head) { end = jiffies + (HZ * 3); last_head = dinfo->ring_head; @@ -1513,12 +1526,7 @@ refresh_ring(struct intelfb_info *dinfo) dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK; dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK; - if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head) - dinfo->ring_space = dinfo->ring_head - - (dinfo->ring_tail + RING_MIN_FREE); - else - dinfo->ring_space = (dinfo->ring.size + dinfo->ring_head) - - (dinfo->ring_tail + RING_MIN_FREE); + dinfo->ring_space = get_ring_space(dinfo); } static void diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig index f0e6512..9397bce 100644 --- a/drivers/video/logo/Kconfig +++ b/drivers/video/logo/Kconfig @@ -2,73 +2,69 @@ # Logo configuration # -menu "Logo configuration" - -config LOGO +menuconfig LOGO bool "Bootup logo" depends on FB || SGI_NEWPORT_CONSOLE help Enable and select frame buffer bootup logos. +if LOGO + config LOGO_LINUX_MONO bool "Standard black and white Linux logo" - depends on LOGO default y config LOGO_LINUX_VGA16 bool "Standard 16-color Linux logo" - depends on LOGO default y config LOGO_LINUX_CLUT224 bool "Standard 224-color Linux logo" - depends on LOGO default y config LOGO_DEC_CLUT224 bool "224-color Digital Equipment Corporation Linux logo" - depends on LOGO && (MACH_DECSTATION || ALPHA) + depends on MACH_DECSTATION || ALPHA default y config LOGO_MAC_CLUT224 bool "224-color Macintosh Linux logo" - depends on LOGO && MAC + depends on MAC default y config LOGO_PARISC_CLUT224 bool "224-color PA-RISC Linux logo" - depends on LOGO && PARISC + depends on PARISC default y config LOGO_SGI_CLUT224 bool "224-color SGI Linux logo" - depends on LOGO && (SGI_IP22 || SGI_IP27 || SGI_IP32 || X86_VISWS) + depends on SGI_IP22 || SGI_IP27 || SGI_IP32 || X86_VISWS default y config LOGO_SUN_CLUT224 bool "224-color Sun Linux logo" - depends on LOGO && SPARC + depends on SPARC default y config LOGO_SUPERH_MONO bool "Black and white SuperH Linux logo" - depends on LOGO && SUPERH + depends on SUPERH default y config LOGO_SUPERH_VGA16 bool "16-color SuperH Linux logo" - depends on LOGO && SUPERH + depends on SUPERH default y config LOGO_SUPERH_CLUT224 bool "224-color SuperH Linux logo" - depends on LOGO && SUPERH + depends on SUPERH default y config LOGO_M32R_CLUT224 bool "224-color M32R Linux logo" - depends on LOGO && M32R + depends on M32R default y -endmenu - +endif # LOGO diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c index 5ec718a..4baab7b 100644 --- a/drivers/video/matrox/i2c-matroxfb.c +++ b/drivers/video/matrox/i2c-matroxfb.c @@ -111,7 +111,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, b->mask.data = data; b->mask.clock = clock; b->adapter = matrox_i2c_adapter_template; - snprintf(b->adapter.name, I2C_NAME_SIZE, name, + snprintf(b->adapter.name, sizeof(b->adapter.name), name, minfo->fbcon.node); i2c_set_adapdata(&b->adapter, b); b->adapter.algo_data = &b->bac; diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index a5690a5..9445cdb 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c @@ -72,7 +72,7 @@ * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> * * (following author is not in any relation with this code, but his ideas - * were used when writting this driver) + * were used when writing this driver) * * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk> * diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c index a5c825d..c57aaad 100644 --- a/drivers/video/matrox/matroxfb_accel.c +++ b/drivers/video/matrox/matroxfb_accel.c @@ -70,7 +70,7 @@ * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> * * (following author is not in any relation with this code, but his ideas - * were used when writting this driver) + * were used when writing this driver) * * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk> * diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index cb2aa40..c8559a7 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -93,7 +93,7 @@ * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> * * (following author is not in any relation with this code, but his ideas - * were used when writting this driver) + * were used when writing this driver) * * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk> * diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c index 18886b6..5948e54 100644 --- a/drivers/video/matrox/matroxfb_misc.c +++ b/drivers/video/matrox/matroxfb_misc.c @@ -78,7 +78,7 @@ * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> * * (following author is not in any relation with this code, but his ideas - * were used when writting this driver) + * were used when writing this driver) * * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk> * diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 3e51794..3741ad7 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -395,7 +395,7 @@ static int my_atoi(const char *name) for (;; name++) { switch (*name) { - case '0'...'9': + case '0' ... '9': val = 10*val+(*name-'0'); break; default: @@ -548,7 +548,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, } else goto done; break; - case '0'...'9': + case '0' ... '9': break; case 'M': if (!yres_specified) diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 395cced..bd30aba 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -665,6 +665,7 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) var->red.msb_right = 0; var->green.msb_right = 0; var->blue.msb_right = 0; + var->transp.msb_right = 0; switch (var->bits_per_pixel) { case 8: /* PSEUDOCOLOUR, 256 */ diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c index 9efb8a3..fa4821c 100644 --- a/drivers/video/nvidia/nv_accel.c +++ b/drivers/video/nvidia/nv_accel.c @@ -69,27 +69,38 @@ static const int NVCopyROP_PM[16] = { 0x5A, /* invert */ }; -static inline void NVFlush(struct nvidia_par *par) +static inline void nvidiafb_safe_mode(struct fb_info *info) { + struct nvidia_par *par = info->par; + + touch_softlockup_watchdog(); + info->pixmap.scan_align = 1; + par->lockup = 1; +} + +static inline void NVFlush(struct fb_info *info) +{ + struct nvidia_par *par = info->par; int count = 1000000000; while (--count && READ_GET(par) != par->dmaPut) ; if (!count) { printk("nvidiafb: DMA Flush lockup\n"); - par->lockup = 1; + nvidiafb_safe_mode(info); } } -static inline void NVSync(struct nvidia_par *par) +static inline void NVSync(struct fb_info *info) { + struct nvidia_par *par = info->par; int count = 1000000000; while (--count && NV_RD32(par->PGRAPH, 0x0700)) ; if (!count) { printk("nvidiafb: DMA Sync lockup\n"); - par->lockup = 1; + nvidiafb_safe_mode(info); } } @@ -101,8 +112,9 @@ static void NVDmaKickoff(struct nvidia_par *par) } } -static void NVDmaWait(struct nvidia_par *par, int size) +static void NVDmaWait(struct fb_info *info, int size) { + struct nvidia_par *par = info->par; int dmaGet; int count = 1000000000, cnt; size++; @@ -135,34 +147,38 @@ static void NVDmaWait(struct nvidia_par *par, int size) } if (!count) { - printk("DMA Wait Lockup\n"); - par->lockup = 1; + printk("nvidiafb: DMA Wait Lockup\n"); + nvidiafb_safe_mode(info); } } -static void NVSetPattern(struct nvidia_par *par, u32 clr0, u32 clr1, +static void NVSetPattern(struct fb_info *info, u32 clr0, u32 clr1, u32 pat0, u32 pat1) { - NVDmaStart(par, PATTERN_COLOR_0, 4); + struct nvidia_par *par = info->par; + + NVDmaStart(info, par, PATTERN_COLOR_0, 4); NVDmaNext(par, clr0); NVDmaNext(par, clr1); NVDmaNext(par, pat0); NVDmaNext(par, pat1); } -static void NVSetRopSolid(struct nvidia_par *par, u32 rop, u32 planemask) +static void NVSetRopSolid(struct fb_info *info, u32 rop, u32 planemask) { + struct nvidia_par *par = info->par; + if (planemask != ~0) { - NVSetPattern(par, 0, planemask, ~0, ~0); + NVSetPattern(info, 0, planemask, ~0, ~0); if (par->currentRop != (rop + 32)) { - NVDmaStart(par, ROP_SET, 1); + NVDmaStart(info, par, ROP_SET, 1); NVDmaNext(par, NVCopyROP_PM[rop]); par->currentRop = rop + 32; } } else if (par->currentRop != rop) { if (par->currentRop >= 16) - NVSetPattern(par, ~0, ~0, ~0, ~0); - NVDmaStart(par, ROP_SET, 1); + NVSetPattern(info, ~0, ~0, ~0, ~0); + NVDmaStart(info, par, ROP_SET, 1); NVDmaNext(par, NVCopyROP[rop]); par->currentRop = rop; } @@ -175,7 +191,7 @@ static void NVSetClippingRectangle(struct fb_info *info, int x1, int y1, int h = y2 - y1 + 1; int w = x2 - x1 + 1; - NVDmaStart(par, CLIP_POINT, 2); + NVDmaStart(info, par, CLIP_POINT, 2); NVDmaNext(par, (y1 << 16) | x1); NVDmaNext(par, (h << 16) | w); } @@ -237,23 +253,23 @@ void NVResetGraphics(struct fb_info *info) break; } - NVDmaStart(par, SURFACE_FORMAT, 4); + NVDmaStart(info, par, SURFACE_FORMAT, 4); NVDmaNext(par, surfaceFormat); NVDmaNext(par, pitch | (pitch << 16)); NVDmaNext(par, 0); NVDmaNext(par, 0); - NVDmaStart(par, PATTERN_FORMAT, 1); + NVDmaStart(info, par, PATTERN_FORMAT, 1); NVDmaNext(par, patternFormat); - NVDmaStart(par, RECT_FORMAT, 1); + NVDmaStart(info, par, RECT_FORMAT, 1); NVDmaNext(par, rectFormat); - NVDmaStart(par, LINE_FORMAT, 1); + NVDmaStart(info, par, LINE_FORMAT, 1); NVDmaNext(par, lineFormat); par->currentRop = ~0; /* set to something invalid */ - NVSetRopSolid(par, ROP_COPY, ~0); + NVSetRopSolid(info, ROP_COPY, ~0); NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual, info->var.yres_virtual); @@ -269,10 +285,10 @@ int nvidiafb_sync(struct fb_info *info) return 0; if (!par->lockup) - NVFlush(par); + NVFlush(info); if (!par->lockup) - NVSync(par); + NVSync(info); return 0; } @@ -287,7 +303,7 @@ void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region) if (par->lockup) return cfb_copyarea(info, region); - NVDmaStart(par, BLIT_POINT_SRC, 3); + NVDmaStart(info, par, BLIT_POINT_SRC, 3); NVDmaNext(par, (region->sy << 16) | region->sx); NVDmaNext(par, (region->dy << 16) | region->dx); NVDmaNext(par, (region->height << 16) | region->width); @@ -312,19 +328,19 @@ void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) color = ((u32 *) info->pseudo_palette)[rect->color]; if (rect->rop != ROP_COPY) - NVSetRopSolid(par, rect->rop, ~0); + NVSetRopSolid(info, rect->rop, ~0); - NVDmaStart(par, RECT_SOLID_COLOR, 1); + NVDmaStart(info, par, RECT_SOLID_COLOR, 1); NVDmaNext(par, color); - NVDmaStart(par, RECT_SOLID_RECTS(0), 2); + NVDmaStart(info, par, RECT_SOLID_RECTS(0), 2); NVDmaNext(par, (rect->dx << 16) | rect->dy); NVDmaNext(par, (rect->width << 16) | rect->height); NVDmaKickoff(par); if (rect->rop != ROP_COPY) - NVSetRopSolid(par, ROP_COPY, ~0); + NVSetRopSolid(info, ROP_COPY, ~0); } static void nvidiafb_mono_color_expand(struct fb_info *info, @@ -346,7 +362,7 @@ static void nvidiafb_mono_color_expand(struct fb_info *info, bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask; } - NVDmaStart(par, RECT_EXPAND_TWO_COLOR_CLIP, 7); + NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_CLIP, 7); NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff)); NVDmaNext(par, ((image->dy + image->height) << 16) | ((image->dx + image->width) & 0xffff)); @@ -357,7 +373,7 @@ static void nvidiafb_mono_color_expand(struct fb_info *info, NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff)); while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) { - NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0), + NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS); for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) { @@ -370,7 +386,7 @@ static void nvidiafb_mono_color_expand(struct fb_info *info, } if (dsize) { - NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize); + NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize); for (j = dsize; j--;) { tmp = data[k++]; diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c index ea42611..aff11bb 100644 --- a/drivers/video/nvidia/nv_hw.c +++ b/drivers/video/nvidia/nv_hw.c @@ -150,7 +150,8 @@ static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk, M = pll & 0xFF; N = (pll >> 8) & 0xFF; if (((par->Chipset & 0xfff0) == 0x0290) || - ((par->Chipset & 0xfff0) == 0x0390)) { + ((par->Chipset & 0xfff0) == 0x0390) || + ((par->Chipset & 0xfff0) == 0x02E0)) { MB = 1; NB = 1; } else { @@ -686,7 +687,7 @@ static void nForceUpdateArbitrationSettings(unsigned VClk, if ((par->Chipset & 0x0FF0) == 0x01A0) { unsigned int uMClkPostDiv; - dev = pci_find_slot(0, 3); + dev = pci_get_bus_and_slot(0, 3); pci_read_config_dword(dev, 0x6C, &uMClkPostDiv); uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf; @@ -694,11 +695,11 @@ static void nForceUpdateArbitrationSettings(unsigned VClk, uMClkPostDiv = 4; MClk = 400000 / uMClkPostDiv; } else { - dev = pci_find_slot(0, 5); + dev = pci_get_bus_and_slot(0, 5); pci_read_config_dword(dev, 0x4c, &MClk); MClk /= 1000; } - + pci_dev_put(dev); pll = NV_RD32(par->PRAMDAC0, 0x0500); M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; @@ -707,19 +708,21 @@ static void nForceUpdateArbitrationSettings(unsigned VClk, sim_data.pix_bpp = (char)pixelDepth; sim_data.enable_video = 0; sim_data.enable_mp = 0; - pci_find_slot(0, 1); + dev = pci_get_bus_and_slot(0, 1); pci_read_config_dword(dev, 0x7C, &sim_data.memory_type); + pci_dev_put(dev); sim_data.memory_type = (sim_data.memory_type >> 12) & 1; sim_data.memory_width = 64; - dev = pci_find_slot(0, 3); + dev = pci_get_bus_and_slot(0, 3); pci_read_config_dword(dev, 0, &memctrl); + pci_dev_put(dev); memctrl >>= 16; if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) { int dimm[3]; - pci_find_slot(0, 2); + dev = pci_get_bus_and_slot(0, 2); pci_read_config_dword(dev, 0x40, &dimm[0]); dimm[0] = (dimm[0] >> 8) & 0x4f; pci_read_config_dword(dev, 0x44, &dimm[1]); @@ -731,6 +734,7 @@ static void nForceUpdateArbitrationSettings(unsigned VClk, printk("nvidiafb: your nForce DIMMs are not arranged " "in optimal banks!\n"); } + pci_dev_put(dev); } sim_data.mem_latency = 3; @@ -960,6 +964,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) if (((par->Chipset & 0xfff0) == 0x0090) || ((par->Chipset & 0xfff0) == 0x01D0) || + ((par->Chipset & 0xfff0) == 0x02E0) || ((par->Chipset & 0xfff0) == 0x0290)) regions = 15; for(i = 0; i < regions; i++) { @@ -1272,6 +1277,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) 0x00100000); break; case 0x0090: + case 0x02E0: case 0x0290: NV_WR32(par->PRAMDAC, 0x0608, NV_RD32(par->PRAMDAC, 0x0608) | @@ -1349,6 +1355,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) } else { if (((par->Chipset & 0xfff0) == 0x0090) || ((par->Chipset & 0xfff0) == 0x01D0) || + ((par->Chipset & 0xfff0) == 0x02E0) || ((par->Chipset & 0xfff0) == 0x0290)) { for (i = 0; i < 60; i++) { NV_WR32(par->PGRAPH, @@ -1400,6 +1407,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) } else { if ((par->Chipset & 0xfff0) == 0x0090 || (par->Chipset & 0xfff0) == 0x01D0 || + (par->Chipset & 0xfff0) == 0x02E0 || (par->Chipset & 0xfff0) == 0x0290) { NV_WR32(par->PGRAPH, 0x0DF0, NV_RD32(par->PFB, 0x0200)); diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index b858897..afe4567 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c @@ -30,16 +30,14 @@ static void nvidia_gpio_setscl(void *data, int state) struct nvidia_par *par = chan->par; u32 val; - VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); - val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0; + val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0; if (state) val |= 0x20; else val &= ~0x20; - VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); - VGA_WR08(par->PCIO, 0x3d5, val | 0x1); + NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01); } static void nvidia_gpio_setsda(void *data, int state) @@ -48,16 +46,14 @@ static void nvidia_gpio_setsda(void *data, int state) struct nvidia_par *par = chan->par; u32 val; - VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); - val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0; + val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0; if (state) val |= 0x10; else val &= ~0x10; - VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); - VGA_WR08(par->PCIO, 0x3d5, val | 0x1); + NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01); } static int nvidia_gpio_getscl(void *data) @@ -66,12 +62,9 @@ static int nvidia_gpio_getscl(void *data) struct nvidia_par *par = chan->par; u32 val = 0; - VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base); - if (VGA_RD08(par->PCIO, 0x3d5) & 0x04) + if (NVReadCrtc(par, chan->ddc_base) & 0x04) val = 1; - val = VGA_RD08(par->PCIO, 0x3d5); - return val; } @@ -81,20 +74,21 @@ static int nvidia_gpio_getsda(void *data) struct nvidia_par *par = chan->par; u32 val = 0; - VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base); - if (VGA_RD08(par->PCIO, 0x3d5) & 0x08) + if (NVReadCrtc(par, chan->ddc_base) & 0x08) val = 1; return val; } -static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name) +static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name, + unsigned int i2c_class) { int rc; strcpy(chan->adapter.name, name); chan->adapter.owner = THIS_MODULE; chan->adapter.id = I2C_HW_B_NVIDIA; + chan->adapter.class = i2c_class; chan->adapter.algo_data = &chan->algo; chan->adapter.dev.parent = &chan->par->pci_dev->dev; chan->algo.setsda = nvidia_gpio_setsda; @@ -127,83 +121,39 @@ static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name) void nvidia_create_i2c_busses(struct nvidia_par *par) { - par->bus = 3; - par->chan[0].par = par; par->chan[1].par = par; par->chan[2].par = par; - par->chan[0].ddc_base = 0x3e; - nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0"); + par->chan[0].ddc_base = 0x36; + nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0", I2C_CLASS_HWMON); - par->chan[1].ddc_base = 0x36; - nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1"); + par->chan[1].ddc_base = 0x3e; + nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1", 0); par->chan[2].ddc_base = 0x50; - nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2"); + nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2", 0); } void nvidia_delete_i2c_busses(struct nvidia_par *par) { - if (par->chan[0].par) - i2c_del_adapter(&par->chan[0].adapter); - par->chan[0].par = NULL; - - if (par->chan[1].par) - i2c_del_adapter(&par->chan[1].adapter); - par->chan[1].par = NULL; - - if (par->chan[2].par) - i2c_del_adapter(&par->chan[2].adapter); - par->chan[2].par = NULL; - -} + int i; -static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan) -{ - u8 start = 0x0; - struct i2c_msg msgs[] = { - { - .addr = 0x50, - .len = 1, - .buf = &start, - }, { - .addr = 0x50, - .flags = I2C_M_RD, - .len = EDID_LENGTH, - }, - }; - u8 *buf; - - if (!chan->par) - return NULL; - - buf = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (!buf) { - dev_warn(&chan->par->pci_dev->dev, "Out of memory!\n"); - return NULL; + for (i = 0; i < 3; i++) { + if (!par->chan[i].par) + continue; + i2c_del_adapter(&par->chan[i].adapter); + par->chan[i].par = NULL; } - msgs[1].buf = buf; - - if (i2c_transfer(&chan->adapter, msgs, 2) == 2) - return buf; - dev_dbg(&chan->par->pci_dev->dev, "Unable to read EDID block.\n"); - kfree(buf); - return NULL; } int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) { struct nvidia_par *par = info->par; u8 *edid = NULL; - int i; - for (i = 0; i < 3; i++) { - /* Do the real work */ - edid = nvidia_do_probe_i2c_edid(&par->chan[conn - 1]); - if (edid) - break; - } + if (par->chan[conn - 1].par) + edid = fb_ddc_read(&par->chan[conn - 1].adapter); if (!edid && conn == 1) { /* try to get from firmware */ diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h index e009d24..68e508d 100644 --- a/drivers/video/nvidia/nv_local.h +++ b/drivers/video/nvidia/nv_local.h @@ -73,9 +73,9 @@ #define NVDmaNext(par, data) \ NV_WR32(&(par)->dmaBase[(par)->dmaCurrent++], 0, (data)) -#define NVDmaStart(par, tag, size) { \ +#define NVDmaStart(info, par, tag, size) { \ if((par)->dmaFree <= (size)) \ - NVDmaWait(par, size); \ + NVDmaWait(info, size); \ NVDmaNext(par, ((size) << 18) | (tag)); \ (par)->dmaFree -= ((size) + 1); \ } diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c index 163a774..73afd7e 100644 --- a/drivers/video/nvidia/nv_of.c +++ b/drivers/video/nvidia/nv_of.c @@ -46,15 +46,15 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) for (dp = NULL; (dp = of_get_next_child(parent, dp)) != NULL;) { - pname = get_property(dp, "name", NULL); + pname = of_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 = get_property(dp, propnames[i], - NULL); + pedid = of_get_property(dp, + propnames[i], NULL); if (pedid != NULL) break; } @@ -65,7 +65,7 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) } if (pedid == NULL) { for (i = 0; propnames[i] != NULL; ++i) { - pedid = get_property(parent, propnames[i], NULL); + pedid = of_get_property(parent, propnames[i], NULL); if (pedid != NULL) break; } diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index eab3e28..707e2c8 100644 --- a/drivers/video/nvidia/nv_setup.c +++ b/drivers/video/nvidia/nv_setup.c @@ -261,7 +261,7 @@ static void nv10GetConfig(struct nvidia_par *par) } #endif - dev = pci_find_slot(0, 1); + dev = pci_get_bus_and_slot(0, 1); if ((par->Chipset & 0xffff) == 0x01a0) { int amt = 0; @@ -276,6 +276,7 @@ static void nv10GetConfig(struct nvidia_par *par) par->RamAmountKBytes = (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10; } + pci_dev_put(dev); par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ? 14318 : 13500; @@ -656,7 +657,7 @@ int NVCommonSetup(struct fb_info *info) par->LVDS = 0; if (par->FlatPanel && par->twoHeads) { NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004); - if (par->PRAMDAC0[0x08b4] & 1) + if (NV_RD32(par->PRAMDAC0, 0x08b4) & 1) par->LVDS = 1; printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS"); } diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h index 86e65de..38f7cc0 100644 --- a/drivers/video/nvidia/nv_type.h +++ b/drivers/video/nvidia/nv_type.h @@ -4,8 +4,9 @@ #include <linux/fb.h> #include <linux/types.h> #include <linux/i2c.h> -#include <linux/i2c-id.h> #include <linux/i2c-algo-bit.h> +#include <linux/mutex.h> +#include <video/vga.h> #define NV_ARCH_04 0x04 #define NV_ARCH_10 0x10 @@ -94,13 +95,15 @@ struct riva_regs { struct nvidia_par { RIVA_HW_STATE SavedReg; RIVA_HW_STATE ModeReg; + RIVA_HW_STATE initial_state; RIVA_HW_STATE *CurrentState; + struct vgastate vgastate; + struct mutex open_lock; u32 pseudo_palette[16]; struct pci_dev *pci_dev; u32 Architecture; u32 CursorStart; int Chipset; - int bus; unsigned long FbAddress; u8 __iomem *FbStart; u32 FbMapSize; @@ -143,6 +146,7 @@ struct nvidia_par { int BlendingPossible; u32 paletteEnabled; u32 forceCRTC; + u32 open_count; u8 DDCBase; #ifdef CONFIG_MTRR struct { diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index b97ec69..41f6365 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -37,7 +37,6 @@ #include "nv_proto.h" #include "nv_dma.h" -#undef CONFIG_FB_NVIDIA_DEBUG #ifdef CONFIG_FB_NVIDIA_DEBUG #define NVTRACE printk #else @@ -200,7 +199,7 @@ static int nvidia_panel_tweak(struct nvidia_par *par, return tweak; } -static void nvidia_vga_protect(struct nvidia_par *par, int on) +static void nvidia_screen_off(struct nvidia_par *par, int on) { unsigned char tmp; @@ -649,7 +648,7 @@ static int nvidiafb_set_par(struct fb_info *info) NVLockUnlock(par, 0); } - nvidia_vga_protect(par, 1); + nvidia_screen_off(par, 1); nvidia_write_regs(par, &par->ModeReg); NVSetStartAddress(par, 0); @@ -687,7 +686,7 @@ static int nvidiafb_set_par(struct fb_info *info) par->cursor_reset = 1; - nvidia_vga_protect(par, 0); + nvidia_screen_off(par, 0); #ifdef CONFIG_BOOTX_TEXT /* Update debug text engine */ @@ -696,6 +695,7 @@ static int nvidiafb_set_par(struct fb_info *info) info->var.bits_per_pixel, info->fix.line_length); #endif + NVLockUnlock(par, 0); NVTRACE_LEAVE(); return 0; } @@ -948,8 +948,80 @@ static int nvidiafb_blank(int blank, struct fb_info *info) return 0; } +/* + * Because the VGA registers are not mapped linearly in its MMIO space, + * restrict VGA register saving and restore to x86 only, where legacy VGA IO + * access is legal. Consequently, we must also check if the device is the + * primary display. + */ +#ifdef CONFIG_X86 +static void save_vga_x86(struct nvidia_par *par) +{ + struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE]; + + if (res && res->flags & IORESOURCE_ROM_SHADOW) { + memset(&par->vgastate, 0, sizeof(par->vgastate)); + par->vgastate.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | + VGA_SAVE_CMAP; + save_vga(&par->vgastate); + } +} + +static void restore_vga_x86(struct nvidia_par *par) +{ + struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE]; + + if (res && res->flags & IORESOURCE_ROM_SHADOW) + restore_vga(&par->vgastate); +} +#else +#define save_vga_x86(x) do {} while (0) +#define restore_vga_x86(x) do {} while (0) +#endif /* X86 */ + +static int nvidiafb_open(struct fb_info *info, int user) +{ + struct nvidia_par *par = info->par; + + mutex_lock(&par->open_lock); + + if (!par->open_count) { + save_vga_x86(par); + nvidia_save_vga(par, &par->initial_state); + } + + par->open_count++; + mutex_unlock(&par->open_lock); + return 0; +} + +static int nvidiafb_release(struct fb_info *info, int user) +{ + struct nvidia_par *par = info->par; + int err = 0; + + mutex_lock(&par->open_lock); + + if (!par->open_count) { + err = -EINVAL; + goto done; + } + + if (par->open_count == 1) { + nvidia_write_regs(par, &par->initial_state); + restore_vga_x86(par); + } + + par->open_count--; +done: + mutex_unlock(&par->open_lock); + return err; +} + static struct fb_ops nvidia_fb_ops = { .owner = THIS_MODULE, + .fb_open = nvidiafb_open, + .fb_release = nvidiafb_release, .fb_check_var = nvidiafb_check_var, .fb_set_par = nvidiafb_set_par, .fb_setcolreg = nvidiafb_setcolreg, @@ -1170,6 +1242,7 @@ static u32 __devinit nvidia_get_arch(struct fb_info *info) case 0x0140: /* GeForce 6600 */ case 0x0160: /* GeForce 6200 */ case 0x01D0: /* GeForce 7200, 7300, 7400 */ + case 0x02E0: /* GeForce 7300 GT */ case 0x0090: /* GeForce 7800 */ case 0x0210: /* GeForce 6800 */ case 0x0220: /* GeForce 6200 */ @@ -1207,7 +1280,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, par = info->par; par->pci_dev = pd; - + mutex_init(&par->open_lock); info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); if (info->pixmap.addr == NULL) diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 9576a55..885b428 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -322,8 +322,8 @@ static void __init offb_init_fb(const char *name, const char *full_name, ioremap(base + 0x7ff000, 0x1000) + 0xcc0; par->cmap_data = par->cmap_adr + 1; par->cmap_type = cmap_m64; - } else if (dp && (device_is_compatible(dp, "pci1014,b7") || - device_is_compatible(dp, "pci1014,21c"))) { + } else if (dp && (of_device_is_compatible(dp, "pci1014,b7") || + of_device_is_compatible(dp, "pci1014,21c"))) { par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); if (par->cmap_adr) par->cmap_type = cmap_gxt2000; @@ -425,27 +425,27 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) const u32 *pp, *addrp, *up; u64 asize; - pp = get_property(dp, "linux,bootx-depth", &len); + pp = of_get_property(dp, "linux,bootx-depth", &len); if (pp == NULL) - pp = get_property(dp, "depth", &len); + pp = of_get_property(dp, "depth", &len); if (pp && len == sizeof(u32)) depth = *pp; - pp = get_property(dp, "linux,bootx-width", &len); + pp = of_get_property(dp, "linux,bootx-width", &len); if (pp == NULL) - pp = get_property(dp, "width", &len); + pp = of_get_property(dp, "width", &len); if (pp && len == sizeof(u32)) width = *pp; - pp = get_property(dp, "linux,bootx-height", &len); + pp = of_get_property(dp, "linux,bootx-height", &len); if (pp == NULL) - pp = get_property(dp, "height", &len); + pp = of_get_property(dp, "height", &len); if (pp && len == sizeof(u32)) height = *pp; - pp = get_property(dp, "linux,bootx-linebytes", &len); + pp = of_get_property(dp, "linux,bootx-linebytes", &len); if (pp == NULL) - pp = get_property(dp, "linebytes", &len); + pp = of_get_property(dp, "linebytes", &len); if (pp && len == sizeof(u32) && (*pp != 0xffffffffu)) pitch = *pp; else @@ -463,9 +463,9 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) * ranges and pick one that is both big enough and if possible encloses * the "address" property. If none match, we pick the biggest */ - up = get_property(dp, "linux,bootx-addr", &len); + up = of_get_property(dp, "linux,bootx-addr", &len); if (up == NULL) - up = get_property(dp, "address", &len); + up = of_get_property(dp, "address", &len); if (up && len == sizeof(u32)) addr_prop = *up; @@ -521,7 +521,7 @@ static int __init offb_init(void) return -ENODEV; /* Check if we have a MacOS display without a node spec */ - if (get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) { + if (of_get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) { /* The old code tried to work out which node was the MacOS * display based on the address. I'm dropping that since the * lack of a node spec only happens with old BootX versions @@ -532,14 +532,14 @@ static int __init offb_init(void) } for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && - get_property(dp, "linux,boot-display", NULL)) { + if (of_get_property(dp, "linux,opened", NULL) && + of_get_property(dp, "linux,boot-display", NULL)) { boot_disp = dp; offb_init_nodriver(dp, 0); } } for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && + if (of_get_property(dp, "linux,opened", NULL) && dp != boot_disp) offb_init_nodriver(dp, 0); } diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 2338716..e64f8b5 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -28,7 +28,6 @@ #include <linux/interrupt.h> #include <linux/fb.h> #include <linux/init.h> -#include <linux/pci.h> #include <linux/nvram.h> #include <asm/io.h> #include <asm/prom.h> diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index a560a22..ab5e668 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -81,8 +81,6 @@ static int lowvsync; struct pm2fb_par { pm2type_t type; /* Board type */ - u32 fb_size; /* framebuffer memory size */ - unsigned char __iomem *v_fb; /* virtual address of frame buffer */ unsigned char __iomem *v_regs;/* virtual address of p_regs */ u32 memclock; /* memclock */ u32 video; /* video flags before blanking */ @@ -103,7 +101,7 @@ static struct fb_fix_screeninfo pm2fb_fix __devinitdata = { .xpanstep = 1, .ypanstep = 1, .ywrapstep = 0, - .accel = FB_ACCEL_NONE, + .accel = FB_ACCEL_3DLABS_PERMEDIA2, }; /* @@ -302,10 +300,10 @@ static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn, s32 delta = 1000; *mm = *nn = *pp = 0; - for (n = 1; n; n++) { - for ( m = 1; m; m++) { + for ( m = 1; m < 128; m++) { + for (n = 2 * m + 1; n; n++) { for ( p = 0; p < 2; p++) { - f = PM2_REFERENCE_CLOCK * n / (m * (1 << (p + 1))); + f = ( PM2_REFERENCE_CLOCK >> ( p + 1 )) * n / m; if ( clk > f - delta && clk < f + delta ) { delta = ( clk > f ) ? clk - f : f - clk; *mm=m; @@ -462,21 +460,43 @@ static void set_memclock(struct pm2fb_par* par, u32 clk) int i; unsigned char m, n, p; - pm2_mnp(clk, &m, &n, &p); - WAIT_FIFO(par, 10); - pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6); - wmb(); - pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m); - pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n); - wmb(); - pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p); - wmb(); - pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS); - rmb(); - for (i = 256; - i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED); - i--) - ; + switch (par->type) { + case PM2_TYPE_PERMEDIA2V: + pm2v_mnp(clk/2, &m, &n, &p); + WAIT_FIFO(par, 8); + pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_MCLK_CONTROL >> 8); + pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 0); + wmb(); + pm2v_RDAC_WR(par, PM2VI_RD_MCLK_PRESCALE, m); + pm2v_RDAC_WR(par, PM2VI_RD_MCLK_FEEDBACK, n); + pm2v_RDAC_WR(par, PM2VI_RD_MCLK_POSTSCALE, p); + wmb(); + pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 1); + rmb(); + for (i = 256; + i && !(pm2_RDAC_RD(par, PM2VI_RD_MCLK_CONTROL) & 2); + i--) + ; + pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0); + break; + case PM2_TYPE_PERMEDIA2: + pm2_mnp(clk, &m, &n, &p); + WAIT_FIFO(par, 10); + pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6); + wmb(); + pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m); + pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n); + wmb(); + pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p); + wmb(); + pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS); + rmb(); + for (i = 256; + i && !(pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED); + i--) + ; + break; + } } static void set_pixclock(struct pm2fb_par* par, u32 clk) @@ -623,6 +643,8 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) return -EINVAL; } + var->transp.offset = 0; + var->transp.length = 0; switch(var->bits_per_pixel) { case 8: var->red.length = var->green.length = var->blue.length = 8; @@ -1017,6 +1039,131 @@ static int pm2fb_blank(int blank_mode, struct fb_info *info) return 0; } +static int pm2fb_sync(struct fb_info *info) +{ + struct pm2fb_par *par = info->par; + + WAIT_FIFO(par, 1); + pm2_WR(par, PM2R_SYNC, 0); + mb(); + do { + while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0) + udelay(10); + rmb(); + } while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC)); + + return 0; +} + +/* + * block operation. copy=0: rectangle fill, copy=1: rectangle copy. + */ +static void pm2fb_block_op(struct fb_info* info, int copy, + s32 xsrc, s32 ysrc, + s32 x, s32 y, s32 w, s32 h, + u32 color) { + struct pm2fb_par *par = info->par; + + if (!w || !h) + return; + WAIT_FIFO(par, 6); + pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE | + PM2F_CONFIG_FB_READ_SOURCE_ENABLE); + pm2_WR(par, PM2R_FB_PIXEL_OFFSET, 0); + if (copy) + pm2_WR(par, PM2R_FB_SOURCE_DELTA, + ((ysrc-y) & 0xfff) << 16 | ((xsrc-x) & 0xfff)); + else + pm2_WR(par, PM2R_FB_BLOCK_COLOR, color); + pm2_WR(par, PM2R_RECTANGLE_ORIGIN, (y << 16) | x); + pm2_WR(par, PM2R_RECTANGLE_SIZE, (h << 16) | w); + wmb(); + pm2_WR(par, PM2R_RENDER,PM2F_RENDER_RECTANGLE | + (x<xsrc ? PM2F_INCREASE_X : 0) | + (y<ysrc ? PM2F_INCREASE_Y : 0) | + (copy ? 0 : PM2F_RENDER_FASTFILL)); +} + +static void pm2fb_fillrect (struct fb_info *info, + const struct fb_fillrect *region) +{ + struct fb_fillrect modded; + int vxres, vyres; + u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ? + ((u32*)info->pseudo_palette)[region->color] : region->color; + + if (info->state != FBINFO_STATE_RUNNING) + return; + if ((info->flags & FBINFO_HWACCEL_DISABLED) || + region->rop != ROP_COPY ) { + cfb_fillrect(info, region); + return; + } + + vxres = info->var.xres_virtual; + vyres = info->var.yres_virtual; + + memcpy(&modded, region, sizeof(struct fb_fillrect)); + + if(!modded.width || !modded.height || + modded.dx >= vxres || modded.dy >= vyres) + return; + + if(modded.dx + modded.width > vxres) + modded.width = vxres - modded.dx; + if(modded.dy + modded.height > vyres) + modded.height = vyres - modded.dy; + + if(info->var.bits_per_pixel == 8) + color |= color << 8; + if(info->var.bits_per_pixel <= 16) + color |= color << 16; + + if(info->var.bits_per_pixel != 24) + pm2fb_block_op(info, 0, 0, 0, + modded.dx, modded.dy, + modded.width, modded.height, color); + else + cfb_fillrect(info, region); +} + +static void pm2fb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + struct fb_copyarea modded; + u32 vxres, vyres; + + if (info->state != FBINFO_STATE_RUNNING) + return; + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_copyarea(info, area); + return; + } + + memcpy(&modded, area, sizeof(struct fb_copyarea)); + + vxres = info->var.xres_virtual; + vyres = info->var.yres_virtual; + + if(!modded.width || !modded.height || + modded.sx >= vxres || modded.sy >= vyres || + modded.dx >= vxres || modded.dy >= vyres) + return; + + if(modded.sx + modded.width > vxres) + modded.width = vxres - modded.sx; + if(modded.dx + modded.width > vxres) + modded.width = vxres - modded.dx; + if(modded.sy + modded.height > vyres) + modded.height = vyres - modded.sy; + if(modded.dy + modded.height > vyres) + modded.height = vyres - modded.dy; + + pm2fb_block_op(info, 1, modded.sx, modded.sy, + modded.dx, modded.dy, + modded.width, modded.height, 0); +} + /* ------------ Hardware Independent Functions ------------ */ /* @@ -1030,9 +1177,10 @@ static struct fb_ops pm2fb_ops = { .fb_setcolreg = pm2fb_setcolreg, .fb_blank = pm2fb_blank, .fb_pan_display = pm2fb_pan_display, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, + .fb_fillrect = pm2fb_fillrect, + .fb_copyarea = pm2fb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_sync = pm2fb_sync, }; /* @@ -1119,38 +1267,47 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, 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_config == 0x259fffff) { + default_par->memclock = CVPPC_MEMCLOCK; default_par->mem_control=0; default_par->boot_address=0x20; default_par->mem_config=0xe6002021; - default_par->memclock=100000; + if (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->memclock=70000; + } + if (pdev->subsystem_vendor == 0x3d3d && + pdev->subsystem_device == 0x0100) { + 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 3dlabs reference board\n"); + DPRINTK("Initializing card timings manually...\n"); + default_par->memclock=74894; + } } /* 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: - default_par->fb_size=0x200000; + pm2fb_fix.smem_len=0x200000; break; case PM2F_MEM_BANKS_2: - default_par->fb_size=0x400000; + pm2fb_fix.smem_len=0x400000; break; case PM2F_MEM_BANKS_3: - default_par->fb_size=0x600000; + pm2fb_fix.smem_len=0x600000; break; case PM2F_MEM_BANKS_4: - default_par->fb_size=0x800000; + pm2fb_fix.smem_len=0x800000; break; } - default_par->memclock = CVPPC_MEMCLOCK; pm2fb_fix.smem_start = pci_resource_start(pdev, 1); - pm2fb_fix.smem_len = default_par->fb_size; /* Linear frame buffer - request region and map it. */ if ( !request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len, @@ -1158,9 +1315,9 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, printk(KERN_WARNING "pm2fb: Can't reserve smem.\n"); goto err_exit_mmio; } - info->screen_base = default_par->v_fb = + info->screen_base = ioremap_nocache(pm2fb_fix.smem_start, pm2fb_fix.smem_len); - if ( !default_par->v_fb ) { + if ( !info->screen_base ) { printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n"); release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len); goto err_exit_mmio; @@ -1170,7 +1327,9 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, info->fix = pm2fb_fix; info->pseudo_palette = default_par->palette; info->flags = FBINFO_DEFAULT | - FBINFO_HWACCEL_YPAN; + FBINFO_HWACCEL_YPAN | + FBINFO_HWACCEL_COPYAREA | + FBINFO_HWACCEL_FILLRECT; if (!mode) mode = "640x480@60"; @@ -1180,13 +1339,13 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, info->var = pm2fb_var; if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) - goto err_exit_all; + goto err_exit_both; if (register_framebuffer(info) < 0) - goto err_exit_both; + goto err_exit_all; printk(KERN_INFO "fb%d: %s frame buffer device, memory = %dK.\n", - info->node, info->fix.id, default_par->fb_size / 1024); + info->node, info->fix.id, pm2fb_fix.smem_len / 1024); /* * Our driver data @@ -1242,6 +1401,9 @@ static struct pci_device_id pm2fb_id_table[] = { { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V, PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 }, + { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NOT_DEFINED_VGA << 8, + 0xff00, 0 }, { 0, } }; diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index bd787e8..6c4dfcb0 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c @@ -1,55 +1,25 @@ /* * linux/drivers/video/pm3fb.c -- 3DLabs Permedia3 frame buffer device - * - * Copyright (C) 2001 Romain Dolbeau <dolbeau@irisa.fr> + * + * Copyright (C) 2001 Romain Dolbeau <romain@dolbeau.org>. + * + * Ported to 2.6 kernel on 1 May 2007 by Krzysztof Helt <krzysztof.h1@wp.pl> + * based on pm2fb.c + * * Based on code written by: - * Sven Luther, <luther@dpt-info.u-strasbg.fr> - * Alan Hourihane, <alanh@fairlite.demon.co.uk> - * Russell King, <rmk@arm.linux.org.uk> + * Sven Luther, <luther@dpt-info.u-strasbg.fr> + * Alan Hourihane, <alanh@fairlite.demon.co.uk> + * Russell King, <rmk@arm.linux.org.uk> * Based on linux/drivers/video/skeletonfb.c: * Copyright (C) 1997 Geert Uytterhoeven * Based on linux/driver/video/pm2fb.c: - * Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) - * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) + * Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) + * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. * - * $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $ - * - * CHANGELOG: - * Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update. - * Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2. - * Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16. - * Thu Sep 20 10:24:42 MET DST 2001, v 1.4.9: sync bug fix, preliminary flatpanel support, better timings. - * Tue Aug 28 10:13:01 MET DST 2001, v 1.4.8: memory timings check, minor bug fixes. - * Wed Jul 18 19:06:14 CEST 2001, v 1.4.7: Mode fix (800x600-100, 1024x768-100 changed), using HW panning + accel bug fix. - * Mon Jun 25 10:33:56 MET DST 2001, v 1.4.6: Depth 12 fix, chip reset ioctl, moved memory erase ioctl to DEBUG. - * Wed Jun 20 11:13:08 MET DST 2001, v 1.4.5: Fixed missing blinking cursor in 8bpp, code cleaning, memory erase IOCTL. - * Mon Jun 18 16:00:27 CEST 2001, v 1.4.4: Depth 12 (RGBA 4444) support, code cleaning. - * Fri Jun 15 13:53:01 CEST 2001, v 1.4.3: Removed warnings, depth 15 support, add 'depth' option. - * Thu Jun 14 10:13:52 MET DST 2001, v 1.4.2: Fixed depth switching bug, preliminary 15bpp (RGB5551) support. - * Thu Apr 12 11:16:45 MET DST 2001, v 1.4.1B: Doc updates. - * Fri Apr 6 11:12:53 MET DST 2001, v 1.4.1: Configure.help, minor cleanup - * Thu Mar 29 10:56:50 MET DST 2001, v 1.4.0: Module & module options support (note: linux patch changed, 2.2.19 added). - * Thu Mar 15 15:30:31 MET 2001, v 1.3.2: Fixed mirroring bug on little-endian. - * Wed Mar 14 21:25:54 CET 2001, v 1.3.1: Fixed bug in BlockMove (_bmov). - * Tue Mar 13 10:53:19 MET 2001, v 1.3.0: Character drawing hardware support (in all width between 1 and 16), fixes. - * Thu Mar 8 10:20:16 MET 2001, v 1.2.2: Better J2000 support, "font:" option. - * Tue Mar 6 21:25:04 CET 2001, v 1.2.1: Better acceleration support. - * Mon Mar 5 21:54:17 CET 2001, v 1.2.0: Partial acceleration support (clear & bmove) - * Mon Mar 5 12:52:15 CET 2001, v 1.1.3: Big pan_display fix. - * Sun Mar 4 22:21:50 CET 2001, v 1.1.2: (numerous) bug fixes. - * Fri Mar 2 15:54:07 CET 2001, v 1.1.1: Might have Appian J2000 support, resource mangement in 2.4 - * Wed Feb 28 18:21:35 CET 2001, v 1.1.0: Might have multiple boards support (added, but not yest tested) - * Tue Feb 27 17:31:12 CET 2001, v 1.0.6: fixes boot-time mode select, add more default mode - * Tue Feb 27 14:01:36 CET 2001, v 1.0.5: fixes (1.0.4 was broken for 2.2), cleaning up - * Mon Feb 26 23:17:36 CET 2001, v 1.0.4: preliminary 2.4.x support, dropped (useless on pm3) partial product, more OF fix - * Mon Feb 26 20:59:05 CET 2001, v 1.0.3: No more shadow register (and wasted memory), endianess fix, use OF-preset resolution by default - * Wed Feb 21 22:09:30 CET 2001, v 1.0.2: Code cleaning for future multiboard support, better OF support, bugs fix - * Wed Feb 21 19:58:56 CET 2001, v 1.0.1: OpenFirmware support, fixed memory detection, better debug support, code cleaning - * Wed Feb 21 14:47:06 CET 2001, v 1.0.0: First working version */ #include <linux/module.h> @@ -58,856 +28,155 @@ #include <linux/string.h> #include <linux/mm.h> #include <linux/slab.h> -#include <linux/vmalloc.h> #include <linux/delay.h> -#include <linux/interrupt.h> #include <linux/fb.h> #include <linux/init.h> #include <linux/pci.h> -#include <linux/ioport.h> -#include <linux/ctype.h> - -#include <video/fbcon.h> -#include <video/fbcon-mfb.h> -#include <video/fbcon-cfb2.h> -#include <video/fbcon-cfb4.h> -#include <video/fbcon-cfb8.h> -#include <video/fbcon-cfb16.h> -#include <video/fbcon-cfb24.h> -#include <video/fbcon-cfb32.h> -#include <video/pm3fb.h> -#include <asm/io.h> -#include <asm/uaccess.h> +#include <video/pm3fb.h> -#ifdef CONFIG_FB_OF -#include <asm/prom.h> +#if !defined(CONFIG_PCI) +#error "Only generic PCI cards supported." #endif -/* ************************************* */ -/* ***** The various "global" data ***** */ -/* ************************************* */ - -/* those will need a rework for multiple board support */ -/* Driver name */ -static const char permedia3_name[16] = "Permedia3"; - -/* the fb_par struct, mandatory */ -struct pm3fb_par { - u32 pixclock; /* pixclock in KHz */ - - u32 width; /* width of virtual screen */ - u32 height; /* height of virtual screen */ - - u32 hsstart; /* horiz. sync start */ - u32 hsend; /* horiz. sync end */ - u32 hbend; /* horiz. blank end (also gate end) */ - u32 htotal; /* total width (w/ sync & blank) */ - - u32 vsstart; /* vert. sync start */ - u32 vsend; /* vert. sync end */ - u32 vbend; /* vert. blank end */ - u32 vtotal; /* total height (w/ sync & blank) */ - - u32 stride; /* screen stride */ - u32 base; /* screen base (xoffset+yoffset) in 128 bits unit */ - /* NOTE : unlike other pm3 stuff above, stored *after* shiftbpp. don't ask */ - u32 depth; /* screen depth (8, 12, 15, 16 or 32) */ - u32 video; /* video control (hsync,vsync) */ -}; - -/* memory timings */ -struct pm3fb_timings -{ - unsigned long caps; - unsigned long timings; - unsigned long control; - unsigned long refresh; - unsigned long powerdown; -}; -typedef enum pm3fb_timing_result { pm3fb_timing_ok, pm3fb_timing_problem, pm3fb_timing_retry } pm3fb_timing_result; -#define PM3FB_UNKNOWN_TIMING_VALUE ((unsigned long)-1) -#define PM3FB_UNKNOWN_TIMINGS { PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE } - -/* the fb_info struct, mandatory */ -struct pm3fb_info { - struct fb_info_gen gen; - unsigned long board_num; /* internal board number */ - unsigned long use_current; - struct pm3fb_par *current_par; - struct pci_dev *dev; /* PCI device */ - unsigned long board_type; /* index in the cardbase */ - unsigned char *fb_base; /* framebuffer memory base */ - u32 fb_size; /* framebuffer memory size */ - unsigned char *p_fb; /* physical address of frame buffer */ - unsigned char *v_fb; /* virtual address of frame buffer */ - unsigned char *pIOBase; /* physical address of registers region, must be rg_base or rg_base+PM2_REGS_SIZE depending on the host endianness */ - unsigned char *vIOBase; /* address of registers after ioremap() */ - struct { - u8 transp; - u8 red; - u8 green; - u8 blue; - } palette[256]; - union { -#ifdef FBCON_HAS_CFB16 - u16 cmap12[16]; /* RGBA 4444 */ - u16 cmap15[16]; /* RGBA 5551 */ - u16 cmap16[16]; /* RGBA 5650 */ -#endif -#ifdef FBCON_HAS_CFB32 - u32 cmap32[16]; +#undef PM3FB_MASTER_DEBUG +#ifdef PM3FB_MASTER_DEBUG +#define DPRINTK(a,b...) printk(KERN_DEBUG "pm3fb: %s: " a, __FUNCTION__ , ## b) +#else +#define DPRINTK(a,b...) #endif - } cmap; - struct pm3fb_timings memt; -}; - -/* regular resolution database*/ -static struct { - char name[16]; - struct pm3fb_par user_mode; -} mode_base[] __initdata = { - { - "default-800x600", { - 49500, 800, 600, 16, 96, 256, 1056, 1, 4, 25, 625, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, { - "1024x768-74", { - 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38, - 806, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, { - "1024x768-74-32", { - 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38, - 806, 1024, 0, 32, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_32BIT}}, -/* Generated mode : "1600x1024", for the SGI 1600SW flat panel*/ - { - "SGI1600SW", { - 108000, 1600, 1024, 16, 56, 104, 1704, 3, 6, 32, - 1056, 1600, 0, 8, - PM3VideoControl_ENABLE| - PM3VideoControl_HSYNC_ACTIVE_LOW|PM3VideoControl_VSYNC_ACTIVE_LOW| - PM3VideoControl_PIXELSIZE_32BIT}}, -/* ##### auto-generated mode, by fbtimings2pm3 */ -/* Generated mode : "640x480-60" */ - { - "640x480-60", { - 25174, 640, 480, 16, 112, 160, 800, 10, 12, 45, - 525, 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "640x480-72" */ - { - "640x480-72", { - 31199, 640, 480, 24, 64, 192, 832, 9, 12, 40, 520, - 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "640x480-75" */ - { - "640x480-75", { - 31499, 640, 480, 16, 80, 200, 840, 1, 4, 20, 500, - 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "640x480-90" */ - { - "640x480-90", { - 39909, 640, 480, 32, 72, 192, 832, 25, 39, 53, 533, - 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "640x480-100" */ - { - "640x480-100", { - 44899, 640, 480, 32, 160, 208, 848, 22, 34, 51, - 531, 640, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-48-lace" */ -/* INTERLACED NOT SUPPORTED - {"800x600-48-lace", {35999, 800, 600, 80, 208, 264, 1064, 11, 23, 102, 702, 800, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "800x600-56" */ - { - "800x600-56", { - 35999, 800, 600, 24, 96, 224, 1024, 1, 3, 25, 625, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-60" */ - { - "800x600-60", { - 40000, 800, 600, 40, 168, 256, 1056, 1, 5, 28, 628, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-70" */ - { - "800x600-70", { - 44899, 800, 600, 24, 168, 208, 1008, 9, 21, 36, - 636, 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-72" */ - { - "800x600-72", { - 50000, 800, 600, 56, 176, 240, 1040, 37, 43, 66, - 666, 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-75" */ - { - "800x600-75", { - 49497, 800, 600, 16, 96, 256, 1056, 1, 4, 25, 625, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-90" */ - { - "800x600-90", { - 56637, 800, 600, 8, 72, 192, 992, 8, 19, 35, 635, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "800x600-100", from /etc/fb.modes */ -/* DISABLED, hsstart == 0 - { - "800x600-100", { - 67499, 800, 600, 0, 64, 280, 1080, 7, 11, 25, 625, - 800, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -*/ -/* Generated mode : "800x600-100", from ??? */ - { - "800x600-100", { - 69650, 800, 600, 64, 128, 288, 1088, 4, 10, 40, 640, 800, 0, 8, - PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_LOW| - PM3VideoControl_VSYNC_ACTIVE_LOW|PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-43-lace" */ -/* INTERLACED NOT SUPPORTED - {"1024x768-43-lace", {44899, 1024, 768, 8, 184, 240, 1264, 1, 9, 49, 817, 1024, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1024x768-60" */ - { - "1024x768-60", { - 64998, 1024, 768, 24, 160, 320, 1344, 3, 9, 38, - 806, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-70" */ - { - "1024x768-70", { - 74996, 1024, 768, 24, 160, 304, 1328, 3, 9, 38, - 806, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-72" */ - { - "1024x768-72", { - 74996, 10224, 768, 24, 160, 264, 10488, 3, 9, 38, - 806, 10224, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-75" */ - { - "1024x768-75", { - 78746, 1024, 768, 16, 112, 288, 1312, 1, 4, 32, - 800, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-90" */ - { - "1024x768-90", { - 100000, 1024, 768, 0, 96, 288, 1312, 21, 36, 77, - 845, 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1024x768-100", from /etc/fb.modes */ -/* DISABLED, vsstart == 0 - { - "1024x768-100", { - 109998, 1024, 768, 0, 88, 368, 1392, 0, 8, 24, 792, - 1024, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -*/ -/* Generated mode : "1024x768-100", from ??? */ - { - "1024x768-100", { - 115500, 1024, 768, 32, 224, 416, 1440, 3, 13, 34, 802, 1024, 0, 8, - PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_LOW| - PM3VideoControl_VSYNC_ACTIVE_LOW|PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1152x864-43-lace" */ -/* INTERLACED NOT SUPPORTED - {"1152x864-43-lace", {64998, 1152, 864, 72, 200, 264, 1416, 78, 87, 191, 1055, 1152, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1152x864-47-lace" */ -/* INTERLACED NOT SUPPORTED - {"1152x864-47-lace", {64998, 1152, 864, 88, 216, 296, 1448, 30, 39, 83, 947, 1152, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1152x864-60" */ - { - "1152x864-60", { - 80000, 1152, 864, 64, 176, 304, 1456, 6, 11, 52, - 916, 1152, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1152x864-70" */ - { - "1152x864-70", { - 100000, 1152, 864, 40, 192, 360, 1512, 13, 24, 81, - 945, 1152, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1152x864-75" */ - { - "1152x864-75", { - 109998, 1152, 864, 24, 168, 312, 1464, 45, 53, 138, - 1002, 1152, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1152x864-80" */ - { - "1152x864-80", { - 109998, 1152, 864, 16, 128, 288, 1440, 30, 37, 94, - 958, 1152, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1280x1024-43-lace" */ -/* INTERLACED NOT SUPPORTED - {"1280x1024-43-lace", {80000, 1024, 1024, 80, 160, 320, 1344, 50, 60, 125, 1149, 1024, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1280x1024-47-lace" */ -/* INTERLACED NOT SUPPORTED - {"1280x1024-47-lace", {80000, 1280, 1024, 80, 160, 320, 1600, 1, 11, 29, 1053, 1280, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, - INTERLACED NOT SUPPORTED */ -/* Generated mode : "1280x1024-60" */ - { - "1280x1024-60", { - 107991, 1280, 1024, 48, 160, 408, 1688, 1, 4, 42, - 1066, 1280, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1280x1024-70" */ - { - "1280x1024-70", { - 125992, 1280, 1024, 80, 192, 408, 1688, 1, 6, 42, - 1066, 1280, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1280x1024-74" */ - { - "1280x1024-74", { - 134989, 1280, 1024, 32, 176, 432, 1712, 0, 30, 40, - 1064, 1280, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1280x1024-75" */ - { - "1280x1024-75", { - 134989, 1280, 1024, 16, 160, 408, 1688, 1, 4, 42, - 1066, 1280, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_HIGH - | - PM3VideoControl_VSYNC_ACTIVE_HIGH - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1600x1200-60" */ - { - "1600x1200-60", { - 155981, 1600, 1200, 32, 192, 448, 2048, 10, 18, 70, - 1270, 1600, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1600x1200-66" */ - { - "1600x1200-66", { - 171998, 1600, 1200, 40, 176, 480, 2080, 3, 6, 53, - 1253, 1600, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* Generated mode : "1600x1200-76" */ - { - "1600x1200-76", { - 197980, 1600, 1200, 40, 176, 480, 2080, 3, 8, 50, - 1250, 1600, 0, 8, - PM3VideoControl_ENABLE | - PM3VideoControl_HSYNC_ACTIVE_LOW - | - PM3VideoControl_VSYNC_ACTIVE_LOW - | PM3VideoControl_PIXELSIZE_8BIT}}, -/* ##### end of auto-generated mode */ - { - "\0",} -}; -/* more mandatory stuff (see skeletonfb.c + framebuffer driver HOWTO */ -static struct pm3fb_info fb_info[PM3_MAX_BOARD]; -static struct pm3fb_par current_par[PM3_MAX_BOARD]; -static int current_par_valid[PM3_MAX_BOARD]; -/* to allow explicit filtering of board */ -short bus[PM3_MAX_BOARD]; -short slot[PM3_MAX_BOARD]; -short func[PM3_MAX_BOARD]; -short disable[PM3_MAX_BOARD]; -short noaccel[PM3_MAX_BOARD]; -char fontn[PM3_MAX_BOARD][PM3_FONTNAME_SIZE]; -short depth[PM3_MAX_BOARD]; -short flatpanel[PM3_MAX_BOARD]; -static struct display disp[PM3_MAX_BOARD]; -static char g_options[PM3_OPTIONS_SIZE] __initdata = "pm3fb,dummy"; -short printtimings = 0; -short forcesize[PM3_MAX_BOARD]; - -/* ********************* */ -/* ***** prototype ***** */ -/* ********************* */ -/* card-specific */ -static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info); -/* permedia3-specific */ -static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info); -static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info); -static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info); -static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info, - unsigned long r); -static unsigned long pm3fb_CalculateClock(struct pm3fb_info *l_fb_info, unsigned long reqclock, /* In kHz units */ - unsigned long refclock, /* In kHz units */ - unsigned char *prescale, /* ClkPreScale */ - unsigned char *feedback, /* ClkFeedBackScale */ - unsigned char *postscale - /* ClkPostScale */ ); -static void pm3fb_clear_memory(struct pm3fb_info *l_fb_info, u32 cc); -static void pm3fb_clear_colormap(struct pm3fb_info *l_fb_info, unsigned char r, unsigned char g, unsigned char b); -static void pm3fb_common_init(struct pm3fb_info *l_fb_info); -static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info, - unsigned long depth, int v); -static int pm3fb_Unshiftbpp(struct pm3fb_info *l_fb_info, - unsigned long depth, int v); -static void pm3fb_mapIO(struct pm3fb_info *l_fb_info); -static void pm3fb_unmapIO(struct pm3fb_info *l_fb_info); -#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2) -static void pm3fb_show_cur_mode(struct pm3fb_info *l_fb_info); -#endif -static void pm3fb_show_cur_timing(struct pm3fb_info *l_fb_info); -static void pm3fb_write_mode(struct pm3fb_info *l_fb_info); -static void pm3fb_read_mode(struct pm3fb_info *l_fb_info, - struct pm3fb_par *curpar); -static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info); -/* accelerated permedia3-specific */ -#ifdef PM3FB_USE_ACCEL -static void pm3fb_wait_pm3(struct pm3fb_info *l_fb_info); -static void pm3fb_init_engine(struct pm3fb_info *l_fb_info); -#ifdef FBCON_HAS_CFB32 -static void pm3fb_cfb32_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width); -static void pm3fb_cfb32_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only); -#endif /* FBCON_HAS_CFB32 */ -#ifdef FBCON_HAS_CFB16 -static void pm3fb_cfb16_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width); -static void pm3fb_cfb16_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only); -#endif /* FBCON_HAS_CFB16 */ -#ifdef FBCON_HAS_CFB8 -static void pm3fb_cfb8_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width); -static void pm3fb_cfb8_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only); -#endif /* FBCON_HAS_CFB8 */ -#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) -static void pm3fb_cfbX_bmove(struct display *p, - int sy, int sx, - int dy, int dx, int height, int width); -static void pm3fb_cfbX_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx); -static void pm3fb_cfbX_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, - int xx); -static void pm3fb_cfbX_revc(struct display *p, int xx, int yy); -#endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */ -#endif /* PM3FB_USE_ACCEL */ -/* pre-init */ -static void pm3fb_mode_setup(char *mode, unsigned long board_num); -static void pm3fb_pciid_setup(char *pciid, unsigned long board_num); -static char *pm3fb_boardnum_setup(char *options, unsigned long *bn); -static void pm3fb_real_setup(char *options); -/* fbdev */ -static int pm3fb_encode_fix(struct fb_fix_screeninfo *fix, - const void *par, struct fb_info_gen *info); -static int pm3fb_decode_var(const struct fb_var_screeninfo *var, - void *par, struct fb_info_gen *info); -static void pm3fb_encode_depth(struct fb_var_screeninfo *var, long d); -static int pm3fb_encode_var(struct fb_var_screeninfo *var, - const void *par, struct fb_info_gen *info); -static void pm3fb_get_par(void *par, struct fb_info_gen *info); -static void pm3fb_set_par(const void *par, struct fb_info_gen *info); -static void pm3fb_set_color(struct pm3fb_info *l_fb_info, - unsigned char regno, unsigned char r, - unsigned char g, unsigned char b); -static int pm3fb_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info); -static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info); -static int pm3fb_blank(int blank_mode, struct fb_info_gen *info); -static void pm3fb_set_disp(const void *par, struct display *disp, - struct fb_info_gen *info); -static void pm3fb_detect(void); -static int pm3fb_pan_display(const struct fb_var_screeninfo *var, - struct fb_info_gen *info); -static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg); - - -/* the struct that hold them together */ -struct fbgen_hwswitch pm3fb_switch = { - pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var, - pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg, - pm3fb_pan_display, pm3fb_blank, pm3fb_set_disp -}; +/* + * Driver data + */ +static char *mode_option __devinitdata; -static struct fb_ops pm3fb_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_setcolreg = pm3fb_setcolreg, - .fb_pan_display =fbgen_pan_display, - .fb_blank = fbgen_blank, - .fb_ioctl = pm3fb_ioctl, -}; +/* + * If your driver supports multiple boards, you should make the + * below data types arrays, or allocate them dynamically (using kmalloc()). + */ -#ifdef PM3FB_USE_ACCEL -#ifdef FBCON_HAS_CFB32 -static struct display_switch pm3fb_cfb32 = { - fbcon_cfb32_setup, pm3fb_cfbX_bmove, pm3fb_cfb32_clear, - pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc, - NULL /* cursor() */ , NULL /* set_font() */ , - pm3fb_cfb32_clear_margins, - FONTWIDTHRANGE(1, 16) /* true only if accelerated... */ -}; -#endif /* FBCON_HAS_CFB32 */ -#ifdef FBCON_HAS_CFB16 -static struct display_switch pm3fb_cfb16 = { - fbcon_cfb16_setup, pm3fb_cfbX_bmove, pm3fb_cfb16_clear, - pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc, - NULL /* cursor() */ , NULL /* set_font() */ , - pm3fb_cfb16_clear_margins, - FONTWIDTHRANGE(1, 16) /* true only if accelerated... */ -}; -#endif /* FBCON_HAS_CFB16 */ -#ifdef FBCON_HAS_CFB8 -static struct display_switch pm3fb_cfb8 = { - fbcon_cfb8_setup, pm3fb_cfbX_bmove, pm3fb_cfb8_clear, - pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc, - NULL /* cursor() */ , NULL /* set_font() */ , - pm3fb_cfb8_clear_margins, - FONTWIDTHRANGE(1, 16) /* true only if accelerated... */ -}; -#endif /* FBCON_HAS_CFB8 */ -#endif /* PM3FB_USE_ACCEL */ - -/* ****************************** */ -/* ***** card-specific data ***** */ -/* ****************************** */ -struct pm3fb_card_timings { - unsigned long memsize; /* 0 for last value (i.e. default) */ - struct pm3fb_timings memt; +/* + * This structure defines the hardware state of the graphics card. Normally + * you place this in a header file in linux/include/video. This file usually + * also includes register information. That allows other driver subsystems + * and userland applications the ability to use the same header file to + * avoid duplicate work and easy porting of software. + */ +struct pm3_par { + unsigned char __iomem *v_regs;/* virtual address of p_regs */ + u32 video; /* video flags before blanking */ + u32 base; /* screen base (xoffset+yoffset) in 128 bits unit */ + u32 palette[16]; }; -static struct pm3fb_card_timings t_FormacProFormance3[] = { - { 16, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} }, - { 0, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} } /* from 16 MB PF3 */ +/* + * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo + * if we don't use modedb. If we do use modedb see pm3fb_init how to use it + * to get a fb_var_screeninfo. Otherwise define a default var as well. + */ +static struct fb_fix_screeninfo pm3fb_fix __devinitdata = { + .id = "Permedia3", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_PSEUDOCOLOR, + .xpanstep = 1, + .ypanstep = 1, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, }; -static struct pm3fb_card_timings t_AppianJeronimo2000[] = { - { 32, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} }, - { 0, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} } /* from 32MB J2000 */ -}; +/* + * Utility functions + */ -static struct pm3fb_card_timings t_3DLabsOxygenVX1[] = { - { 32, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} }, - { 0, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} } /* from 32MB VX1 */ -}; +static inline u32 PM3_READ_REG(struct pm3_par *par, s32 off) +{ + return fb_readl(par->v_regs + off); +} -static struct { - char cardname[32]; /* recognized card name */ - u16 subvendor; /* subvendor of the card */ - u16 subdevice; /* subdevice of the card */ - u8 func; /* function of the card to which the extra init apply */ - void (*specific_setup)(struct pm3fb_info *l_fb_info); /* card/func specific setup, done before _any_ FB access */ - struct pm3fb_card_timings *c_memt; /* defauls timings for the boards */ -} cardbase[] = { - { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, NULL }, - { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL, - t_AppianJeronimo2000 - }, - { "Appian Jeronimo 2000 head 2", 0x1097, 0x3d32, 2, pm3fb_j2000_setup, - t_AppianJeronimo2000 - }, - { "Formac ProFormance 3", PCI_VENDOR_ID_3DLABS, 0x000a, 0, NULL, /* Formac use 3DLabs ID ?!? */ - t_FormacProFormance3 - }, - { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, NULL }, - { "3DLabs Oxygen VX1 PCI", PCI_VENDOR_ID_3DLABS, 0x0121, 0, NULL, - t_3DLabsOxygenVX1 - }, - { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, NULL }, - { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, NULL }, - { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, NULL }, - { "\0", 0x0, 0x0, 0, NULL, NULL } -}; +static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v) +{ + fb_writel(v, par->v_regs + off); +} -/* ********************************** */ -/* ***** card-specific function ***** */ -/* ********************************** */ -static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info) -{ /* the appian j2000 require more initialization of the second head */ - /* l_fb_info must point to the _second_ head of the J2000 */ - - DTRACE; - - l_fb_info->memt = t_AppianJeronimo2000[0].memt; /* 32 MB, first and only j2000 ? */ - - pm3fb_write_memory_timings(l_fb_info); +static inline void PM3_WAIT(struct pm3_par *par, u32 n) +{ + while (PM3_READ_REG(par, PM3InFIFOSpace) < n); } -/* *************************************** */ -/* ***** permedia3-specific function ***** */ -/* *************************************** */ -static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info) +static inline void PM3_SLOW_WRITE_REG(struct pm3_par *par, s32 off, u32 v) { - l_fb_info->memt.caps = PM3_READ_REG(PM3LocalMemCaps); - l_fb_info->memt.timings = PM3_READ_REG(PM3LocalMemTimings); - l_fb_info->memt.control = PM3_READ_REG(PM3LocalMemControl); - l_fb_info->memt.refresh = PM3_READ_REG(PM3LocalMemRefresh); - l_fb_info->memt.powerdown = PM3_READ_REG(PM3LocalMemPowerDown); - - if ((l_fb_info->memt.caps == PM3FB_UNKNOWN_TIMING_VALUE) || - (l_fb_info->memt.timings == PM3FB_UNKNOWN_TIMING_VALUE) || - (l_fb_info->memt.control == PM3FB_UNKNOWN_TIMING_VALUE) || - (l_fb_info->memt.refresh == PM3FB_UNKNOWN_TIMING_VALUE) || - (l_fb_info->memt.powerdown == PM3FB_UNKNOWN_TIMING_VALUE)) - { - printk(KERN_ERR "pm3fb: invalid memory timings in permedia3 board #%ld\n", l_fb_info->board_num); - return(pm3fb_try_memory_timings(l_fb_info)); + if (par->v_regs) { + mb(); + PM3_WAIT(par, 1); + wmb(); + PM3_WRITE_REG(par, off, v); } - return(pm3fb_timing_ok); } -static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info) +static inline void PM3_SET_INDEX(struct pm3_par *par, unsigned index) { - if (cardbase[l_fb_info->board_type].c_memt) - { - int i = 0, done = 0; - while (!done) - { - if ((cardbase[l_fb_info->board_type].c_memt[i].memsize == l_fb_info->fb_size) - || !(cardbase[l_fb_info->board_type].c_memt[i].memsize)) - { /* will use the 0-sized timings by default */ - done = 1; - l_fb_info->memt = cardbase[l_fb_info->board_type].c_memt[i].memt; - printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s, %ld MB)\n", - l_fb_info->board_num, - cardbase[l_fb_info->board_type].cardname, - cardbase[l_fb_info->board_type].c_memt[i].memsize); - pm3fb_write_memory_timings(l_fb_info); - return(pm3fb_timing_retry); - } - i++; - } - } else - return(pm3fb_timing_problem); - return(pm3fb_timing_ok); + PM3_SLOW_WRITE_REG(par, PM3RD_IndexHigh, (index >> 8) & 0xff); + PM3_SLOW_WRITE_REG(par, PM3RD_IndexLow, index & 0xff); } -static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info) +static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v) { - unsigned char m, n, p; - unsigned long clockused; - - PM3_SLOW_WRITE_REG(PM3LocalMemCaps, l_fb_info->memt.caps); - PM3_SLOW_WRITE_REG(PM3LocalMemTimings, l_fb_info->memt.timings); - PM3_SLOW_WRITE_REG(PM3LocalMemControl, l_fb_info->memt.control); - PM3_SLOW_WRITE_REG(PM3LocalMemRefresh, l_fb_info->memt.refresh); - PM3_SLOW_WRITE_REG(PM3LocalMemPowerDown, l_fb_info->memt.powerdown); - - clockused = - pm3fb_CalculateClock(l_fb_info, 2 * 105000, PM3_REF_CLOCK, &m, - &n, &p); - - PM3_WRITE_DAC_REG(PM3RD_KClkPreScale, m); - PM3_WRITE_DAC_REG(PM3RD_KClkFeedbackScale, n); - PM3_WRITE_DAC_REG(PM3RD_KClkPostScale, p); - PM3_WRITE_DAC_REG(PM3RD_KClkControl, - PM3RD_KClkControl_STATE_RUN | - PM3RD_KClkControl_SOURCE_PLL | - PM3RD_KClkControl_ENABLE); - PM3_WRITE_DAC_REG(PM3RD_MClkControl, - PM3RD_MClkControl_STATE_RUN | - PM3RD_MClkControl_SOURCE_KCLK | - PM3RD_MClkControl_ENABLE); - PM3_WRITE_DAC_REG(PM3RD_SClkControl, - PM3RD_SClkControl_STATE_RUN | - PM3RD_SClkControl_SOURCE_PCLK | - PM3RD_SClkControl_ENABLE); + PM3_SET_INDEX(par, r); + wmb(); + PM3_WRITE_REG(par, PM3RD_IndexedData, v); } -static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info, - unsigned long r) +static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno, + unsigned char r, unsigned char g, unsigned char b) { - DASSERT((l_fb_info->vIOBase != (unsigned char *) (-1)), - "l_fb_info->vIOBase mapped in read dac reg\n"); - PM3_SET_INDEX(r); - mb(); - return (PM3_READ_REG(PM3RD_IndexedData)); + PM3_SLOW_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno); + PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, r); + PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, g); + PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, b); +} + +static void pm3fb_clear_colormap(struct pm3_par *par, + unsigned char r, unsigned char g, unsigned char b) +{ + int i; + + for (i = 0; i < 256 ; i++) /* fill color map with white */ + pm3fb_set_color(par, i, r, g, b); + } /* Calculating various clock parameter */ -static unsigned long pm3fb_CalculateClock(struct pm3fb_info *l_fb_info, unsigned long reqclock, /* In kHz units */ - unsigned long refclock, /* In kHz units */ - unsigned char *prescale, /* ClkPreScale */ - unsigned char *feedback, /* ClkFeedBackScale */ - unsigned char *postscale - /* ClkPostScale */ ) +static void pm3fb_calculate_clock(unsigned long reqclock, + unsigned char *prescale, + unsigned char *feedback, + unsigned char *postscale) { int f, pre, post; unsigned long freq; long freqerr = 1000; - unsigned long actualclock = 0; - - DTRACE; + long currerr; for (f = 1; f < 256; f++) { for (pre = 1; pre < 256; pre++) { for (post = 0; post < 5; post++) { - freq = - ((2 * refclock * f) / - (pre * (1 << post))); - if ((reqclock > freq - freqerr) - && (reqclock < freq + freqerr)) { - freqerr = - (reqclock > - freq) ? reqclock - - freq : freq - reqclock; + freq = ((2*PM3_REF_CLOCK * f) >> post) / pre; + currerr = (reqclock > freq) + ? reqclock - freq + : freq - reqclock; + if (currerr < freqerr) { + freqerr = currerr; *feedback = f; *prescale = pre; *postscale = post; - actualclock = freq; } } } } - - return (actualclock); } -static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info, - unsigned long depth, int v) +static inline int pm3fb_shift_bpp(unsigned long depth, int v) { - DTRACE; - switch (depth) { case 8: return (v >> 4); @@ -918,181 +187,59 @@ static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info, case 32: return (v >> 2); } - DPRINTK(1, "Unsupported depth %ld\n", depth); - return (0); -} - -static int pm3fb_Unshiftbpp(struct pm3fb_info *l_fb_info, - unsigned long depth, int v) -{ - DTRACE; - - switch (depth) { - case 8: - return (v << 4); - case 12: - case 15: - case 16: - return (v << 3); - case 32: - return (v << 2); - } - DPRINTK(1, "Unsupported depth %ld\n", depth); - return (0); -} - -static void pm3fb_mapIO(struct pm3fb_info *l_fb_info) -{ - DTRACE; - - l_fb_info->vIOBase = - ioremap((unsigned long) l_fb_info->pIOBase, PM3_REGS_SIZE); - l_fb_info->v_fb = - ioremap((unsigned long) l_fb_info->p_fb, l_fb_info->fb_size); - DPRINTK(2, "IO mapping : IOBase %lx / %lx, fb %lx / %lx\n", - (unsigned long) l_fb_info->pIOBase, - (unsigned long) l_fb_info->vIOBase, - (unsigned long) l_fb_info->p_fb, - (unsigned long) l_fb_info->v_fb); -} - -static void pm3fb_unmapIO(struct pm3fb_info *l_fb_info) -{ - DTRACE; - - iounmap(l_fb_info->vIOBase); - iounmap(l_fb_info->v_fb); - l_fb_info->vIOBase = (unsigned char *) -1; - l_fb_info->v_fb = (unsigned char *) -1; -} - -#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2) -static void pm3fb_show_cur_mode(struct pm3fb_info *l_fb_info) -{ - DPRINTK(2, "PM3Aperture0: 0x%08x\n", PM3_READ_REG(PM3Aperture0)); - DPRINTK(2, "PM3Aperture1: 0x%08x\n", PM3_READ_REG(PM3Aperture1)); - DPRINTK(2, "PM3ByAperture1Mode: 0x%08x\n", - PM3_READ_REG(PM3ByAperture1Mode)); - DPRINTK(2, "PM3ByAperture2Mode: 0x%08x\n", - PM3_READ_REG(PM3ByAperture2Mode)); - DPRINTK(2, "PM3ChipConfig: 0x%08x\n", PM3_READ_REG(PM3ChipConfig)); - DPRINTK(2, "PM3FIFODis: 0x%08x\n", PM3_READ_REG(PM3FIFODis)); - DPRINTK(2, "PM3HTotal: 0x%08x\n", PM3_READ_REG(PM3HTotal)); - DPRINTK(2, "PM3HbEnd: 0x%08x\n", PM3_READ_REG(PM3HbEnd)); - DPRINTK(2, "PM3HgEnd: 0x%08x\n", PM3_READ_REG(PM3HgEnd)); - DPRINTK(2, "PM3HsEnd: 0x%08x\n", PM3_READ_REG(PM3HsEnd)); - DPRINTK(2, "PM3HsStart: 0x%08x\n", PM3_READ_REG(PM3HsStart)); - DPRINTK(2, "PM3MemBypassWriteMask: 0x%08x\n", - PM3_READ_REG(PM3MemBypassWriteMask)); - DPRINTK(2, "PM3RD_IndexControl: 0x%08x\n", - PM3_READ_REG(PM3RD_IndexControl)); - DPRINTK(2, "PM3ScreenBase: 0x%08x\n", PM3_READ_REG(PM3ScreenBase)); - DPRINTK(2, "PM3ScreenStride: 0x%08x\n", - PM3_READ_REG(PM3ScreenStride)); - DPRINTK(2, "PM3VClkCtl: 0x%08x\n", PM3_READ_REG(PM3VClkCtl)); - DPRINTK(2, "PM3VTotal: 0x%08x\n", PM3_READ_REG(PM3VTotal)); - DPRINTK(2, "PM3VbEnd: 0x%08x\n", PM3_READ_REG(PM3VbEnd)); - DPRINTK(2, "PM3VideoControl: 0x%08x\n", - PM3_READ_REG(PM3VideoControl)); - DPRINTK(2, "PM3VsEnd: 0x%08x\n", PM3_READ_REG(PM3VsEnd)); - DPRINTK(2, "PM3VsStart: 0x%08x\n", PM3_READ_REG(PM3VsStart)); - - DPRINTK(2, "PM3RD_ColorFormat: %ld\n", - PM3_READ_DAC_REG(PM3RD_ColorFormat)); - DPRINTK(2, "PM3RD_DACControl: %ld\n", - PM3_READ_DAC_REG(PM3RD_DACControl)); - DPRINTK(2, "PM3RD_DClk0FeedbackScale: %ld\n", - PM3_READ_DAC_REG(PM3RD_DClk0FeedbackScale)); - DPRINTK(2, "PM3RD_DClk0PostScale: %ld\n", - PM3_READ_DAC_REG(PM3RD_DClk0PostScale)); - DPRINTK(2, "PM3RD_DClk0PreScale: %ld\n", - PM3_READ_DAC_REG(PM3RD_DClk0PreScale)); - DPRINTK(2, "[not set] PM3RD_IndexControl: %ld\n", - PM3_READ_DAC_REG(PM3RD_IndexControl)); - DPRINTK(2, "PM3RD_MiscControl: %ld\n", - PM3_READ_DAC_REG(PM3RD_MiscControl)); - DPRINTK(2, "PM3RD_PixelSize: %ld\n", - PM3_READ_DAC_REG(PM3RD_PixelSize)); - DPRINTK(2, "PM3RD_SyncControl: %ld\n", - PM3_READ_DAC_REG(PM3RD_SyncControl)); -} - -#endif /* defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2) */ -static void pm3fb_show_cur_timing(struct pm3fb_info *l_fb_info) -{ - u16 subvendor, subdevice; - - if ((!pci_read_config_word - (l_fb_info->dev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor)) - && - (!pci_read_config_word - (l_fb_info->dev, PCI_SUBSYSTEM_ID, &subdevice))) { - /* well, nothing... */ - } else { - subvendor = subdevice = (u16)-1; - } - - printk(KERN_INFO "pm3fb: memory timings for board #%ld (subvendor: 0x%hx, subdevice: 0x%hx)\n", l_fb_info->board_num, subvendor, subdevice); - printk(KERN_INFO " PM3LocalMemCaps: 0x%08x\n", - PM3_READ_REG(PM3LocalMemCaps)); - printk(KERN_INFO " PM3LocalMemTimings: 0x%08x\n", - PM3_READ_REG(PM3LocalMemTimings)); - printk(KERN_INFO " PM3LocalMemControl: 0x%08x\n", - PM3_READ_REG(PM3LocalMemControl)); - printk(KERN_INFO " PM3LocalMemRefresh: 0x%08x\n", - PM3_READ_REG(PM3LocalMemRefresh)); - printk(KERN_INFO " PM3LocalMemPowerDown: 0x%08x\n", - PM3_READ_REG(PM3LocalMemPowerDown)); + DPRINTK("Unsupported depth %ld\n", depth); + return 0; } /* write the mode to registers */ -static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) +static void pm3fb_write_mode(struct fb_info *info) { + struct pm3_par *par = info->par; char tempsync = 0x00, tempmisc = 0x00; - DTRACE; - - PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xffffffff); - PM3_SLOW_WRITE_REG(PM3Aperture0, 0x00000000); - PM3_SLOW_WRITE_REG(PM3Aperture1, 0x00000000); - PM3_SLOW_WRITE_REG(PM3FIFODis, 0x00000007); - - PM3_SLOW_WRITE_REG(PM3HTotal, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->htotal - - 1)); - PM3_SLOW_WRITE_REG(PM3HsEnd, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->hsend)); - PM3_SLOW_WRITE_REG(PM3HsStart, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par-> + const u32 hsstart = info->var.right_margin; + const u32 hsend = hsstart + info->var.hsync_len; + const u32 hbend = hsend + info->var.left_margin; + const u32 xres = (info->var.xres + 31) & ~31; + const u32 htotal = xres + hbend; + const u32 vsstart = info->var.lower_margin; + const u32 vsend = vsstart + info->var.vsync_len; + const u32 vbend = vsend + info->var.upper_margin; + const u32 vtotal = info->var.yres + vbend; + const u32 width = (info->var.xres_virtual + 7) & ~7; + + PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff); + PM3_SLOW_WRITE_REG(par, PM3Aperture0, 0x00000000); + PM3_SLOW_WRITE_REG(par, PM3Aperture1, 0x00000000); + PM3_SLOW_WRITE_REG(par, PM3FIFODis, 0x00000007); + + PM3_SLOW_WRITE_REG(par, PM3HTotal, + pm3fb_shift_bpp(info->var.bits_per_pixel, + htotal - 1)); + PM3_SLOW_WRITE_REG(par, PM3HsEnd, + pm3fb_shift_bpp(info->var.bits_per_pixel, + hsend)); + PM3_SLOW_WRITE_REG(par, PM3HsStart, + pm3fb_shift_bpp(info->var.bits_per_pixel, hsstart)); - PM3_SLOW_WRITE_REG(PM3HbEnd, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->hbend)); - PM3_SLOW_WRITE_REG(PM3HgEnd, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->hbend)); - PM3_SLOW_WRITE_REG(PM3ScreenStride, - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - l_fb_info->current_par->stride)); - PM3_SLOW_WRITE_REG(PM3VTotal, l_fb_info->current_par->vtotal - 1); - PM3_SLOW_WRITE_REG(PM3VsEnd, l_fb_info->current_par->vsend - 1); - PM3_SLOW_WRITE_REG(PM3VsStart, - l_fb_info->current_par->vsstart - 1); - PM3_SLOW_WRITE_REG(PM3VbEnd, l_fb_info->current_par->vbend); - - switch (l_fb_info->current_par->depth) { + PM3_SLOW_WRITE_REG(par, PM3HbEnd, + pm3fb_shift_bpp(info->var.bits_per_pixel, + hbend)); + PM3_SLOW_WRITE_REG(par, PM3HgEnd, + pm3fb_shift_bpp(info->var.bits_per_pixel, + hbend)); + PM3_SLOW_WRITE_REG(par, PM3ScreenStride, + pm3fb_shift_bpp(info->var.bits_per_pixel, + width)); + PM3_SLOW_WRITE_REG(par, PM3VTotal, vtotal - 1); + PM3_SLOW_WRITE_REG(par, PM3VsEnd, vsend - 1); + PM3_SLOW_WRITE_REG(par, PM3VsStart, vsstart - 1); + PM3_SLOW_WRITE_REG(par, PM3VbEnd, vbend); + + switch (info->var.bits_per_pixel) { case 8: - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_8BIT); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_8BIT); break; @@ -1100,15 +247,15 @@ static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) case 15: case 16: #ifndef __BIG_ENDIAN - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT); #else - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT | PM3ByApertureMode_BYTESWAP_BADC); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT | PM3ByApertureMode_BYTESWAP_BADC); #endif /* ! __BIG_ENDIAN */ @@ -1116,23 +263,23 @@ static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) case 32: #ifndef __BIG_ENDIAN - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT); #else - PM3_SLOW_WRITE_REG(PM3ByAperture1Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT | PM3ByApertureMode_BYTESWAP_DCBA); - PM3_SLOW_WRITE_REG(PM3ByAperture2Mode, + PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT | PM3ByApertureMode_BYTESWAP_DCBA); #endif /* ! __BIG_ENDIAN */ break; default: - DPRINTK(1, "Unsupported depth %d\n", - l_fb_info->current_par->depth); + DPRINTK("Unsupported depth %d\n", + info->var.bits_per_pixel); break; } @@ -1143,95 +290,86 @@ static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) * sync options in PM3RD_SyncControl. --rmk */ { - unsigned int video = l_fb_info->current_par->video; + unsigned int video = par->video; video &= ~(PM3VideoControl_HSYNC_MASK | PM3VideoControl_VSYNC_MASK); video |= PM3VideoControl_HSYNC_ACTIVE_HIGH | PM3VideoControl_VSYNC_ACTIVE_HIGH; - PM3_SLOW_WRITE_REG(PM3VideoControl, video); + PM3_SLOW_WRITE_REG(par, PM3VideoControl, video); } - PM3_SLOW_WRITE_REG(PM3VClkCtl, - (PM3_READ_REG(PM3VClkCtl) & 0xFFFFFFFC)); - PM3_SLOW_WRITE_REG(PM3ScreenBase, l_fb_info->current_par->base); - PM3_SLOW_WRITE_REG(PM3ChipConfig, - (PM3_READ_REG(PM3ChipConfig) & 0xFFFFFFFD)); + PM3_SLOW_WRITE_REG(par, PM3VClkCtl, + (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC)); + PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base); + PM3_SLOW_WRITE_REG(par, PM3ChipConfig, + (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD)); { - unsigned char m; /* ClkPreScale */ - unsigned char n; /* ClkFeedBackScale */ - unsigned char p; /* ClkPostScale */ - (void)pm3fb_CalculateClock(l_fb_info, l_fb_info->current_par->pixclock, PM3_REF_CLOCK, &m, &n, &p); - - DPRINTK(2, - "Pixclock: %d, Pre: %d, Feedback: %d, Post: %d\n", - l_fb_info->current_par->pixclock, (int) m, (int) n, - (int) p); - - PM3_WRITE_DAC_REG(PM3RD_DClk0PreScale, m); - PM3_WRITE_DAC_REG(PM3RD_DClk0FeedbackScale, n); - PM3_WRITE_DAC_REG(PM3RD_DClk0PostScale, p); + unsigned char uninitialized_var(m); /* ClkPreScale */ + unsigned char uninitialized_var(n); /* ClkFeedBackScale */ + unsigned char uninitialized_var(p); /* ClkPostScale */ + unsigned long pixclock = PICOS2KHZ(info->var.pixclock); + + (void)pm3fb_calculate_clock(pixclock, &m, &n, &p); + + DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n", + pixclock, (int) m, (int) n, (int) p); + + PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m); + PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n); + PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p); } /* - PM3_WRITE_DAC_REG(PM3RD_IndexControl, 0x00); + PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00); */ /* - PM3_SLOW_WRITE_REG(PM3RD_IndexControl, 0x00); + PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00); */ - if ((l_fb_info->current_par->video & PM3VideoControl_HSYNC_MASK) == + if ((par->video & PM3VideoControl_HSYNC_MASK) == PM3VideoControl_HSYNC_ACTIVE_HIGH) tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH; - if ((l_fb_info->current_par->video & PM3VideoControl_VSYNC_MASK) == + if ((par->video & PM3VideoControl_VSYNC_MASK) == PM3VideoControl_VSYNC_ACTIVE_HIGH) tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH; - - PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync); - DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync); - - if (flatpanel[l_fb_info->board_num]) - { - PM3_WRITE_DAC_REG(PM3RD_DACControl, PM3RD_DACControl_BLANK_PEDESTAL_ENABLE); - PM3_WAIT(2); - PM3_WRITE_REG(PM3VSConfiguration, 0x06); - PM3_WRITE_REG(0x5a00, 1 << 14); /* black magic... */ - tempmisc = PM3RD_MiscControl_VSB_OUTPUT_ENABLE; - } - else - PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00); - switch (l_fb_info->current_par->depth) { + PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync); + DPRINTK("PM3RD_SyncControl: %d\n", tempsync); + + PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00); + + switch (info->var.bits_per_pixel) { case 8: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_8_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_CI8_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW); tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; case 12: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_16_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_4444_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; - break; + break; case 15: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_16_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_5551_FRONT_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; - break; + break; case 16: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_16_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_565_FRONT_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); @@ -1239,1936 +377,280 @@ static void pm3fb_write_mode(struct pm3fb_info *l_fb_info) PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; case 32: - PM3_WRITE_DAC_REG(PM3RD_PixelSize, + PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_32_BIT_PIXELS); - PM3_WRITE_DAC_REG(PM3RD_ColorFormat, + PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_8888_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; } - PM3_WRITE_DAC_REG(PM3RD_MiscControl, tempmisc); - - PM3_SHOW_CUR_MODE; + PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc); } -static void pm3fb_read_mode(struct pm3fb_info *l_fb_info, - struct pm3fb_par *curpar) -{ - unsigned long pixsize1, pixsize2, clockused; - unsigned long pre, feedback, post; - - DTRACE; - - clockused = PM3_READ_REG(PM3VClkCtl); +/* + * hardware independent functions + */ +int pm3fb_init(void); +int pm3fb_setup(char*); - switch (clockused) { - case 3: - pre = PM3_READ_DAC_REG(PM3RD_DClk3PreScale); - feedback = PM3_READ_DAC_REG(PM3RD_DClk3FeedbackScale); - post = PM3_READ_DAC_REG(PM3RD_DClk3PostScale); +static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + u32 lpitch; - DPRINTK(2, - "DClk3 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n", - pre, feedback, post, PM3_SCALE_TO_CLOCK(pre, - feedback, - post)); + var->transp.offset = 0; + var->transp.length = 0; + switch(var->bits_per_pixel) { + case 8: + var->red.length = var->green.length = var->blue.length = 8; + var->red.offset = var->green.offset = var->blue.offset = 0; break; - case 2: - pre = PM3_READ_DAC_REG(PM3RD_DClk2PreScale); - feedback = PM3_READ_DAC_REG(PM3RD_DClk2FeedbackScale); - post = PM3_READ_DAC_REG(PM3RD_DClk2PostScale); - - DPRINTK(2, - "DClk2 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n", - pre, feedback, post, PM3_SCALE_TO_CLOCK(pre, - feedback, - post)); + case 12: + var->red.offset = 8; + var->red.length = 4; + var->green.offset = 4; + var->green.length = 4; + var->blue.offset = 0; + var->blue.length = 4; + var->transp.offset = 12; + var->transp.length = 4; + case 15: + var->red.offset = 10; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 15; + var->transp.length = 1; break; - case 1: - pre = PM3_READ_DAC_REG(PM3RD_DClk1PreScale); - feedback = PM3_READ_DAC_REG(PM3RD_DClk1FeedbackScale); - post = PM3_READ_DAC_REG(PM3RD_DClk1PostScale); - - DPRINTK(2, - "DClk1 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n", - pre, feedback, post, PM3_SCALE_TO_CLOCK(pre, - feedback, - post)); + case 16: + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; break; - case 0: - pre = PM3_READ_DAC_REG(PM3RD_DClk0PreScale); - feedback = PM3_READ_DAC_REG(PM3RD_DClk0FeedbackScale); - post = PM3_READ_DAC_REG(PM3RD_DClk0PostScale); - - DPRINTK(2, - "DClk0 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n", - pre, feedback, post, PM3_SCALE_TO_CLOCK(pre, - feedback, - post)); + case 32: + var->transp.offset = 24; + var->transp.length = 8; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 8; break; default: - pre = feedback = post = 0; - DPRINTK(1, "Unknowk D clock used : %ld\n", clockused); - break; - } - - curpar->pixclock = PM3_SCALE_TO_CLOCK(pre, feedback, post); - - pixsize1 = - PM3ByApertureMode_PIXELSIZE_MASK & - (PM3_READ_REG(PM3ByAperture1Mode)); - pixsize2 = - PM3ByApertureMode_PIXELSIZE_MASK & - (PM3_READ_REG(PM3ByAperture2Mode)); - - DASSERT((pixsize1 == pixsize2), - "pixsize the same in both aperture\n"); - - if (pixsize1 & PM3ByApertureMode_PIXELSIZE_32BIT) - curpar->depth = 32; - else if (pixsize1 & PM3ByApertureMode_PIXELSIZE_16BIT) - { - curpar->depth = 16; - } - else - curpar->depth = 8; - - /* not sure if I need to add one on the next ; it give better result with */ - curpar->htotal = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - 1 + PM3_READ_REG(PM3HTotal)); - curpar->hsend = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - PM3_READ_REG(PM3HsEnd)); - curpar->hsstart = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - PM3_READ_REG(PM3HsStart)); - curpar->hbend = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - PM3_READ_REG(PM3HbEnd)); - - curpar->stride = - pm3fb_Unshiftbpp(l_fb_info, curpar->depth, - PM3_READ_REG(PM3ScreenStride)); - - curpar->vtotal = 1 + PM3_READ_REG(PM3VTotal); - curpar->vsend = 1 + PM3_READ_REG(PM3VsEnd); - curpar->vsstart = 1 + PM3_READ_REG(PM3VsStart); - curpar->vbend = PM3_READ_REG(PM3VbEnd); - - curpar->video = PM3_READ_REG(PM3VideoControl); - - curpar->base = PM3_READ_REG(PM3ScreenBase); - curpar->width = curpar->htotal - curpar->hbend; /* make virtual == displayed resolution */ - curpar->height = curpar->vtotal - curpar->vbend; - - DPRINTK(2, "Found : %d * %d, %d Khz, stride is %08x\n", - curpar->width, curpar->height, curpar->pixclock, - curpar->stride); -} - -static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info) -{ - unsigned long memsize = 0, tempBypass, i, temp1, temp2; - u16 subvendor, subdevice; - pm3fb_timing_result ptr; - - DTRACE; - - l_fb_info->fb_size = 64 * 1024 * 1024; /* pm3 aperture always 64 MB */ - pm3fb_mapIO(l_fb_info); /* temporary map IO */ - - DASSERT((l_fb_info->vIOBase != NULL), - "IO successfully mapped before mem detect\n"); - DASSERT((l_fb_info->v_fb != NULL), - "FB successfully mapped before mem detect\n"); - - /* card-specific stuff, *before* accessing *any* FB memory */ - if ((!pci_read_config_word - (l_fb_info->dev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor)) - && - (!pci_read_config_word - (l_fb_info->dev, PCI_SUBSYSTEM_ID, &subdevice))) { - i = 0; l_fb_info->board_type = 0; - while ((cardbase[i].cardname[0]) && !(l_fb_info->board_type)) { - if ((cardbase[i].subvendor == subvendor) && - (cardbase[i].subdevice == subdevice) && - (cardbase[i].func == PCI_FUNC(l_fb_info->dev->devfn))) { - DPRINTK(2, "Card #%ld is an %s\n", - l_fb_info->board_num, - cardbase[i].cardname); - if (cardbase[i].specific_setup) - cardbase[i].specific_setup(l_fb_info); - l_fb_info->board_type = i; - } - i++; - } - if (!l_fb_info->board_type) { - DPRINTK(1, "Card #%ld is an unknown 0x%04x / 0x%04x\n", - l_fb_info->board_num, subvendor, subdevice); - } - } else { - printk(KERN_ERR "pm3fb: Error: pci_read_config_word failed, board #%ld\n", - l_fb_info->board_num); - } - - if (printtimings) - pm3fb_show_cur_timing(l_fb_info); - - /* card-specific setup is done, we preserve the final - memory timing for future reference */ - if ((ptr = pm3fb_preserve_memory_timings(l_fb_info)) == pm3fb_timing_problem) { /* memory timings were wrong ! oops.... */ - return(0); - } - - tempBypass = PM3_READ_REG(PM3MemBypassWriteMask); - - DPRINTK(2, "PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass); - - PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xFFFFFFFF); - - /* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */ - for (i = 0; i < 32; i++) { - fb_writel(i * 0x00345678, - (l_fb_info->v_fb + (i * 1048576))); - mb(); - temp1 = fb_readl((l_fb_info->v_fb + (i * 1048576))); - - /* Let's check for wrapover, write will fail at 16MB boundary */ - if (temp1 == (i * 0x00345678)) - memsize = i; - else - break; - } - - DPRINTK(2, "First detect pass already got %ld MB\n", memsize + 1); - - if (memsize == i) { - for (i = 0; i < 32; i++) { - /* Clear first 32MB ; 0 is 0, no need to byteswap */ - writel(0x0000000, - (l_fb_info->v_fb + (i * 1048576))); - mb(); - } - - for (i = 32; i < 64; i++) { - fb_writel(i * 0x00345678, - (l_fb_info->v_fb + (i * 1048576))); - mb(); - temp1 = - fb_readl((l_fb_info->v_fb + (i * 1048576))); - temp2 = - fb_readl((l_fb_info->v_fb + - ((i - 32) * 1048576))); - if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) /* different value, different RAM... */ - memsize = i; - else - break; - } - } - - DPRINTK(2, "Second detect pass got %ld MB\n", memsize + 1); - - PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, tempBypass); - - pm3fb_unmapIO(l_fb_info); - memsize = 1048576 * (memsize + 1); - - DPRINTK(2, "Returning 0x%08lx bytes\n", memsize); - - if (forcesize[l_fb_info->board_num] && ((forcesize[l_fb_info->board_num] * 1048576) != memsize)) - { - printk(KERN_WARNING "pm3fb: mismatch between probed (%ld MB) and specified (%hd MB) memory size, using SPECIFIED !\n", memsize, forcesize[l_fb_info->board_num]); - memsize = 1048576 * forcesize[l_fb_info->board_num]; - } - - l_fb_info->fb_size = memsize; - - if (ptr == pm3fb_timing_retry) - { - printk(KERN_WARNING "pm3fb: retrying memory timings check"); - if (pm3fb_try_memory_timings(l_fb_info) == pm3fb_timing_problem) - return(0); - } - - return (memsize); -} - -static void pm3fb_clear_memory(struct pm3fb_info *l_fb_info, u32 cc) -{ - int i; - - DTRACE; - - for (i = 0; i < (l_fb_info->fb_size / sizeof(u32)) ; i++) /* clear entire FB memory to black */ - { - fb_writel(cc, (l_fb_info->v_fb + (i * sizeof(u32)))); + DPRINTK("depth not supported: %u\n", var->bits_per_pixel); + return -EINVAL; } -} - -static void pm3fb_clear_colormap(struct pm3fb_info *l_fb_info, unsigned char r, unsigned char g, unsigned char b) -{ - int i; - - DTRACE; - - for (i = 0; i < 256 ; i++) /* fill color map with white */ - pm3fb_set_color(l_fb_info, i, r, g, b); - -} - -/* common initialisation */ -static void pm3fb_common_init(struct pm3fb_info *l_fb_info) -{ - DTRACE; - - DPRINTK(2, "Initializing board #%ld @ %lx\n", l_fb_info->board_num, - (unsigned long) l_fb_info); - - strcpy(l_fb_info->gen.info.modename, permedia3_name); - disp[l_fb_info->board_num].scrollmode = 0; /* SCROLL_YNOMOVE; *//* 0 means "let fbcon choose" */ - l_fb_info->gen.parsize = sizeof(struct pm3fb_par); - l_fb_info->gen.info.changevar = NULL; - l_fb_info->gen.info.fbops = &pm3fb_ops; - l_fb_info->gen.info.disp = &(disp[l_fb_info->board_num]); - if (fontn[l_fb_info->board_num][0]) - strcpy(l_fb_info->gen.info.fontname, - fontn[l_fb_info->board_num]); - l_fb_info->gen.info.switch_con = &fbgen_switch; - l_fb_info->gen.info.updatevar = &fbgen_update_var; /* */ - l_fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT; - - pm3fb_mapIO(l_fb_info); - - pm3fb_clear_memory(l_fb_info, 0); - pm3fb_clear_colormap(l_fb_info, 0, 0, 0); - - (void) fbgen_get_var(&(disp[l_fb_info->board_num]).var, -1, - &l_fb_info->gen.info); + var->height = var->width = -1; - if (depth[l_fb_info->board_num]) /* override mode-defined depth */ - { - pm3fb_encode_depth(&(disp[l_fb_info->board_num]).var, depth[l_fb_info->board_num]); - (disp[l_fb_info->board_num]).var.bits_per_pixel = depth2bpp(depth[l_fb_info->board_num]); + if (var->xres != var->xres_virtual) { + DPRINTK("virtual x resolution != physical x resolution not supported\n"); + return -EINVAL; } - (void) fbgen_do_set_var(&(disp[l_fb_info->board_num]).var, 1, - &l_fb_info->gen); - - fbgen_set_disp(-1, &l_fb_info->gen); - - do_install_cmap(0, &l_fb_info->gen.info); - - if (register_framebuffer(&l_fb_info->gen.info) < 0) { - DPRINTK(1, "Couldn't register framebuffer\n"); - return; + if (var->yres > var->yres_virtual) { + DPRINTK("virtual y resolution < physical y resolution not possible\n"); + return -EINVAL; } - PM3_WRITE_DAC_REG(PM3RD_CursorMode, - PM3RD_CursorMode_CURSOR_DISABLE); - - PM3_SHOW_CUR_MODE; - - pm3fb_write_mode(l_fb_info); - - printk("fb%d: %s, using %uK of video memory (%s)\n", - l_fb_info->gen.info.node, - permedia3_name, (u32) (l_fb_info->fb_size >> 10), - cardbase[l_fb_info->board_type].cardname); -} - -/* **************************************************** */ -/* ***** accelerated permedia3-specific functions ***** */ -/* **************************************************** */ -#ifdef PM3FB_USE_ACCEL -static void pm3fb_wait_pm3(struct pm3fb_info *l_fb_info) -{ - DTRACE; - - PM3_SLOW_WRITE_REG(PM3FilterMode, PM3FilterModeSync); - PM3_SLOW_WRITE_REG(PM3Sync, 0); - mb(); - do { - while ((PM3_READ_REG(PM3OutFIFOWords)) == 0); - rmb(); - } while ((PM3_READ_REG(PM3OutputFifo)) != PM3Sync_Tag); -} - -static void pm3fb_init_engine(struct pm3fb_info *l_fb_info) -{ - PM3_SLOW_WRITE_REG(PM3FilterMode, PM3FilterModeSync); - PM3_SLOW_WRITE_REG(PM3StatisticMode, 0x0); - PM3_SLOW_WRITE_REG(PM3DeltaMode, 0x0); - PM3_SLOW_WRITE_REG(PM3RasterizerMode, 0x0); - PM3_SLOW_WRITE_REG(PM3ScissorMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LineStippleMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AreaStippleMode, 0x0); - PM3_SLOW_WRITE_REG(PM3GIDMode, 0x0); - PM3_SLOW_WRITE_REG(PM3DepthMode, 0x0); - PM3_SLOW_WRITE_REG(PM3StencilMode, 0x0); - PM3_SLOW_WRITE_REG(PM3StencilData, 0x0); - PM3_SLOW_WRITE_REG(PM3ColorDDAMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCoordMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureIndexMode0, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureIndexMode1, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureReadMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LUTMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureFilterMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureApplicationMode, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeColorMode1, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeAlphaMode1, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeColorMode0, 0x0); - PM3_SLOW_WRITE_REG(PM3TextureCompositeAlphaMode0, 0x0); - PM3_SLOW_WRITE_REG(PM3FogMode, 0x0); - PM3_SLOW_WRITE_REG(PM3ChromaTestMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AlphaTestMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AntialiasMode, 0x0); - PM3_SLOW_WRITE_REG(PM3YUVMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AlphaBlendColorMode, 0x0); - PM3_SLOW_WRITE_REG(PM3AlphaBlendAlphaMode, 0x0); - PM3_SLOW_WRITE_REG(PM3DitherMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LogicalOpMode, 0x0); - PM3_SLOW_WRITE_REG(PM3RouterMode, 0x0); - PM3_SLOW_WRITE_REG(PM3Window, 0x0); - - PM3_SLOW_WRITE_REG(PM3Config2D, 0x0); - - PM3_SLOW_WRITE_REG(PM3SpanColorMask, 0xffffffff); - - PM3_SLOW_WRITE_REG(PM3XBias, 0x0); - PM3_SLOW_WRITE_REG(PM3YBias, 0x0); - PM3_SLOW_WRITE_REG(PM3DeltaControl, 0x0); - - PM3_SLOW_WRITE_REG(PM3BitMaskPattern, 0xffffffff); - - PM3_SLOW_WRITE_REG(PM3FBDestReadEnables, - PM3FBDestReadEnables_E(0xff) | - PM3FBDestReadEnables_R(0xff) | - PM3FBDestReadEnables_ReferenceAlpha(0xff)); - PM3_SLOW_WRITE_REG(PM3FBDestReadBufferAddr0, 0x0); - PM3_SLOW_WRITE_REG(PM3FBDestReadBufferOffset0, 0x0); - PM3_SLOW_WRITE_REG(PM3FBDestReadBufferWidth0, - PM3FBDestReadBufferWidth_Width(l_fb_info-> - current_par-> - width)); - - PM3_SLOW_WRITE_REG(PM3FBDestReadMode, - PM3FBDestReadMode_ReadEnable | - PM3FBDestReadMode_Enable0); - PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferAddr, 0x0); - PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferOffset, 0x0); - PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferWidth, - PM3FBSourceReadBufferWidth_Width(l_fb_info-> - current_par-> - width)); - PM3_SLOW_WRITE_REG(PM3FBSourceReadMode, - PM3FBSourceReadMode_Blocking | - PM3FBSourceReadMode_ReadEnable); - - { - unsigned long rm = 1; - switch (l_fb_info->current_par->depth) { - case 8: - PM3_SLOW_WRITE_REG(PM3PixelSize, - PM3PixelSize_GLOBAL_8BIT); - break; - case 12: - case 15: - case 16: - PM3_SLOW_WRITE_REG(PM3PixelSize, - PM3PixelSize_GLOBAL_16BIT); - break; - case 32: - PM3_SLOW_WRITE_REG(PM3PixelSize, - PM3PixelSize_GLOBAL_32BIT); - break; - default: - DPRINTK(1, "Unsupported depth %d\n", - l_fb_info->current_par->depth); - break; - } - PM3_SLOW_WRITE_REG(PM3RasterizerMode, rm); + if (var->xoffset) { + DPRINTK("xoffset not supported\n"); + return -EINVAL; } - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xffffffff); - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff); - PM3_SLOW_WRITE_REG(PM3FBWriteMode, - PM3FBWriteMode_WriteEnable | - PM3FBWriteMode_OpaqueSpan | - PM3FBWriteMode_Enable0); - PM3_SLOW_WRITE_REG(PM3FBWriteBufferAddr0, 0x0); - PM3_SLOW_WRITE_REG(PM3FBWriteBufferOffset0, 0x0); - PM3_SLOW_WRITE_REG(PM3FBWriteBufferWidth0, - PM3FBWriteBufferWidth_Width(l_fb_info-> - current_par-> - width)); - - PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 0x0); - { - unsigned long sofb = (8UL * l_fb_info->fb_size) / - ((depth2bpp(l_fb_info->current_par->depth)) - * l_fb_info->current_par->width); /* size in lines of FB */ - if (sofb > 4095) - PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 4095); - else - PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, sofb); - - switch (l_fb_info->current_par->depth) { - case 8: - PM3_SLOW_WRITE_REG(PM3DitherMode, - (1 << 10) | (2 << 3)); - break; - case 12: - case 15: - case 16: - PM3_SLOW_WRITE_REG(PM3DitherMode, - (1 << 10) | (1 << 3)); - break; - case 32: - PM3_SLOW_WRITE_REG(PM3DitherMode, - (1 << 10) | (0 << 3)); - break; - default: - DPRINTK(1, "Unsupported depth %d\n", - l_fb_info->current_par->depth); - break; - } + if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + DPRINTK("interlace not supported\n"); + return -EINVAL; } - PM3_SLOW_WRITE_REG(PM3dXDom, 0x0); - PM3_SLOW_WRITE_REG(PM3dXSub, 0x0); - PM3_SLOW_WRITE_REG(PM3dY, (1 << 16)); - PM3_SLOW_WRITE_REG(PM3StartXDom, 0x0); - PM3_SLOW_WRITE_REG(PM3StartXSub, 0x0); - PM3_SLOW_WRITE_REG(PM3StartY, 0x0); - PM3_SLOW_WRITE_REG(PM3Count, 0x0); - -/* Disable LocalBuffer. better safe than sorry */ - PM3_SLOW_WRITE_REG(PM3LBDestReadMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LBDestReadEnables, 0x0); - PM3_SLOW_WRITE_REG(PM3LBSourceReadMode, 0x0); - PM3_SLOW_WRITE_REG(PM3LBWriteMode, 0x0); - - pm3fb_wait_pm3(l_fb_info); -} + var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */ + lpitch = var->xres * ((var->bits_per_pixel + 7)>>3); -#ifdef FBCON_HAS_CFB32 -static void pm3fb_cfb32_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u32 c; - - DTRACE; - - sx = sx * fontwidth(p); - width = width * fontwidth(p); - sy = sy * fontheight(p); - height = height * fontheight(p); - c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - /* block fills in 32bpp are hard, but in low res (width <= 1600 :-) - we can use 16bpp operations, but not if NoWriteMask is on (SDRAM) */ - if ((l_fb_info->current_par->width > 1600) || - (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)) { - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(width)) | - (PM3Render2D_Height(height))); - } else { - PM3_WAIT(8); - - PM3_WRITE_REG(PM3FBBlockColor, c); - - PM3_WRITE_REG(PM3PixelSize, PM3PixelSize_GLOBAL_16BIT); - - PM3_WRITE_REG(PM3FBWriteBufferWidth0, - PM3FBWriteBufferWidth_Width(l_fb_info-> - current_par-> - width << 1)); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx << 1)) | - (PM3RectanglePosition_YOffset(sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - (PM3Render2D_Width(width << 1)) | - (PM3Render2D_Height(height))); - - PM3_WRITE_REG(PM3FBWriteBufferWidth0, - PM3FBWriteBufferWidth_Width(l_fb_info-> - current_par-> - width)); - - PM3_WRITE_REG(PM3PixelSize, PM3PixelSize_GLOBAL_32BIT); + if (var->xres < 200 || var->xres > 2048) { + DPRINTK("width not supported: %u\n", var->xres); + return -EINVAL; } - pm3fb_wait_pm3(l_fb_info); -} - -static void pm3fb_cfb32_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - int sx, sy; - u32 c; - - DTRACE; - - sx = conp->vc_cols * fontwidth(p); /* right margin */ - sy = conp->vc_rows * fontheight(p); /* bottom margin */ - c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)]; - - if (!bottom_only) { /* right margin top->bottom */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset - (p->var.xoffset + - sx)) | (PM3RectanglePosition_YOffset(p-> - var. - yoffset))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres - sx)) | - (PM3Render2D_Height(p->var.yres))); + if (var->yres < 200 || var->yres > 4095) { + DPRINTK("height not supported: %u\n", var->yres); + return -EINVAL; } - /* bottom margin left -> right */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(p->var.xoffset)) | - (PM3RectanglePosition_YOffset(p->var.yoffset + sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres)) | - (PM3Render2D_Height(p->var.yres - sy))); - - pm3fb_wait_pm3(l_fb_info); -} -#endif /* FBCON_HAS_CFB32 */ -#ifdef FBCON_HAS_CFB16 -static void pm3fb_cfb16_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u32 c; - - DTRACE; - - sx = sx * fontwidth(p); - width = width * fontwidth(p); - sy = sy * fontheight(p); - height = height * fontheight(p); - c = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)]; - c = c | (c << 16); - - PM3_WAIT(4); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3ForegroundColor, c); - else - PM3_WRITE_REG(PM3FBBlockColor, c); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(width)) | - (PM3Render2D_Height(height))); - else - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - (PM3Render2D_Width(width)) | - (PM3Render2D_Height(height))); - - pm3fb_wait_pm3(l_fb_info); -} - -static void pm3fb_cfb16_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - int sx, sy; - u32 c; - - DTRACE; - - sx = conp->vc_cols * fontwidth(p); /* right margin */ - sy = conp->vc_rows * fontheight(p); /* bottom margin */ - c = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)]; - c = c | (c << 16); - - if (!bottom_only) { /* right margin top->bottom */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3ForegroundColor, c); - else - PM3_WRITE_REG(PM3FBBlockColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset - (p->var.xoffset + - sx)) | (PM3RectanglePosition_YOffset(p-> - var. - yoffset))); - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres - sx)) | - (PM3Render2D_Height(p->var.yres))); - else - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - (PM3Render2D_Width(p->var.xres - sx)) | - (PM3Render2D_Height(p->var.yres))); + if (lpitch * var->yres_virtual > info->fix.smem_len) { + DPRINTK("no memory for screen (%ux%ux%u)\n", + var->xres, var->yres_virtual, var->bits_per_pixel); + return -EINVAL; } - - /* bottom margin left -> right */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3ForegroundColor, c); - else - PM3_WRITE_REG(PM3FBBlockColor, c); - - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(p->var.xoffset)) | - (PM3RectanglePosition_YOffset(p->var.yoffset + sy))); - - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres)) | - (PM3Render2D_Height(p->var.yres - sy))); - else - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - (PM3Render2D_Width(p->var.xres)) | - (PM3Render2D_Height(p->var.yres - sy))); - - pm3fb_wait_pm3(l_fb_info); -} -#endif /* FBCON_HAS_CFB16 */ -#ifdef FBCON_HAS_CFB8 -static void pm3fb_cfb8_clear(struct vc_data *conp, - struct display *p, - int sy, int sx, int height, int width) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u32 c; - - DTRACE; - - sx = sx * fontwidth(p); - width = width * fontwidth(p); - sy = sy * fontheight(p); - height = height * fontheight(p); - - c = attr_bgcol_ec(p, conp); - c |= c << 8; - c |= c << 16; - - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(width)) | - (PM3Render2D_Height(height))); - - pm3fb_wait_pm3(l_fb_info); -} - -static void pm3fb_cfb8_clear_margins(struct vc_data *conp, - struct display *p, int bottom_only) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - int sx, sy; - u32 c; - - DTRACE; - - sx = conp->vc_cols * fontwidth(p); /* right margin */ - sy = conp->vc_rows * fontheight(p); /* bottom margin */ - c = attr_bgcol_ec(p, conp); - c |= c << 8; - c |= c << 16; - - if (!bottom_only) { /* right margin top->bottom */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset - (p->var.xoffset + - sx)) | (PM3RectanglePosition_YOffset(p-> - var. - yoffset))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres - sx)) | - (PM3Render2D_Height(p->var.yres))); + if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) { + DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock)); + return -EINVAL; } - /* bottom margin left -> right */ - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ForegroundColor, c); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(p->var.xoffset)) | - (PM3RectanglePosition_YOffset(p->var.yoffset + sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(p->var.xres)) | - (PM3Render2D_Height(p->var.yres - sy))); + var->accel_flags = 0; /* Can't mmap if this is on */ - pm3fb_wait_pm3(l_fb_info); -} -#endif /* FBCON_HAS_CFB8 */ -#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) -static void pm3fb_cfbX_bmove(struct display *p, - int sy, int sx, - int dy, int dx, int height, int width) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - int x_align, o_x, o_y; - - DTRACE; - - sx = sx * fontwidth(p); - dx = dx * fontwidth(p); - width = width * fontwidth(p); - sy = sy * fontheight(p); - dy = dy * fontheight(p); - height = height * fontheight(p); - - o_x = sx - dx; /*(sx > dx ) ? (sx - dx) : (dx - sx); */ - o_y = sy - dy; /*(sy > dy ) ? (sy - dy) : (dy - sy); */ - - x_align = (sx & 0x1f); - - PM3_WAIT(6); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UserScissorEnable | - PM3Config2D_ForegroundROPEnable | - PM3Config2D_Blocking | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3ScissorMinXY, - ((dy & 0x0fff) << 16) | (dx & 0x0fff)); - PM3_WRITE_REG(PM3ScissorMaxXY, - (((dy + height) & 0x0fff) << 16) | - ((dx + width) & 0x0fff)); - - PM3_WRITE_REG(PM3FBSourceReadBufferOffset, - PM3FBSourceReadBufferOffset_XOffset(o_x) | - PM3FBSourceReadBufferOffset_YOffset(o_y)); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(dx - x_align)) | - (PM3RectanglePosition_YOffset(dy))); - - PM3_WRITE_REG(PM3Render2D, - ((sx > dx) ? PM3Render2D_XPositive : 0) | - ((sy > dy) ? PM3Render2D_YPositive : 0) | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - PM3Render2D_FBSourceReadEnable | - (PM3Render2D_Width(width + x_align)) | - (PM3Render2D_Height(height))); - - pm3fb_wait_pm3(l_fb_info); + DPRINTK("Checking graphics mode at %dx%d depth %d\n", + var->xres, var->yres, var->bits_per_pixel); + return 0; } -static void pm3fb_cfbX_putc(struct vc_data *conp, struct display *p, - int c, int yy, int xx) +static int pm3fb_set_par(struct fb_info *info) { - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0; - u32 fgx, bgx, ldat; - int sx, sy, i; + struct pm3_par *par = info->par; + const u32 xres = (info->var.xres + 31) & ~31; + const int depth = (info->var.bits_per_pixel + 7) & ~7; - DTRACE; + par->base = pm3fb_shift_bpp(info->var.bits_per_pixel, + (info->var.yoffset * xres) + + info->var.xoffset); + par->video = 0; - if (l_fb_info->current_par->depth == 8) - fgx = attr_fgcol(p, c); - else if (depth2bpp(l_fb_info->current_par->depth) == 16) - fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, c)]; + if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) + par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH; else - fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, c)]; + par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW; - PM3_COLOR(fgx); - - if (l_fb_info->current_par->depth == 8) - bgx = attr_bgcol(p, c); - else if (depth2bpp(l_fb_info->current_par->depth) == 16) - bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, c)]; + if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) + par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH; else - bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, c)]; - - PM3_COLOR(bgx); - - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable | PM3Config2D_OpaqueSpan); - - PM3_WRITE_REG(PM3ForegroundColor, fgx); - PM3_WRITE_REG(PM3FillBackgroundColor, bgx); - - /* WARNING : address select X need to specify 8 bits for fontwidth <= 8 */ - /* and 16 bits for fontwidth <= 16 */ - /* same in _putcs, same for Y and fontheight */ - if (fontwidth(p) <= 8) - asx = 2; - else if (fontwidth(p) <= 16) - asx = 3; /* look OK */ - if (fontheight(p) <= 8) - asy = 2; - else if (fontheight(p) <= 16) - asy = 3; /* look OK */ - else if (fontheight(p) <= 32) - asy = 4; /* look OK */ - - sx = xx * fontwidth(p); - sy = yy * fontheight(p); - - if (fontwidth(p) <= 8) - o_x = (8 - (sx & 0x7)) & 0x7; - else if (fontwidth(p) <= 16) - o_x = (16 - (sx & 0xF)) & 0xF; - if (fontheight(p) <= 8) - o_y = (8 - (sy & 0x7)) & 0x7; - else if (fontheight(p) <= 16) - o_y = (16 - (sy & 0xF)) & 0xF; - else if (fontheight(p) <= 32) - o_y = (32 - (sy & 0x1F)) & 0x1F; - - PM3_WRITE_REG(PM3AreaStippleMode, (o_x << 7) | (o_y << 12) | /* x_offset, y_offset in pattern */ - (1 << 18) | /* BE */ - 1 | (asx << 1) | (asy << 4) | /* address select x/y */ - (1 << 20)); /* OpaqueSpan */ - - if (fontwidth(p) <= 8) { - cdat = p->fontdata + (c & p->charmask) * fontheight(p); - } else { - cdat = - p->fontdata + - ((c & p->charmask) * (fontheight(p) << 1)); - } - - PM3_WAIT(2 + fontheight(p)); - - for (i = 0; i < fontheight(p); i++) { /* assume fontheight <= 32 */ - if (fontwidth(p) <= 8) { - ldat = *cdat++; - } else { /* assume fontwidth <= 16 ATM */ - - ldat = ((*cdat++) << 8); - ldat |= *cdat++; - } - PM3_WRITE_REG(AreaStipplePattern_indexed(i), ldat); - } - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); + par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW; - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_AreaStippleEnable | - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(fontwidth(p))) | - (PM3Render2D_Height(fontheight(p)))); - - pm3fb_wait_pm3(l_fb_info); -} - -static void pm3fb_cfbX_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, - int xx) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0; - u32 fgx, bgx, ldat; - int sx, sy, i, j; - u16 sc; - - DTRACE; - - sc = scr_readw(s); - if (l_fb_info->current_par->depth == 8) - fgx = attr_fgcol(p, sc); - else if (depth2bpp(l_fb_info->current_par->depth) == 16) - fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, sc)]; - else - fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, sc)]; - - PM3_COLOR(fgx); - - if (l_fb_info->current_par->depth == 8) - bgx = attr_bgcol(p, sc); - else if (depth2bpp(l_fb_info->current_par->depth) == 16) - bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, sc)]; + if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) + par->video |= PM3VideoControl_LINE_DOUBLE_ON; else - bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, sc)]; - - PM3_COLOR(bgx); - - PM3_WAIT(4); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ - PM3Config2D_FBWriteEnable | - PM3Config2D_OpaqueSpan); - - PM3_WRITE_REG(PM3ForegroundColor, fgx); - PM3_WRITE_REG(PM3FillBackgroundColor, bgx); - - /* WARNING : address select X need to specify 8 bits for fontwidth <= 8 */ - /* and 16 bits for fontwidth <= 16 */ - /* same in _putc, same for Y and fontheight */ - if (fontwidth(p) <= 8) - asx = 2; - else if (fontwidth(p) <= 16) - asx = 3; /* look OK */ - if (fontheight(p) <= 8) - asy = 2; - else if (fontheight(p) <= 16) - asy = 3; /* look OK */ - else if (fontheight(p) <= 32) - asy = 4; /* look OK */ - - sy = yy * fontheight(p); - - if (fontheight(p) <= 8) - o_y = (8 - (sy & 0x7)) & 0x7; - else if (fontheight(p) <= 16) - o_y = (16 - (sy & 0xF)) & 0xF; - else if (fontheight(p) <= 32) - o_y = (32 - (sy & 0x1F)) & 0x1F; - - for (j = 0; j < count; j++) { - sc = scr_readw(s + j); - if (fontwidth(p) <= 8) - cdat = p->fontdata + - (sc & p->charmask) * fontheight(p); - else - cdat = p->fontdata + - ((sc & p->charmask) * fontheight(p) << 1); - - sx = (xx + j) * fontwidth(p); - - if (fontwidth(p) <= 8) - o_x = (8 - (sx & 0x7)) & 0x7; - else if (fontwidth(p) <= 16) - o_x = (16 - (sx & 0xF)) & 0xF; - - PM3_WAIT(3 + fontheight(p)); - - PM3_WRITE_REG(PM3AreaStippleMode, (o_x << 7) | (o_y << 12) | /* x_offset, y_offset in pattern */ - (1 << 18) | /* BE */ - 1 | (asx << 1) | (asy << 4) | /* address select x/y */ - (1 << 20)); /* OpaqueSpan */ - - for (i = 0; i < fontheight(p); i++) { /* assume fontheight <= 32 */ - if (fontwidth(p) <= 8) { - ldat = *cdat++; - } else { /* assume fontwidth <= 16 ATM */ - ldat = ((*cdat++) << 8); - ldat |= *cdat++; - } - PM3_WRITE_REG(AreaStipplePattern_indexed(i), ldat); - } - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(sx)) | - (PM3RectanglePosition_YOffset(sy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_AreaStippleEnable | - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(fontwidth(p))) | - (PM3Render2D_Height(fontheight(p)))); - } - pm3fb_wait_pm3(l_fb_info); -} + par->video |= PM3VideoControl_LINE_DOUBLE_OFF; -static void pm3fb_cfbX_revc(struct display *p, int xx, int yy) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info; - - xx = xx * fontwidth(p); - yy = yy * fontheight(p); - - if (l_fb_info->current_par->depth == 8) - { - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0x0F0F0F0F); - else - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F); + if (info->var.activate == FB_ACTIVATE_NOW) + par->video |= PM3VideoControl_ENABLE; + else { + par->video |= PM3VideoControl_DISABLE; + DPRINTK("PM3Video disabled\n"); } - - PM3_WAIT(3); - - PM3_WRITE_REG(PM3Config2D, - PM3Config2D_UseConstantSource | - PM3Config2D_ForegroundROPEnable | - (PM3Config2D_ForegroundROP(0xa)) | /* Oxa is GXinvert */ - PM3Config2D_FBDestReadEnable | - PM3Config2D_FBWriteEnable); - - PM3_WRITE_REG(PM3RectanglePosition, - (PM3RectanglePosition_XOffset(xx)) | - (PM3RectanglePosition_YOffset(yy))); - - PM3_WRITE_REG(PM3Render2D, - PM3Render2D_XPositive | - PM3Render2D_YPositive | - PM3Render2D_Operation_Normal | - PM3Render2D_SpanOperation | - (PM3Render2D_Width(fontwidth(p))) | - (PM3Render2D_Height(fontheight(p)))); - - pm3fb_wait_pm3(l_fb_info); - - if (l_fb_info->current_par->depth == 8) - { - if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask) - PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xFFFFFFFF); - else - PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF); - } -} - -#endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */ -#endif /* PM3FB_USE_ACCEL */ -/* *********************************** */ -/* ***** pre-init board(s) setup ***** */ -/* *********************************** */ - -static void pm3fb_mode_setup(char *mode, unsigned long board_num) -{ - struct pm3fb_info *l_fb_info = &(fb_info[board_num]); - struct pm3fb_par *l_fb_par = &(current_par[board_num]); - unsigned long i = 0; - - current_par_valid[board_num] = 0; - - if (!strncmp(mode, "current", 7)) { - l_fb_info->use_current = 1; /* default w/ OpenFirmware */ - } else { - while ((mode_base[i].name[0]) - && (!current_par_valid[board_num])) { - if (! - (strncmp - (mode, mode_base[i].name, - strlen(mode_base[i].name)))) { - memcpy(l_fb_par, &(mode_base[i].user_mode), - sizeof(struct pm3fb_par)); - current_par_valid[board_num] = 1; - DPRINTK(2, "Mode set to %s\n", - mode_base[i].name); - } - i++; - } - DASSERT(current_par_valid[board_num], - "Valid mode on command line\n"); - } -} - -static void pm3fb_pciid_setup(char *pciid, unsigned long board_num) -{ - short l_bus = -1, l_slot = -1, l_func = -1; - char *next; - - if (pciid) { - l_bus = simple_strtoul(pciid, &next, 10); - if (next && (next[0] == ':')) { - pciid = next + 1; - l_slot = simple_strtoul(pciid, &next, 10); - if (next && (next[0] == ':')) { - pciid = next + 1; - l_func = - simple_strtoul(pciid, (char **) NULL, - 10); - } - } - } else - return; - - if ((l_bus >= 0) && (l_slot >= 0) && (l_func >= 0)) { - bus[board_num] = l_bus; - slot[board_num] = l_slot; - func[board_num] = l_func; - DPRINTK(2, "Board #%ld will be PciId: %hd:%hd:%hd\n", - board_num, l_bus, l_slot, l_func); - } else { - DPRINTK(1, "Invalid PciId: %hd:%hd:%hd for board #%ld\n", - l_bus, l_slot, l_func, board_num); - } -} - -static void pm3fb_font_setup(char *lf, unsigned long board_num) -{ - unsigned long lfs = strlen(lf); - - if (lfs > (PM3_FONTNAME_SIZE - 1)) { - DPRINTK(1, "Fontname %s too long\n", lf); - return; - } - strlcpy(fontn[board_num], lf, lfs + 1); -} - -static void pm3fb_bootdepth_setup(char *bds, unsigned long board_num) -{ - unsigned long bd = simple_strtoul(bds, (char **) NULL, 10); - - if (!(depth_supported(bd))) { - printk(KERN_WARNING "pm3fb: ignoring invalid depth %s for board #%ld\n", - bds, board_num); - return; - } - depth[board_num] = bd; -} - -static void pm3fb_forcesize_setup(char *bds, unsigned long board_num) -{ - unsigned long bd = simple_strtoul(bds, (char **) NULL, 10); - - if (bd > 64) { - printk(KERN_WARNING "pm3fb: ignoring invalid memory size %s for board #%ld\n", - bds, board_num); - return; - } - forcesize[board_num] = bd; -} - -static char *pm3fb_boardnum_setup(char *options, unsigned long *bn) -{ - char *next; - - if (!(isdigit(options[0]))) { - (*bn) = 0; - return (options); - } - - (*bn) = simple_strtoul(options, &next, 10); - - if (next && (next[0] == ':') && ((*bn) >= 0) - && ((*bn) <= PM3_MAX_BOARD)) { - DPRINTK(2, "Board_num seen as %ld\n", (*bn)); - return (next + 1); - } else { - (*bn) = 0; - DPRINTK(2, "Board_num default to %ld\n", (*bn)); - return (options); - } -} - -static void pm3fb_real_setup(char *options) -{ - char *next; - unsigned long i, bn; - struct pm3fb_info *l_fb_info; - - DTRACE; - - DPRINTK(2, "Options : %s\n", options); - - for (i = 0; i < PM3_MAX_BOARD; i++) { - l_fb_info = &(fb_info[i]); - memset(l_fb_info, 0, sizeof(struct pm3fb_info)); - l_fb_info->gen.fbhw = &pm3fb_switch; - l_fb_info->board_num = i; - current_par_valid[i] = 0; - slot[i] = -1; - func[i] = -1; - bus[i] = -1; - disable[i] = 0; - noaccel[i] = 0; - fontn[i][0] = '\0'; - depth[i] = 0; - l_fb_info->current_par = &(current_par[i]); - } - - /* eat up prefix pm3fb and whatever is used as separator i.e. :,= */ - if (!strncmp(options, "pm3fb", 5)) { - options += 5; - while (((*options) == ',') || ((*options) == ':') - || ((*options) == '=')) - options++; - } - - while (options) { - bn = 0; - if ((next = strchr(options, ','))) { - (*next) = '\0'; - next++; - } - - if (!strncmp(options, "mode:", 5)) { - options = pm3fb_boardnum_setup(options + 5, &bn); - DPRINTK(2, "Setting mode for board #%ld\n", bn); - pm3fb_mode_setup(options, bn); - } else if (!strncmp(options, "off:", 4)) { - options = pm3fb_boardnum_setup(options + 4, &bn); - DPRINTK(2, "Disabling board #%ld\n", bn); - disable[bn] = 1; - } else if (!strncmp(options, "off", 3)) { /* disable everything */ - for (i = 0; i < PM3_MAX_BOARD; i++) - disable[i] = 1; - } else if (!strncmp(options, "disable:", 8)) { - options = pm3fb_boardnum_setup(options + 8, &bn); - DPRINTK(2, "Disabling board #%ld\n", bn); - disable[bn] = 1; - } else if (!strncmp(options, "pciid:", 6)) { - options = pm3fb_boardnum_setup(options + 6, &bn); - DPRINTK(2, "Setting PciID for board #%ld\n", bn); - pm3fb_pciid_setup(options, bn); - } else if (!strncmp(options, "noaccel:", 8)) { - options = pm3fb_boardnum_setup(options + 8, &bn); - noaccel[bn] = 1; - } else if (!strncmp(options, "font:", 5)) { - options = pm3fb_boardnum_setup(options + 5, &bn); - pm3fb_font_setup(options, bn); - } else if (!strncmp(options, "depth:", 6)) { - options = pm3fb_boardnum_setup(options + 6, &bn); - pm3fb_bootdepth_setup(options, bn); - } else if (!strncmp(options, "printtimings", 12)) { - printtimings = 1; - } else if (!strncmp(options, "flatpanel:", 10)) { - options = pm3fb_boardnum_setup(options + 10, &bn); - flatpanel[bn] = 1; - } else if (!strncmp(options, "forcesize:", 10)) { - options = pm3fb_boardnum_setup(options + 10, &bn); - pm3fb_forcesize_setup(options, bn); - } - options = next; - } -} - -/* ********************************************** */ -/* ***** framebuffer API standard functions ***** */ -/* ********************************************** */ - -static int pm3fb_encode_fix(struct fb_fix_screeninfo *fix, - const void *par, struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - struct pm3fb_par *p = (struct pm3fb_par *) par; - - DTRACE; - - strcpy(fix->id, permedia3_name); - fix->smem_start = (unsigned long)l_fb_info->p_fb; - fix->smem_len = l_fb_info->fb_size; - fix->mmio_start = (unsigned long)l_fb_info->pIOBase; - fix->mmio_len = PM3_REGS_SIZE; -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - fix->accel = FB_ACCEL_3DLABS_PERMEDIA3; - else -#endif /* PM3FB_USE_ACCEL */ - fix->accel = FB_ACCEL_NONE; - fix->type = FB_TYPE_PACKED_PIXELS; - fix->visual = - (p->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - if (current_par_valid[l_fb_info->board_num]) - fix->line_length = - l_fb_info->current_par->width * - depth2ByPP(l_fb_info->current_par->depth); - else - fix->line_length = 0; - fix->xpanstep = 64 / depth2bpp(p->depth); - fix->ypanstep = 1; - fix->ywrapstep = 0; - return (0); -} - -static int pm3fb_decode_var(const struct fb_var_screeninfo *var, - void *par, struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - struct pm3fb_par *p = (struct pm3fb_par *) par; - struct pm3fb_par temp_p; - u32 xres; - - DTRACE; - - DASSERT((var != NULL), "fb_var_screeninfo* not NULL"); - DASSERT((p != NULL), "pm3fb_par* not NULL"); - DASSERT((l_fb_info != NULL), "pm3fb_info* not NULL"); - - memset(&temp_p, 0, sizeof(struct pm3fb_par)); - temp_p.width = (var->xres_virtual + 7) & ~7; - temp_p.height = var->yres_virtual; - - if (!(depth_supported(var->bits_per_pixel))) /* round unsupported up to a multiple of 8 */ - temp_p.depth = depth2bpp(var->bits_per_pixel); - else - temp_p.depth = var->bits_per_pixel; - - temp_p.depth = (temp_p.depth > 32) ? 32 : temp_p.depth; /* max 32 */ - temp_p.depth = (temp_p.depth == 24) ? 32 : temp_p.depth; /* 24 unsupported, round-up to 32 */ - - if ((temp_p.depth == 16) && (var->red.length == 5) && (var->green.length == 5) && (var->blue.length == 5)) - temp_p.depth = 15; /* RGBA 5551 is stored as depth 15 */ - - if ((temp_p.depth == 16) && (var->red.length == 4) && (var->green.length == 4) && (var->blue.length == 4)) - temp_p.depth = 12; /* RGBA 4444 is stored as depth 12 */ - - - DPRINTK(2, - "xres: %d, yres: %d, vxres: %d, vyres: %d ; xoffset:%d, yoffset: %d\n", - var->xres, var->yres, var->xres_virtual, var->yres_virtual, - var->xoffset, var->yoffset); - - xres = (var->xres + 31) & ~31; - if (temp_p.width < xres + var->xoffset) - temp_p.width = xres + var->xoffset; - if (temp_p.height < var->yres + var->yoffset) - temp_p.height = var->yres + var->yoffset; - - if (temp_p.width > 2048) { - DPRINTK(1, "virtual width not supported: %u\n", - temp_p.width); - return (-EINVAL); - } - if (var->yres < 200) { - DPRINTK(1, "height not supported: %u\n", (u32) var->yres); - return (-EINVAL); - } - if (temp_p.height < 200 || temp_p.height > 4095) { - DPRINTK(1, "virtual height not supported: %u\n", - temp_p.height); - return (-EINVAL); - } - if (!(depth_supported(temp_p.depth))) { - DPRINTK(1, "depth not supported: %u\n", temp_p.depth); - return (-EINVAL); - } - if ((temp_p.width * temp_p.height * depth2ByPP(temp_p.depth)) > - l_fb_info->fb_size) { - DPRINTK(1, "no memory for screen (%ux%ux%u)\n", - temp_p.width, temp_p.height, temp_p.depth); - return (-EINVAL); - } - - if ((!var->pixclock) || - (!var->right_margin) || - (!var->hsync_len) || - (!var->left_margin) || - (!var->lower_margin) || - (!var->vsync_len) || (!var->upper_margin) - ) { - unsigned long i = 0, done = 0; - printk(KERN_WARNING "pm3fb: refusing to use a likely wrong timing\n"); - - while ((mode_base[i].user_mode.width) && !done) { - if ((mode_base[i].user_mode.width == temp_p.width) - && (mode_base[i].user_mode.height == - temp_p.height)) { - printk(KERN_NOTICE "pm3fb: using close match %s\n", - mode_base[i].name); - temp_p = mode_base[i].user_mode; - done = 1; - } - i++; - } - if (!done) - return (-EINVAL); - } else { - temp_p.pixclock = PICOS2KHZ(var->pixclock); - if (temp_p.pixclock > PM3_MAX_PIXCLOCK) { - DPRINTK(1, "pixclock too high (%uKHz)\n", - temp_p.pixclock); - return (-EINVAL); - } - - temp_p.hsstart = var->right_margin; - temp_p.hsend = var->right_margin + var->hsync_len; - temp_p.hbend = - var->right_margin + var->hsync_len + var->left_margin; - temp_p.htotal = xres + temp_p.hbend; - - temp_p.vsstart = var->lower_margin; - temp_p.vsend = var->lower_margin + var->vsync_len; - temp_p.vbend = - var->lower_margin + var->vsync_len + var->upper_margin; - temp_p.vtotal = var->yres + temp_p.vbend; - - temp_p.stride = temp_p.width; - - DPRINTK(2, "Using %d * %d, %d Khz, stride is %08x\n", - temp_p.width, temp_p.height, temp_p.pixclock, - temp_p.stride); - - temp_p.base = - pm3fb_Shiftbpp(l_fb_info, temp_p.depth, - (var->yoffset * xres) + var->xoffset); - - temp_p.video = 0; - - if (var->sync & FB_SYNC_HOR_HIGH_ACT) - temp_p.video |= PM3VideoControl_HSYNC_ACTIVE_HIGH; - else - temp_p.video |= PM3VideoControl_HSYNC_ACTIVE_LOW; - - if (var->sync & FB_SYNC_VERT_HIGH_ACT) - temp_p.video |= PM3VideoControl_VSYNC_ACTIVE_HIGH; - else - temp_p.video |= PM3VideoControl_VSYNC_ACTIVE_LOW; - - if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { - DPRINTK(1, "Interlaced mode not supported\n\n"); - return (-EINVAL); - } - - if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) - temp_p.video |= PM3VideoControl_LINE_DOUBLE_ON; - else - temp_p.video |= PM3VideoControl_LINE_DOUBLE_OFF; - - if (var->activate == FB_ACTIVATE_NOW) - temp_p.video |= PM3VideoControl_ENABLE; - else { - temp_p.video |= PM3VideoControl_DISABLE; - DPRINTK(2, "PM3Video disabled\n"); - } - - switch (temp_p.depth) { - case 8: - temp_p.video |= PM3VideoControl_PIXELSIZE_8BIT; - break; - case 12: - case 15: - case 16: - temp_p.video |= PM3VideoControl_PIXELSIZE_16BIT; - break; - case 32: - temp_p.video |= PM3VideoControl_PIXELSIZE_32BIT; - break; - default: - DPRINTK(1, "Unsupported depth\n"); - break; - } - } - (*p) = temp_p; - -#ifdef PM3FB_USE_ACCEL - if (var->accel_flags & FB_ACCELF_TEXT) - noaccel[l_fb_info->board_num] = 0; - else - noaccel[l_fb_info->board_num] = 1; -#endif /* PM3FB_USE_ACCEL */ - - return (0); -} - -static void pm3fb_encode_depth(struct fb_var_screeninfo *var, long d) -{ - switch (d) { + switch (depth) { case 8: - var->red.length = var->green.length = var->blue.length = 8; - var->red.offset = var->green.offset = var->blue.offset = 0; - var->transp.offset = var->transp.length = 0; + par->video |= PM3VideoControl_PIXELSIZE_8BIT; break; - case 12: - var->red.offset = 8; - var->red.length = 4; - var->green.offset = 4; - var->green.length = 4; - var->blue.offset = 0; - var->blue.length = 4; - var->transp.offset = 12; - var->transp.length = 4; - break; - case 15: - var->red.offset = 10; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 5; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 15; - var->transp.length = 1; - break; - case 16: - 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 = var->transp.length = 0; + par->video |= PM3VideoControl_PIXELSIZE_16BIT; break; - case 32: - var->transp.offset = 24; - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; - var->red.length = var->green.length = - var->blue.length = var->transp.length = 8; + par->video |= PM3VideoControl_PIXELSIZE_32BIT; break; - default: - DPRINTK(1, "Unsupported depth %ld\n", d); + DPRINTK("Unsupported depth\n"); break; } -} -static int pm3fb_encode_var(struct fb_var_screeninfo *var, - const void *par, struct fb_info_gen *info) -{ - struct pm3fb_par *p = (struct pm3fb_par *) par; - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - u32 base; - - DTRACE; - - DASSERT((var != NULL), "fb_var_screeninfo* not NULL"); - DASSERT((p != NULL), "pm3fb_par* not NULL"); - DASSERT((info != NULL), "fb_info_gen* not NULL"); - - memset(var, 0, sizeof(struct fb_var_screeninfo)); - -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - var->accel_flags |= FB_ACCELF_TEXT; -#endif /* PM3FB_USE_ACCEL */ - - var->xres_virtual = p->width; - var->yres_virtual = p->height; - var->xres = p->htotal - p->hbend; - var->yres = p->vtotal - p->vbend; - - DPRINTK(2, "xres = %d, yres : %d\n", var->xres, var->yres); - - var->right_margin = p->hsstart; - var->hsync_len = p->hsend - p->hsstart; - var->left_margin = p->hbend - p->hsend; - var->lower_margin = p->vsstart; - var->vsync_len = p->vsend - p->vsstart; - var->upper_margin = p->vbend - p->vsend; - var->bits_per_pixel = depth2bpp(p->depth); - - pm3fb_encode_depth(var, p->depth); - - base = pm3fb_Unshiftbpp(l_fb_info, p->depth, p->base); - - var->xoffset = base % var->xres; - var->yoffset = base / var->xres; - - var->height = var->width = -1; - - var->pixclock = KHZ2PICOS(p->pixclock); - - if ((p->video & PM3VideoControl_HSYNC_MASK) == - PM3VideoControl_HSYNC_ACTIVE_HIGH) - var->sync |= FB_SYNC_HOR_HIGH_ACT; - if ((p->video & PM3VideoControl_VSYNC_MASK) == - PM3VideoControl_VSYNC_ACTIVE_HIGH) - var->sync |= FB_SYNC_VERT_HIGH_ACT; - if (p->video & PM3VideoControl_LINE_DOUBLE_ON) - var->vmode = FB_VMODE_DOUBLE; - - return (0); -} - -static void pm3fb_get_par(void *par, struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - DTRACE; + info->fix.visual = + (depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + info->fix.line_length = ((info->var.xres_virtual + 7) & ~7) + * depth / 8; - if (!current_par_valid[l_fb_info->board_num]) { - if (l_fb_info->use_current) - pm3fb_read_mode(l_fb_info, l_fb_info->current_par); - else - memcpy(l_fb_info->current_par, - &(mode_base[0].user_mode), - sizeof(struct pm3fb_par)); - current_par_valid[l_fb_info->board_num] = 1; - } - *((struct pm3fb_par *) par) = *(l_fb_info->current_par); -} - -static void pm3fb_set_par(const void *par, struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - DTRACE; - - *(l_fb_info->current_par) = *((struct pm3fb_par *) par); - current_par_valid[l_fb_info->board_num] = 1; - - pm3fb_write_mode(l_fb_info); - -#ifdef PM3FB_USE_ACCEL - pm3fb_init_engine(l_fb_info); -#endif /* PM3FB_USE_ACCEL */ -} - -static void pm3fb_set_color(struct pm3fb_info *l_fb_info, - unsigned char regno, unsigned char r, - unsigned char g, unsigned char b) -{ - DTRACE; - - PM3_SLOW_WRITE_REG(PM3RD_PaletteWriteAddress, regno); - PM3_SLOW_WRITE_REG(PM3RD_PaletteData, r); - PM3_SLOW_WRITE_REG(PM3RD_PaletteData, g); - PM3_SLOW_WRITE_REG(PM3RD_PaletteData, b); -} - -static int pm3fb_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - DTRACE; - - if (regno < 256) { - *red = - l_fb_info->palette[regno].red << 8 | l_fb_info-> - palette[regno].red; - *green = - l_fb_info->palette[regno].green << 8 | l_fb_info-> - palette[regno].green; - *blue = - l_fb_info->palette[regno].blue << 8 | l_fb_info-> - palette[regno].blue; - *transp = - l_fb_info->palette[regno].transp << 8 | l_fb_info-> - palette[regno].transp; - } - return (regno > 255); +/* pm3fb_clear_memory(info, 0);*/ + pm3fb_clear_colormap(par, 0, 0, 0); + PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, + PM3RD_CursorMode_CURSOR_DISABLE); + pm3fb_write_mode(info); + return 0; } static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - - DTRACE; + struct pm3_par *par = info->par; + + if (regno >= 256) /* no. of hw registers */ + return -EINVAL; + + /* grayscale works only partially under directcolor */ + if (info->var.grayscale) { + /* grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; + } + + /* Directcolor: + * var->{color}.offset contains start of bitfield + * var->{color}.length contains length of bitfield + * {hardwarespecific} contains width of DAC + * pseudo_palette[X] is programmed to (X << red.offset) | + * (X << green.offset) | + * (X << blue.offset) + * RAMDAC[X] is programmed to (red, green, blue) + * color depth = SUM(var->{color}.length) + * + * Pseudocolor: + * var->{color}.offset is 0 + * var->{color}.length contains width of DAC or the number of unique + * colors available (color depth) + * pseudo_palette is not used + * RAMDAC[X] is programmed to (red, green, blue) + * color depth = var->{color}.length + */ - if (regno < 16) { - switch (l_fb_info->current_par->depth) { -#ifdef FBCON_HAS_CFB8 + /* + * This is the point where the color is converted to something that + * is acceptable by the hardware. + */ +#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) + red = CNVT_TOHW(red, info->var.red.length); + green = CNVT_TOHW(green, info->var.green.length); + blue = CNVT_TOHW(blue, info->var.blue.length); + transp = CNVT_TOHW(transp, info->var.transp.length); +#undef CNVT_TOHW + + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + u32 v; + + if (regno >= 16) + return -EINVAL; + + v = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + + switch (info->var.bits_per_pixel) { case 8: break; -#endif -#ifdef FBCON_HAS_CFB16 - case 12: - l_fb_info->cmap.cmap12[regno] = - (((u32) red & 0xf000) >> 4) | - (((u32) green & 0xf000) >> 8) | - (((u32) blue & 0xf000) >> 12); - break; - - case 15: - l_fb_info->cmap.cmap15[regno] = - (((u32) red & 0xf800) >> 1) | - (((u32) green & 0xf800) >> 6) | - (((u32) blue & 0xf800) >> 11); - break; - case 16: - l_fb_info->cmap.cmap16[regno] = - ((u32) red & 0xf800) | - (((u32) green & 0xfc00) >> 5) | - (((u32) blue & 0xf800) >> 11); - break; -#endif -#ifdef FBCON_HAS_CFB32 + case 24: case 32: - l_fb_info->cmap.cmap32[regno] = - (((u32) transp & 0xff00) << 16) | - (((u32) red & 0xff00) << 8) | - (((u32) green & 0xff00)) | - (((u32) blue & 0xff00) >> 8); - break; -#endif - default: - DPRINTK(1, "bad depth %u\n", - l_fb_info->current_par->depth); + ((u32*)(info->pseudo_palette))[regno] = v; break; } + return 0; } - if (regno < 256) { - l_fb_info->palette[regno].red = red >> 8; - l_fb_info->palette[regno].green = green >> 8; - l_fb_info->palette[regno].blue = blue >> 8; - l_fb_info->palette[regno].transp = transp >> 8; - if (l_fb_info->current_par->depth == 8) - pm3fb_set_color(l_fb_info, regno, red >> 8, - green >> 8, blue >> 8); - } - return (regno > 255); + else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) + pm3fb_set_color(par, regno, red, green, blue); + + return 0; } -static int pm3fb_blank(int blank_mode, struct fb_info_gen *info) +static int pm3fb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) { - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - u32 video; - - DTRACE; + struct pm3_par *par = info->par; + const u32 xres = (var->xres + 31) & ~31; - if (!current_par_valid[l_fb_info->board_num]) - return (1); + par->base = pm3fb_shift_bpp(var->bits_per_pixel, + (var->yoffset * xres) + + var->xoffset); + PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base); + return 0; +} - video = l_fb_info->current_par->video; +static int pm3fb_blank(int blank_mode, struct fb_info *info) +{ + struct pm3_par *par = info->par; + u32 video = par->video; /* * Oxygen VX1 - it appears that setting PM3VideoControl and @@ -3181,454 +663,345 @@ static int pm3fb_blank(int blank_mode, struct fb_info_gen *info) video |= PM3VideoControl_HSYNC_ACTIVE_HIGH | PM3VideoControl_VSYNC_ACTIVE_HIGH; - if (blank_mode > 0) { - switch (blank_mode - 1) { - - case VESA_NO_BLANKING: /* FIXME */ - video = video & ~(PM3VideoControl_ENABLE); - break; - - case VESA_HSYNC_SUSPEND: - video = video & ~(PM3VideoControl_HSYNC_MASK | - PM3VideoControl_BLANK_ACTIVE_LOW); - break; - case VESA_VSYNC_SUSPEND: - video = video & ~(PM3VideoControl_VSYNC_MASK | - PM3VideoControl_BLANK_ACTIVE_LOW); - break; - case VESA_POWERDOWN: - video = video & ~(PM3VideoControl_HSYNC_MASK | - PM3VideoControl_VSYNC_MASK | - PM3VideoControl_BLANK_ACTIVE_LOW); - break; - default: - DPRINTK(1, "Unsupported blanking %d\n", - blank_mode); - return (1); - break; - } - } - - PM3_SLOW_WRITE_REG(PM3VideoControl, video); - - return (0); -} - -static void pm3fb_set_disp(const void *par, struct display *disp, - struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - struct pm3fb_par *p = (struct pm3fb_par *) par; - u32 flags; - - DTRACE; - - local_irq_save(flags); - info->info.screen_base = l_fb_info->v_fb; - switch (p->depth) { -#ifdef FBCON_HAS_CFB8 - case 8: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb8; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb8; + switch (blank_mode) { + case FB_BLANK_UNBLANK: + video = video | PM3VideoControl_ENABLE; break; -#endif -#ifdef FBCON_HAS_CFB16 - case 12: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb16; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = l_fb_info->cmap.cmap12; + case FB_BLANK_NORMAL: /* FIXME */ + video = video & ~(PM3VideoControl_ENABLE); break; - case 15: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb16; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = l_fb_info->cmap.cmap15; + case FB_BLANK_HSYNC_SUSPEND: + video = video & ~(PM3VideoControl_HSYNC_MASK | + PM3VideoControl_BLANK_ACTIVE_LOW); break; - case 16: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb16; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = l_fb_info->cmap.cmap16; + case FB_BLANK_VSYNC_SUSPEND: + video = video & ~(PM3VideoControl_VSYNC_MASK | + PM3VideoControl_BLANK_ACTIVE_LOW); break; -#endif -#ifdef FBCON_HAS_CFB32 - case 32: -#ifdef PM3FB_USE_ACCEL - if (!(noaccel[l_fb_info->board_num])) - disp->dispsw = &pm3fb_cfb32; - else -#endif /* PM3FB_USE_ACCEL */ - disp->dispsw = &fbcon_cfb32; - disp->dispsw_data = l_fb_info->cmap.cmap32; + case FB_BLANK_POWERDOWN: + video = video & ~(PM3VideoControl_HSYNC_MASK | + PM3VideoControl_VSYNC_MASK | + PM3VideoControl_BLANK_ACTIVE_LOW); break; -#endif /* FBCON_HAS_CFB32 */ default: - disp->dispsw = &fbcon_dummy; - DPRINTK(1, "Invalid depth, using fbcon_dummy\n"); - break; + DPRINTK("Unsupported blanking %d\n", blank_mode); + return 1; } - local_irq_restore(flags); + + PM3_SLOW_WRITE_REG(par,PM3VideoControl, video); + + return 0; } -/* */ -static void pm3fb_detect(void) -{ - struct pci_dev *dev_array[PM3_MAX_BOARD]; - struct pci_dev *dev = NULL; - struct pm3fb_info *l_fb_info = &(fb_info[0]); - unsigned long i, j, done; + /* + * Frame buffer operations + */ - DTRACE; +static struct fb_ops pm3fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = pm3fb_check_var, + .fb_set_par = pm3fb_set_par, + .fb_setcolreg = pm3fb_setcolreg, + .fb_pan_display = pm3fb_pan_display, + .fb_fillrect = cfb_fillrect, /* Needed !!! */ + .fb_copyarea = cfb_copyarea, /* Needed !!! */ + .fb_imageblit = cfb_imageblit, /* Needed !!! */ + .fb_blank = pm3fb_blank, +}; - for (i = 0; i < PM3_MAX_BOARD; i++) { - dev_array[i] = NULL; - fb_info[i].dev = NULL; - } +/* ------------------------------------------------------------------------- */ - dev = pci_get_device(PCI_VENDOR_ID_3DLABS, - PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev); + /* + * Initialization + */ - for (i = 0; ((i < PM3_MAX_BOARD) && dev); i++) { - dev_array[i] = dev; - dev = pci_get_device(PCI_VENDOR_ID_3DLABS, - PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev); - } +/* mmio register are already mapped when this function is called */ +/* the pm3fb_fix.smem_start is also set */ +static unsigned long pm3fb_size_memory(struct pm3_par *par) +{ + unsigned long memsize = 0, tempBypass, i, temp1, temp2; + unsigned char __iomem *screen_mem; - if (dev) { /* more than PM3_MAX_BOARD */ - printk(KERN_WARNING "pm3fb: Warning: more than %d boards found\n", - PM3_MAX_BOARD); + pm3fb_fix.smem_len = 64 * 1024 * 1024; /* request full aperture size */ + /* Linear frame buffer - request region and map it. */ + if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len, + "pm3fb smem")) { + printk(KERN_WARNING "pm3fb: Can't reserve smem.\n"); + return 0; } - - if (!dev_array[0]) { /* not a single board, abort */ - return; + screen_mem = + ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + if (!screen_mem) { + printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n"); + release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + return 0; } - /* allocate user-defined boards */ - for (i = 0; i < PM3_MAX_BOARD; i++) { - if ((bus[i] >= 0) && (slot[i] >= 0) && (func[i] >= 0)) { - for (j = 0; j < PM3_MAX_BOARD; j++) { - if ((dev_array[j] != NULL) && - (dev_array[j]->bus->number == bus[i]) - && (PCI_SLOT(dev_array[j]->devfn) == - slot[i]) - && (PCI_FUNC(dev_array[j]->devfn) == - func[i])) { - fb_info[i].dev = dev_array[j]; - dev_array[j] = NULL; - } - } - } + /* TODO: card-specific stuff, *before* accessing *any* FB memory */ + /* For Appian Jeronimo 2000 board second head */ + + tempBypass = PM3_READ_REG(par, PM3MemBypassWriteMask); + + DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass); + + PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF); + + /* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */ + for (i = 0; i < 32; i++) { + fb_writel(i * 0x00345678, + (screen_mem + (i * 1048576))); + mb(); + temp1 = fb_readl((screen_mem + (i * 1048576))); + + /* Let's check for wrapover, write will fail at 16MB boundary */ + if (temp1 == (i * 0x00345678)) + memsize = i; + else + break; } - /* allocate remaining boards */ - for (i = 0; i < PM3_MAX_BOARD; i++) { - if (fb_info[i].dev == NULL) { - done = 0; - for (j = 0; ((j < PM3_MAX_BOARD) && (!done)); j++) { - if (dev_array[j] != NULL) { - fb_info[i].dev = dev_array[j]; - dev_array[j] = NULL; - done = 1; - } - } + + DPRINTK("First detect pass already got %ld MB\n", memsize + 1); + + if (memsize + 1 == i) { + for (i = 0; i < 32; i++) { + /* Clear first 32MB ; 0 is 0, no need to byteswap */ + writel(0x0000000, + (screen_mem + (i * 1048576))); + mb(); } - } - /* at that point, all PCI Permedia3 are detected and allocated */ - /* now, initialize... or not */ - for (i = 0; i < PM3_MAX_BOARD; i++) { - l_fb_info = &(fb_info[i]); - if (l_fb_info->dev && !disable[i]) { /* PCI device was found and not disabled by user */ - DPRINTK(2, - "found @%lx Vendor %lx Device %lx ; base @ : %lx - %lx - %lx - %lx - %lx - %lx, irq %ld\n", - (unsigned long) l_fb_info->dev, - (unsigned long) l_fb_info->dev->vendor, - (unsigned long) l_fb_info->dev->device, - (unsigned long) - pci_resource_start(l_fb_info->dev, 0), - (unsigned long) - pci_resource_start(l_fb_info->dev, 1), - (unsigned long) - pci_resource_start(l_fb_info->dev, 2), - (unsigned long) - pci_resource_start(l_fb_info->dev, 3), - (unsigned long) - pci_resource_start(l_fb_info->dev, 4), - (unsigned long) - pci_resource_start(l_fb_info->dev, 5), - (unsigned long) l_fb_info->dev->irq); - - l_fb_info->pIOBase = - (unsigned char *) - pci_resource_start(l_fb_info->dev, 0); -#ifdef __BIG_ENDIAN - l_fb_info->pIOBase += PM3_REGS_SIZE; -#endif - l_fb_info->vIOBase = (unsigned char *) -1; - l_fb_info->p_fb = - (unsigned char *) - pci_resource_start(l_fb_info->dev, 1); - l_fb_info->v_fb = (unsigned char *) -1; - - if (!request_mem_region - ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */ - "pm3fb")) { - printk - (KERN_ERR "pm3fb: Error: couldn't request framebuffer memory, board #%ld\n", - l_fb_info->board_num); - continue; - } - if (!request_mem_region - ((unsigned long)l_fb_info->pIOBase, PM3_REGS_SIZE, - "pm3fb I/O regs")) { - printk - (KERN_ERR "pm3fb: Error: couldn't request IObase memory, board #%ld\n", - l_fb_info->board_num); - continue; - } - if (forcesize[l_fb_info->board_num]) - l_fb_info->fb_size = forcesize[l_fb_info->board_num]; - - l_fb_info->fb_size = - pm3fb_size_memory(l_fb_info); - if (l_fb_info->fb_size) { - (void) pci_enable_device(l_fb_info->dev); - pm3fb_common_init(l_fb_info); - } else - printk(KERN_ERR "pm3fb: memory problem, not enabling board #%ld\n", l_fb_info->board_num); + for (i = 32; i < 64; i++) { + fb_writel(i * 0x00345678, + (screen_mem + (i * 1048576))); + mb(); + temp1 = + fb_readl((screen_mem + (i * 1048576))); + temp2 = + fb_readl((screen_mem + ((i - 32) * 1048576))); + /* different value, different RAM... */ + if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) + memsize = i; + else + break; } } -} + DPRINTK("Second detect pass got %ld MB\n", memsize + 1); -static int pm3fb_pan_display(const struct fb_var_screeninfo *var, - struct fb_info_gen *info) -{ - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; + PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass); - DTRACE; + iounmap(screen_mem); + release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + memsize = 1048576 * (memsize + 1); - if (!current_par_valid[l_fb_info->board_num]) - return -EINVAL; + DPRINTK("Returning 0x%08lx bytes\n", memsize); - l_fb_info->current_par->base = /* in 128 bits chunk - i.e. AFTER Shiftbpp */ - pm3fb_Shiftbpp(l_fb_info, - l_fb_info->current_par->depth, - (var->yoffset * l_fb_info->current_par->width) + - var->xoffset); - PM3_SLOW_WRITE_REG(PM3ScreenBase, l_fb_info->current_par->base); - return 0; + return memsize; } -static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) +static int __devinit pm3fb_probe(struct pci_dev *dev, + const struct pci_device_id *ent) { - struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; - u32 cm, i; -#ifdef PM3FB_MASTER_DEBUG - char cc[3]; -#endif /* PM3FB_MASTER_DEBUG */ + struct fb_info *info; + struct pm3_par *par; + struct device* device = &dev->dev; /* for pci drivers */ + int err, retval = -ENXIO; - switch(cmd) - { -#ifdef PM3FB_MASTER_DEBUG - case PM3FBIO_CLEARMEMORY: - if (copy_from_user(&cm, (void *)arg, sizeof(u32))) - return(-EFAULT); - pm3fb_clear_memory(l_fb_info, cm); - return(0); - break; + err = pci_enable_device(dev); + if (err) { + printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err); + return err; + } + /* + * Dynamically allocate info and par + */ + info = framebuffer_alloc(sizeof(struct pm3_par), device); - case PM3FBIO_CLEARCMAP: - if (copy_from_user(cc, (void*)arg, 3 * sizeof(char))) - return(-EFAULT); - pm3fb_clear_colormap(l_fb_info, cc[0], cc[1], cc[2]); - return(0); - break; -#endif /* PM3FB_MASTER_DEBUG */ - - case PM3FBIO_RESETCHIP: - cm = 1; - PM3_SLOW_WRITE_REG(PM3ResetStatus, 1); - for (i = 0 ; (i < 10000) && cm ; i++) - { - PM3_DELAY(10); - cm = PM3_READ_REG(PM3ResetStatus); - } - if (cm) - { - printk(KERN_ERR "pm3fb: chip reset failed with status 0x%x\n", cm); - return(-EIO); - } - /* first thing first, reload memory timings */ - pm3fb_write_memory_timings(l_fb_info); -#ifdef PM3FB_USE_ACCEL - pm3fb_init_engine(l_fb_info); -#endif /* PM3FB_USE_ACCEL */ - pm3fb_write_mode(l_fb_info); - return(0); - break; + if (!info) + return -ENOMEM; + par = info->par; - default: - DPRINTK(2, "unknown ioctl: %d (%x)\n", cmd, cmd); - return(-EINVAL); + /* + * Here we set the screen_base to the virtual memory address + * for the framebuffer. + */ + pm3fb_fix.mmio_start = pci_resource_start(dev, 0); + pm3fb_fix.mmio_len = PM3_REGS_SIZE; + + /* Registers - request region and map it. */ + if (!request_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len, + "pm3fb regbase")) { + printk(KERN_WARNING "pm3fb: Can't reserve regbase.\n"); + goto err_exit_neither; + } + par->v_regs = + ioremap_nocache(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); + if (!par->v_regs) { + printk(KERN_WARNING "pm3fb: Can't remap %s register area.\n", + pm3fb_fix.id); + release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); + goto err_exit_neither; + } + +#if defined(__BIG_ENDIAN) + pm3fb_fix.mmio_start += PM3_REGS_SIZE; + DPRINTK("Adjusting register base for big-endian.\n"); +#endif + /* Linear frame buffer - request region and map it. */ + pm3fb_fix.smem_start = pci_resource_start(dev, 1); + pm3fb_fix.smem_len = pm3fb_size_memory(par); + if (!pm3fb_fix.smem_len) + { + printk(KERN_WARNING "pm3fb: Can't find memory on board.\n"); + goto err_exit_mmio; } -} - -/* ****************************************** */ -/* ***** standard FB API init functions ***** */ -/* ****************************************** */ + if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len, + "pm3fb smem")) { + printk(KERN_WARNING "pm3fb: Can't reserve smem.\n"); + goto err_exit_mmio; + } + info->screen_base = + ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + if (!info->screen_base) { + printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n"); + release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + goto err_exit_mmio; + } + info->screen_size = pm3fb_fix.smem_len; -int __init pm3fb_setup(char *options) -{ - long opsi = strlen(options); + info->fbops = &pm3fb_ops; - DTRACE; + par->video = PM3_READ_REG(par, PM3VideoControl); - memcpy(g_options, options, - ((opsi + 1) > - PM3_OPTIONS_SIZE) ? PM3_OPTIONS_SIZE : (opsi + 1)); - g_options[PM3_OPTIONS_SIZE - 1] = 0; + info->fix = pm3fb_fix; + info->pseudo_palette = par->palette; + info->flags = FBINFO_DEFAULT;/* | FBINFO_HWACCEL_YPAN;*/ - return (0); -} + /* + * This should give a reasonable default video mode. The following is + * done when we can set a video mode. + */ + if (!mode_option) + mode_option = "640x480@60"; -int __init pm3fb_init(void) -{ - DTRACE; + retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); - DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $"); + if (!retval || retval == 4) { + retval = -EINVAL; + goto err_exit_both; + } - pm3fb_real_setup(g_options); + /* This has to been done !!! */ + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + retval = -ENOMEM; + goto err_exit_both; + } - pm3fb_detect(); + /* + * For drivers that can... + */ + pm3fb_check_var(&info->var, info); - if (!fb_info[0].dev) { /* not even one board ??? */ - DPRINTK(1, "No PCI Permedia3 board detected\n"); + if (register_framebuffer(info) < 0) { + retval = -EINVAL; + goto err_exit_all; } - return (0); + printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, + info->fix.id); + pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */ + return 0; + + err_exit_all: + fb_dealloc_cmap(&info->cmap); + err_exit_both: + iounmap(info->screen_base); + release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + err_exit_mmio: + iounmap(par->v_regs); + release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); + err_exit_neither: + framebuffer_release(info); + return retval; } -/* ************************* */ -/* **** Module support ***** */ -/* ************************* */ + /* + * Cleanup + */ +static void __devexit pm3fb_remove(struct pci_dev *dev) +{ + struct fb_info *info = pci_get_drvdata(dev); -#ifdef MODULE -MODULE_AUTHOR("Romain Dolbeau"); -MODULE_DESCRIPTION("Permedia3 framebuffer device driver"); -static char *mode[PM3_MAX_BOARD]; -module_param_array(mode, charp, NULL, 0); -MODULE_PARM_DESC(mode,"video mode"); -module_param_array(disable, short, NULL, 0); -MODULE_PARM_DESC(disable,"disable board"); -static short off[PM3_MAX_BOARD]; -module_param_array(off, short, NULL, 0); -MODULE_PARM_DESC(off,"disable board"); -static char *pciid[PM3_MAX_BOARD]; -module_param_array(pciid, charp, NULL, 0); -MODULE_PARM_DESC(pciid,"board PCI Id"); -module_param_array(noaccel, short, NULL, 0); -MODULE_PARM_DESC(noaccel,"disable accel"); -static char *font[PM3_MAX_BOARD]; -module_param_array(font, charp, NULL, 0); -MODULE_PARM_DESC(font,"choose font"); -module_param(depth, short, NULL, 0); -MODULE_PARM_DESC(depth,"boot-time depth"); -module_param(printtimings, short, NULL, 0); -MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)"); -module_param(forcesize, short, NULL, 0); -MODULE_PARM_DESC(forcesize, "force specified memory size"); -/* -MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards") -MODULE_GENERIC_TABLE(gtype,name) -MODULE_DEVICE_TABLE(type,name) -*/ + if (info) { + struct fb_fix_screeninfo *fix = &info->fix; + struct pm3_par *par = info->par; -void pm3fb_build_options(void) -{ - int i; - char ts[128]; + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - strcpy(g_options, "pm3fb"); - for (i = 0; i < PM3_MAX_BOARD ; i++) - { - if (mode[i]) - { - sprintf(ts, ",mode:%d:%s", i, mode[i]); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (disable[i] || off[i]) - { - sprintf(ts, ",disable:%d:", i); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (pciid[i]) - { - sprintf(ts, ",pciid:%d:%s", i, pciid[i]); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (noaccel[i]) - { - sprintf(ts, ",noaccel:%d:", i); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (font[i]) - { - sprintf(ts, ",font:%d:%s", i, font[i]); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } - if (depth[i]) - { - sprintf(ts, ",depth:%d:%d", i, depth[i]); - strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options)); - } + iounmap(info->screen_base); + release_mem_region(fix->smem_start, fix->smem_len); + iounmap(par->v_regs); + release_mem_region(fix->mmio_start, fix->mmio_len); + + pci_set_drvdata(dev, NULL); + framebuffer_release(info); } - g_options[PM3_OPTIONS_SIZE - 1] = '\0'; - DPRINTK(1, "pm3fb use options: %s\n", g_options); } -int init_module(void) +static struct pci_device_id pm3fb_id_table[] = { + { PCI_VENDOR_ID_3DLABS, 0x0a, + PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, + 0xff0000, 0 }, + { 0, } +}; + +/* For PCI drivers */ +static struct pci_driver pm3fb_driver = { + .name = "pm3fb", + .id_table = pm3fb_id_table, + .probe = pm3fb_probe, + .remove = __devexit_p(pm3fb_remove), +}; + +MODULE_DEVICE_TABLE(pci, pm3fb_id_table); + +int __init pm3fb_init(void) { - DTRACE; + /* + * For kernel boot options (in 'video=pm3fb:<options>' format) + */ +#ifndef MODULE + char *option = NULL; - pm3fb_build_options(); + if (fb_get_options("pm3fb", &option)) + return -ENODEV; + pm3fb_setup(option); +#endif - pm3fb_init(); + return pci_register_driver(&pm3fb_driver); +} - return 0; +static void __exit pm3fb_exit(void) +{ + pci_unregister_driver(&pm3fb_driver); } -void cleanup_module(void) +#ifdef MODULE + /* + * Setup + */ + +/* + * Only necessary if your driver takes special options, + * otherwise we fall back on the generic fb_setup(). + */ +int __init pm3fb_setup(char *options) { - DTRACE; - { - unsigned long i; - struct pm3fb_info *l_fb_info; - for (i = 0; i < PM3_MAX_BOARD; i++) { - l_fb_info = &(fb_info[i]); - pci_dev_put(l_fb_info->dev); - if (l_fb_info->dev != NULL && !(disable[l_fb_info->board_num])) { - if (l_fb_info->vIOBase != (unsigned char *) -1) { - pm3fb_unmapIO(l_fb_info); - release_mem_region(l_fb_info->p_fb, - l_fb_info->fb_size); - release_mem_region(l_fb_info->pIOBase, - PM3_REGS_SIZE); - } - unregister_framebuffer(&l_fb_info->gen.info); - } - } - } + /* Parse user speficied options (`video=pm3fb:') */ + return 0; } #endif /* MODULE */ + +module_init(pm3fb_init); +module_exit(pm3fb_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 81e43cd..9756a72 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c @@ -32,6 +32,8 @@ #include <linux/ioctl.h> #include <linux/notifier.h> #include <linux/reboot.h> +#include <linux/kthread.h> +#include <linux/freezer.h> #include <asm/uaccess.h> #include <linux/fb.h> @@ -45,7 +47,7 @@ #include <asm/ps3.h> #ifdef PS3FB_DEBUG -#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args) +#define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args) #else #define DPRINTK(fmt, args...) #endif @@ -129,7 +131,6 @@ struct ps3fb_priv { u64 context_handle, memory_handle; void *xdr_ea; struct gpu_driver_info *dinfo; - struct semaphore sem; u32 res_index; u64 vblank_count; /* frame count */ @@ -139,6 +140,8 @@ struct ps3fb_priv { atomic_t ext_flip; /* on/off flip with vsync */ atomic_t f_count; /* fb_open count */ int is_blanked; + int is_kicked; + struct task_struct *task; }; static struct ps3fb_priv ps3fb; @@ -294,10 +297,10 @@ static const struct fb_videomode ps3fb_modedb[] = { #define VP_OFF(i) (WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP) #define FB_OFF(i) (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET) -static int ps3fb_mode = 0; +static int ps3fb_mode; module_param(ps3fb_mode, bool, 0); -static char *mode_option __initdata = NULL; +static char *mode_option __initdata; static int ps3fb_get_res_table(u32 xres, u32 yres) @@ -393,7 +396,7 @@ static int ps3fb_sync(u32 frame) if (frame > ps3fb.num_frames - 1) { printk(KERN_WARNING "%s: invalid frame number (%u)\n", - __FUNCTION__, frame); + __func__, frame); return -EINVAL; } offset = xres * yres * BPP * frame; @@ -406,23 +409,26 @@ static int ps3fb_sync(u32 frame) (xres << 16) | yres, xres * BPP); /* line_length */ if (status) - printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n", - __FUNCTION__, status); + printk(KERN_ERR + "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n", + __func__, status); #ifdef HEAD_A status = lv1_gpu_context_attribute(ps3fb.context_handle, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, offset, 0, 0); if (status) - printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n", - __FUNCTION__, status); + printk(KERN_ERR + "%s: lv1_gpu_context_attribute FLIP failed: %d\n", + __func__, status); #endif #ifdef HEAD_B status = lv1_gpu_context_attribute(ps3fb.context_handle, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, offset, 0, 0); if (status) - printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n", - __FUNCTION__, status); + printk(KERN_ERR + "%s: lv1_gpu_context_attribute FLIP failed: %d\n", + __func__, status); #endif return 0; } @@ -631,7 +637,7 @@ static int ps3fb_blank(int blank, struct fb_info *info) { int retval; - DPRINTK("%s: blank:%d\n", __FUNCTION__, blank); + DPRINTK("%s: blank:%d\n", __func__, blank); switch (blank) { case FB_BLANK_POWERDOWN: case FB_BLANK_HSYNC_SUSPEND: @@ -677,13 +683,10 @@ EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync); void ps3fb_flip_ctl(int on) { - if (on) { - if (atomic_read(&ps3fb.ext_flip) > 0) { - atomic_dec(&ps3fb.ext_flip); - } - } else { + if (on) + atomic_dec_if_positive(&ps3fb.ext_flip); + else atomic_inc(&ps3fb.ext_flip); - } } EXPORT_SYMBOL_GPL(ps3fb_flip_ctl); @@ -732,6 +735,11 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, if (copy_from_user(&val, argp, sizeof(val))) break; + if (!(val & PS3AV_MODE_MASK)) { + u32 id = ps3av_get_auto_mode(0); + if (id > 0) + val = (val & ~PS3AV_MODE_MASK) | id; + } DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val); retval = -EINVAL; old_mode = ps3fb_mode; @@ -783,8 +791,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, case PS3FB_IOCTL_OFF: DPRINTK("PS3FB_IOCTL_OFF:\n"); - if (atomic_read(&ps3fb.ext_flip) > 0) - atomic_dec(&ps3fb.ext_flip); + atomic_dec_if_positive(&ps3fb.ext_flip); retval = 0; break; @@ -805,11 +812,14 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, static int ps3fbd(void *arg) { - daemonize("ps3fbd"); - for (;;) { - down(&ps3fb.sem); - if (atomic_read(&ps3fb.ext_flip) == 0) + while (!kthread_should_stop()) { + try_to_freeze(); + set_current_state(TASK_INTERRUPTIBLE); + if (ps3fb.is_kicked) { + ps3fb.is_kicked = 0; ps3fb_sync(0); /* single buffer */ + } + schedule(); } return 0; } @@ -823,15 +833,18 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr) status = lv1_gpu_context_intr(ps3fb.context_handle, &v1); if (status) { printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n", - __FUNCTION__, status); + __func__, status); return IRQ_NONE; } if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) { /* VSYNC */ ps3fb.vblank_count = head->vblank_count; - if (!ps3fb.is_blanked) - up(&ps3fb.sem); + if (ps3fb.task && !ps3fb.is_blanked && + !atomic_read(&ps3fb.ext_flip)) { + ps3fb.is_kicked = 1; + wake_up_process(ps3fb.task); + } wake_up_interruptible(&ps3fb.wait_vsync); } @@ -879,16 +892,16 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev) dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000); if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) { - printk(KERN_ERR "%s: version_driver err:%x\n", __FUNCTION__, + printk(KERN_ERR "%s: version_driver err:%x\n", __func__, dinfo->version_driver); return -EINVAL; } ps3fb.dev = dev; - error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, - &ps3fb.irq_no); + error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, + &ps3fb.irq_no); if (error) { - printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__, + printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __func__, error); return error; } @@ -896,9 +909,9 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev) error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED, "ps3fb vsync", ps3fb.dev); if (error) { - printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__, + printk(KERN_ERR "%s: request_irq failed %d\n", __func__, error); - ps3_free_irq(ps3fb.irq_no); + ps3_irq_plug_destroy(ps3fb.irq_no); return error; } @@ -915,7 +928,7 @@ static int ps3fb_xdr_settings(u64 xdr_lpar) xdr_lpar, ps3fb_videomemory.size, 0); if (status) { printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n", - __FUNCTION__, status); + __func__, status); return -ENXIO; } DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n", @@ -927,8 +940,9 @@ static int ps3fb_xdr_settings(u64 xdr_lpar) xdr_lpar, ps3fb_videomemory.size, GPU_IOIF, 0); if (status) { - printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n", - __FUNCTION__, status); + printk(KERN_ERR + "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n", + __func__, status); return -ENXIO; } return 0; @@ -968,13 +982,14 @@ static int __init ps3fb_probe(struct platform_device *dev) u64 xdr_lpar; int status; unsigned long offset; + struct task_struct *task; /* get gpu context handle */ status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0, &ps3fb.memory_handle, &ddr_lpar); if (status) { printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n", - __FUNCTION__, status); + __func__, status); goto err; } DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar); @@ -985,14 +1000,14 @@ static int __init ps3fb_probe(struct platform_device *dev) &lpar_reports, &lpar_reports_size); if (status) { printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n", - __FUNCTION__, status); + __func__, status); goto err_gpu_memory_free; } /* vsync interrupt */ ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024); if (!ps3fb.dinfo) { - printk(KERN_ERR "%s: ioremap failed\n", __FUNCTION__); + printk(KERN_ERR "%s: ioremap failed\n", __func__); goto err_gpu_context_free; } @@ -1050,16 +1065,25 @@ static int __init ps3fb_probe(struct platform_device *dev) "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n", info->node, ps3fb_videomemory.size >> 10); - kernel_thread(ps3fbd, info, CLONE_KERNEL); + task = kthread_run(ps3fbd, info, "ps3fbd"); + if (IS_ERR(task)) { + retval = PTR_ERR(task); + goto err_unregister_framebuffer; + } + + ps3fb.task = task; + return 0; +err_unregister_framebuffer: + unregister_framebuffer(info); err_fb_dealloc: fb_dealloc_cmap(&info->cmap); err_framebuffer_release: framebuffer_release(info); err_free_irq: free_irq(ps3fb.irq_no, ps3fb.dev); - ps3_free_irq(ps3fb.irq_no); + ps3_irq_plug_destroy(ps3fb.irq_no); err_iounmap_dinfo: iounmap((u8 __iomem *)ps3fb.dinfo); err_gpu_context_free: @@ -1075,7 +1099,7 @@ static void ps3fb_shutdown(struct platform_device *dev) ps3fb_flip_ctl(0); /* flip off */ ps3fb.dinfo->irq.mask = 0; free_irq(ps3fb.irq_no, ps3fb.dev); - ps3_free_irq(ps3fb.irq_no); + ps3_irq_plug_destroy(ps3fb.irq_no); iounmap((u8 __iomem *)ps3fb.dinfo); } @@ -1083,9 +1107,14 @@ void ps3fb_cleanup(void) { int status; + if (ps3fb.task) { + struct task_struct *task = ps3fb.task; + ps3fb.task = NULL; + kthread_stop(task); + } if (ps3fb.irq_no) { free_irq(ps3fb.irq_no, ps3fb.dev); - ps3_free_irq(ps3fb.irq_no); + ps3_irq_plug_destroy(ps3fb.irq_no); } iounmap((u8 __iomem *)ps3fb.dinfo); @@ -1137,8 +1166,9 @@ int ps3fb_set_sync(void) L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); if (status) { - printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n", - __FUNCTION__, status); + printk(KERN_ERR + "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n", + __func__, status); return -1; } #endif @@ -1148,8 +1178,9 @@ int ps3fb_set_sync(void) 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); if (status) { - printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n", - __FUNCTION__, status); + printk(KERN_ERR + "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n", + __func__, status); return -1; } #endif @@ -1174,7 +1205,7 @@ static int __init ps3fb_init(void) error = ps3av_dev_open(); if (error) { - printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__); + printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__); goto err; } @@ -1195,7 +1226,6 @@ static int __init ps3fb_init(void) atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ - init_MUTEX(&ps3fb.sem); init_waitqueue_head(&ps3fb.wait_vsync); ps3fb.num_frames = 1; diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index a93618b..df2909a 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -214,7 +214,7 @@ static int pvr2_init_cable(void); static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val, int size); #ifdef CONFIG_SH_DMA -static ssize_t pvr2fb_write(struct file *file, const char *buf, +static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, size_t count, loff_t *ppos); #endif @@ -674,7 +674,7 @@ static int pvr2_init_cable(void) } #ifdef CONFIG_SH_DMA -static ssize_t pvr2fb_write(struct file *file, const char *buf, +static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, size_t count, loff_t *ppos) { unsigned long dst, start, end, len; diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index b4947c8..81e571d 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -803,7 +803,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); /* enable LCD controller clock */ - pxa_set_cken(CKEN16_LCD, 1); + pxa_set_cken(CKEN_LCD, 1); /* Sequence from 11.7.10 */ LCCR3 = fbi->reg_lccr3; @@ -840,7 +840,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) remove_wait_queue(&fbi->ctrlr_wait, &wait); /* disable LCD controller clock */ - pxa_set_cken(CKEN16_LCD, 0); + pxa_set_cken(CKEN_LCD, 0); } /* @@ -1203,7 +1203,7 @@ static int __init pxafb_parse_options(struct device *dev, char *options) } else goto done; break; - case '0'...'9': + case '0' ... '9': break; default: goto done; diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index d7ece8d..0fe5478 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -317,15 +317,15 @@ static int riva_bl_update_status(struct backlight_device *bd) else level = bd->props.brightness; - tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF; - tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC; + tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF; + tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFFFFFC; if(level > 0) { tmp_pcrt |= 0x1; tmp_pmc |= (1 << 31); /* backlight bit */ tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */ } - par->riva.PCRTC0[0x081C/4] = tmp_pcrt; - par->riva.PMC[0x10F0/4] = tmp_pmc; + NV_WR32(par->riva.PCRTC0, 0x081C, tmp_pcrt); + NV_WR32(par->riva.PMC, 0x10F0, tmp_pmc); return 0; } @@ -1760,13 +1760,13 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd) NVTRACE_ENTER(); dp = pci_device_to_OF_node(pd); for (; dp != NULL; dp = dp->child) { - disptype = get_property(dp, "display-type", NULL); + disptype = of_get_property(dp, "display-type", NULL); if (disptype == NULL) continue; if (strncmp(disptype, "LCD", 3) != 0) continue; for (i = 0; propnames[i] != NULL; ++i) { - pedid = get_property(dp, propnames[i], NULL); + pedid = of_get_property(dp, propnames[i], NULL); if (pedid != NULL) { par->EDID = (unsigned char *)pedid; NVTRACE("LCD found.\n"); @@ -1788,8 +1788,10 @@ static int __devinit riva_get_EDID_i2c(struct fb_info *info) NVTRACE_ENTER(); riva_create_i2c_busses(par); - for (i = 0; i < par->bus; i++) { - riva_probe_i2c_connector(par, i+1, &par->EDID); + for (i = 0; i < 3; i++) { + if (!par->chan[i].par) + continue; + riva_probe_i2c_connector(par, i, &par->EDID); if (par->EDID && !fb_parse_edid(par->EDID, &var)) { printk(PFX "Found EDID Block from BUS %i\n", i); break; @@ -2104,7 +2106,7 @@ err_ret: return ret; } -static void __exit rivafb_remove(struct pci_dev *pd) +static void __devexit rivafb_remove(struct pci_dev *pd) { struct fb_info *info = pci_get_drvdata(pd); struct riva_par *par = info->par; @@ -2185,7 +2187,7 @@ static struct pci_driver rivafb_driver = { .name = "rivafb", .id_table = rivafb_pci_tbl, .probe = rivafb_probe, - .remove = __exit_p(rivafb_remove), + .remove = __devexit_p(rivafb_remove), }; diff --git a/drivers/video/riva/nv4ref.h b/drivers/video/riva/nv4ref.h deleted file mode 100644 index 3b5f911..0000000 --- a/drivers/video/riva/nv4ref.h +++ /dev/null @@ -1,2445 +0,0 @@ - /***************************************************************************\ -|* *| -|* Copyright 1993-1998 NVIDIA, Corporation. All rights reserved. *| -|* *| -|* NOTICE TO USER: The source code is copyrighted under U.S. and *| -|* international laws. Users and possessors of this source code are *| -|* hereby granted a nonexclusive, royalty-free copyright license to *| -|* use this code in individual and commercial software. *| -|* *| -|* Any use of this source code must include, in the user documenta- *| -|* tion and internal comments to the code, notices to the end user *| -|* as follows: *| -|* *| -|* Copyright 1993-1998 NVIDIA, Corporation. All rights reserved. *| -|* *| -|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| -|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| -|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| -|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| -|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| -|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| -|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| -|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| -|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| -|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| -|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| -|* *| -|* U.S. Government End Users. This source code is a "commercial *| -|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| -|* consisting of "commercial computer software" and "commercial *| -|* computer software documentation," as such terms are used in *| -|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| -|* ment only as a commercial end item. Consistent with 48 C.F.R. *| -|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| -|* all U.S. Government End Users acquire the source code with only *| -|* those rights set forth herein. *| -|* *| - \***************************************************************************/ - -/* - * GPL licensing note -- nVidia is allowing a liberal interpretation of - * the documentation restriction above, to merely say that this nVidia's - * copyright and disclaimer should be included with all code derived - * from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 - */ - - /***************************************************************************\ -|* Modified 1999 by Fredrik Reite (fredrik@reite.com) *| - \***************************************************************************/ - - -#ifndef __NV4REF_H__ -#define __NV4REF_H__ - -/* Magic values to lock/unlock extended regs */ -#define NV_CIO_SR_LOCK_INDEX 0x0000001F /* */ -#define NV_CIO_SR_UNLOCK_RW_VALUE 0x00000057 /* */ -#define NV_CIO_SR_UNLOCK_RO_VALUE 0x00000075 /* */ -#define NV_CIO_SR_LOCK_VALUE 0x00000099 /* */ - -#define UNLOCK_EXT_MAGIC 0x57 -#define LOCK_EXT_MAGIC 0x99 /* Any value other than 0x57 will do */ - -#define LOCK_EXT_INDEX 0x6 - -#define NV_PCRTC_HORIZ_TOTAL 0x00 -#define NV_PCRTC_HORIZ_DISPLAY_END 0x01 -#define NV_PCRTC_HORIZ_BLANK_START 0x02 - -#define NV_PCRTC_HORIZ_BLANK_END 0x03 -#define NV_PCRTC_HORIZ_BLANK_END_EVRA 7:7 -#define NV_PCRTC_HORIZ_BLANK_END_DISPLAY_END_SKEW 6:5 -#define NV_PCRTC_HORIZ_BLANK_END_HORIZ_BLANK_END 4:0 - -#define NV_PCRTC_HORIZ_RETRACE_START 0x04 - -#define NV_PCRTC_HORIZ_RETRACE_END 0x05 -#define NV_PCRTC_HORIZ_RETRACE_END_HORIZ_BLANK_END_5 7:7 -#define NV_PCRTC_HORIZ_RETRACE_END_HORIZ_RETRACE_SKEW 6:5 -#define NV_PCRTC_HORIZ_RETRACE_END_HORIZ_RETRACE_END 4:0 - -#define NV_PCRTC_VERT_TOTAL 0x06 - -#define NV_PCRTC_OVERFLOW 0x07 -#define NV_PCRTC_OVERFLOW_VERT_RETRACE_START_9 7:7 -#define NV_PCRTC_OVERFLOW_VERT_DISPLAY_END_9 6:6 -#define NV_PCRTC_OVERFLOW_VERT_TOTAL_9 5:5 -#define NV_PCRTC_OVERFLOW_LINE_COMPARE_8 4:4 -#define NV_PCRTC_OVERFLOW_VERT_BLANK_START_8 3:3 -#define NV_PCRTC_OVERFLOW_VERT_RETRACE_START_8 2:2 -#define NV_PCRTC_OVERFLOW_VERT_DISPLAY_END_8 1:1 -#define NV_PCRTC_OVERFLOW_VERT_TOTAL_8 0:0 - -#define NV_PCRTC_PRESET_ROW_SCAN 0x08 - -#define NV_PCRTC_MAX_SCAN_LINE 0x09 -#define NV_PCRTC_MAX_SCAN_LINE_DOUBLE_SCAN 7:7 -#define NV_PCRTC_MAX_SCAN_LINE_LINE_COMPARE_9 6:6 -#define NV_PCRTC_MAX_SCAN_LINE_VERT_BLANK_START_9 5:5 -#define NV_PCRTC_MAX_SCAN_LINE_MAX_SCAN_LINE 4:0 - -#define NV_PCRTC_CURSOR_START 0x0A -#define NV_PCRTC_CURSOR_END 0x0B -#define NV_PCRTC_START_ADDR_HIGH 0x0C -#define NV_PCRTC_START_ADDR_LOW 0x0D -#define NV_PCRTC_CURSOR_LOCATION_HIGH 0x0E -#define NV_PCRTC_CURSOR_LOCATION_LOW 0x0F - -#define NV_PCRTC_VERT_RETRACE_START 0x10 -#define NV_PCRTC_VERT_RETRACE_END 0x11 -#define NV_PCRTC_VERT_DISPLAY_END 0x12 -#define NV_PCRTC_OFFSET 0x13 -#define NV_PCRTC_UNDERLINE_LOCATION 0x14 -#define NV_PCRTC_VERT_BLANK_START 0x15 -#define NV_PCRTC_VERT_BLANK_END 0x16 -#define NV_PCRTC_MODE_CONTROL 0x17 -#define NV_PCRTC_LINE_COMPARE 0x18 - -/* Extended offset and start address */ -#define NV_PCRTC_REPAINT0 0x19 -#define NV_PCRTC_REPAINT0_OFFSET_10_8 7:5 -#define NV_PCRTC_REPAINT0_START_ADDR_20_16 4:0 - -/* Horizonal extended bits */ -#define NV_PCRTC_HORIZ_EXTRA 0x2d -#define NV_PCRTC_HORIZ_EXTRA_INTER_HALF_START_8 4:4 -#define NV_PCRTC_HORIZ_EXTRA_HORIZ_RETRACE_START_8 3:3 -#define NV_PCRTC_HORIZ_EXTRA_HORIZ_BLANK_START_8 2:2 -#define NV_PCRTC_HORIZ_EXTRA_DISPLAY_END_8 1:1 -#define NV_PCRTC_HORIZ_EXTRA_DISPLAY_TOTAL_8 0:0 - -/* Assorted extra bits */ -#define NV_PCRTC_EXTRA 0x25 -#define NV_PCRTC_EXTRA_OFFSET_11 5:5 -#define NV_PCRTC_EXTRA_HORIZ_BLANK_END_6 4:4 -#define NV_PCRTC_EXTRA_VERT_BLANK_START_10 3:3 -#define NV_PCRTC_EXTRA_VERT_RETRACE_START_10 2:2 -#define NV_PCRTC_EXTRA_VERT_DISPLAY_END_10 1:1 -#define NV_PCRTC_EXTRA_VERT_TOTAL_10 0:0 - -/* Controls how much data the refresh fifo requests */ -#define NV_PCRTC_FIFO_CONTROL 0x1b -#define NV_PCRTC_FIFO_CONTROL_UNDERFLOW_WARN 7:7 -#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH 2:0 -#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_8 0x0 -#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_32 0x1 -#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_64 0x2 -#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_128 0x3 -#define NV_PCRTC_FIFO_CONTROL_BURST_LENGTH_256 0x4 - -/* When the fifo occupancy falls below *twice* the watermark, - * the refresh fifo will start to be refilled. If this value is - * too low, you will get junk on the screen. Too high, and performance - * will suffer. Watermark in units of 8 bytes - */ -#define NV_PCRTC_FIFO 0x20 -#define NV_PCRTC_FIFO_RESET 7:7 -#define NV_PCRTC_FIFO_WATERMARK 5:0 - -/* Various flags */ -#define NV_PCRTC_REPAINT1 0x1a -#define NV_PCRTC_REPAINT1_HSYNC 7:7 -#define NV_PCRTC_REPAINT1_HYSNC_DISABLE 0x01 -#define NV_PCRTC_REPAINT1_HYSNC_ENABLE 0x00 -#define NV_PCRTC_REPAINT1_VSYNC 6:6 -#define NV_PCRTC_REPAINT1_VYSNC_DISABLE 0x01 -#define NV_PCRTC_REPAINT1_VYSNC_ENABLE 0x00 -#define NV_PCRTC_REPAINT1_COMPATIBLE_TEXT 4:4 -#define NV_PCRTC_REPAINT1_COMPATIBLE_TEXT_ENABLE 0x01 -#define NV_PCRTC_REPAINT1_COMPATIBLE_TEXT_DISABLE 0x00 -#define NV_PCRTC_REPAINT1_LARGE_SCREEN 2:2 -#define NV_PCRTC_REPAINT1_LARGE_SCREEN_DISABLE 0x01 -#define NV_PCRTC_REPAINT1_LARGE_SCREEN_ENABLE 0x00 /* >=1280 */ -#define NV_PCRTC_REPAINT1_PALETTE_WIDTH 1:1 -#define NV_PCRTC_REPAINT1_PALETTE_WIDTH_8BITS 0x00 -#define NV_PCRTC_REPAINT1_PALETTE_WIDTH_6BITS 0x01 - -#define NV_PCRTC_GRCURSOR0 0x30 -#define NV_PCRTC_GRCURSOR0_START_ADDR_21_16 5:0 - -#define NV_PCRTC_GRCURSOR1 0x31 -#define NV_PCRTC_GRCURSOR1_START_ADDR_15_11 7:3 -#define NV_PCRTC_GRCURSOR1_SCAN_DBL 1:1 -#define NV_PCRTC_GRCURSOR1_SCAN_DBL_DISABLE 0 -#define NV_PCRTC_GRCURSOR1_SCAN_DBL_ENABLE 1 -#define NV_PCRTC_GRCURSOR1_CURSOR 0:0 -#define NV_PCRTC_GRCURSOR1_CURSOR_DISABLE 0 -#define NV_PCRTC_GRCURSOR1_CURSOR_ENABLE 1 - -/* Controls what the format of the framebuffer is */ -#define NV_PCRTC_PIXEL 0x28 -#define NV_PCRTC_PIXEL_MODE 7:7 -#define NV_PCRTC_PIXEL_MODE_TV 0x01 -#define NV_PCRTC_PIXEL_MODE_VGA 0x00 -#define NV_PCRTC_PIXEL_TV_MODE 6:6 -#define NV_PCRTC_PIXEL_TV_MODE_NTSC 0x00 -#define NV_PCRTC_PIXEL_TV_MODE_PAL 0x01 -#define NV_PCRTC_PIXEL_TV_HORIZ_ADJUST 5:3 -#define NV_PCRTC_PIXEL_FORMAT 1:0 -#define NV_PCRTC_PIXEL_FORMAT_VGA 0x00 -#define NV_PCRTC_PIXEL_FORMAT_8BPP 0x01 -#define NV_PCRTC_PIXEL_FORMAT_16BPP 0x02 -#define NV_PCRTC_PIXEL_FORMAT_32BPP 0x03 - -/* RAMDAC registers and fields */ -#define NV_PRAMDAC 0x00680FFF:0x00680000 /* RW--D */ -#define NV_PRAMDAC_GRCURSOR_START_POS 0x00680300 /* RW-4R */ -#define NV_PRAMDAC_GRCURSOR_START_POS_X 11:0 /* RWXSF */ -#define NV_PRAMDAC_GRCURSOR_START_POS_Y 27:16 /* RWXSF */ -#define NV_PRAMDAC_NVPLL_COEFF 0x00680500 /* RW-4R */ -#define NV_PRAMDAC_NVPLL_COEFF_MDIV 7:0 /* RWIUF */ -#define NV_PRAMDAC_NVPLL_COEFF_NDIV 15:8 /* RWIUF */ -#define NV_PRAMDAC_NVPLL_COEFF_PDIV 18:16 /* RWIVF */ -#define NV_PRAMDAC_MPLL_COEFF 0x00680504 /* RW-4R */ -#define NV_PRAMDAC_MPLL_COEFF_MDIV 7:0 /* RWIUF */ -#define NV_PRAMDAC_MPLL_COEFF_NDIV 15:8 /* RWIUF */ -#define NV_PRAMDAC_MPLL_COEFF_PDIV 18:16 /* RWIVF */ -#define NV_PRAMDAC_VPLL_COEFF 0x00680508 /* RW-4R */ -#define NV_PRAMDAC_VPLL_COEFF_MDIV 7:0 /* RWIUF */ -#define NV_PRAMDAC_VPLL_COEFF_NDIV 15:8 /* RWIUF */ -#define NV_PRAMDAC_VPLL_COEFF_PDIV 18:16 /* RWIVF */ -#define NV_PRAMDAC_PLL_COEFF_SELECT 0x0068050C /* RW-4R */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_DLL_BYPASS 4:4 /* RWIVF */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_DLL_BYPASS_FALSE 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_DLL_BYPASS_TRUE 0x00000001 /* RW--V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_SOURCE 8:8 /* RWIVF */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_SOURCE_DEFAULT 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_SOURCE_PROG 0x00000001 /* RW--V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_BYPASS 12:12 /* RWIVF */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_BYPASS_FALSE 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_MPLL_BYPASS_TRUE 0x00000001 /* RW--V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_SOURCE 16:16 /* RWIVF */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_SOURCE_DEFAULT 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_SOURCE_PROG 0x00000001 /* RW--V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_BYPASS 20:20 /* RWIVF */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_BYPASS_FALSE 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_VPLL_BYPASS_TRUE 0x00000001 /* RW--V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE 25:24 /* RWIVF */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE_VPLL 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE_VIP 0x00000001 /* RW--V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_PCLK_SOURCE_XTALOSC 0x00000002 /* RW--V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO 28:28 /* RWIVF */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB1 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2 0x00000001 /* RW--V */ -#define NV_PRAMDAC_GENERAL_CONTROL 0x00680600 /* RW-4R */ -#define NV_PRAMDAC_GENERAL_CONTROL_FF_COEFF 1:0 /* RWIVF */ -#define NV_PRAMDAC_GENERAL_CONTROL_FF_COEFF_DEF 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_GENERAL_CONTROL_IDC_MODE 4:4 /* RWIVF */ -#define NV_PRAMDAC_GENERAL_CONTROL_IDC_MODE_GAMMA 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_GENERAL_CONTROL_IDC_MODE_INDEX 0x00000001 /* RW--V */ -#define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE 8:8 /* RWIVF */ -#define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_NOTSE 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL 0x00000001 /* RW--V */ -#define NV_PRAMDAC_GENERAL_CONTROL_565_MODE 12:12 /* RWIVF */ -#define NV_PRAMDAC_GENERAL_CONTROL_565_MODE_NOTSEL 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_GENERAL_CONTROL_565_MODE_SEL 0x00000001 /* RW--V */ -#define NV_PRAMDAC_GENERAL_CONTROL_BLK_PEDSTL 16:16 /* RWIVF */ -#define NV_PRAMDAC_GENERAL_CONTROL_BLK_PEDSTL_OFF 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_GENERAL_CONTROL_BLK_PEDSTL_ON 0x00000001 /* RW--V */ -#define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION 17:17 /* RWIVF */ -#define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_37OHM 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM 0x00000001 /* RW--V */ -#define NV_PRAMDAC_GENERAL_CONTROL_BPC 20:20 /* RWIVF */ -#define NV_PRAMDAC_GENERAL_CONTROL_BPC_6BITS 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS 0x00000001 /* RW--V */ -#define NV_PRAMDAC_GENERAL_CONTROL_DAC_SLEEP 24:24 /* RWIVF */ -#define NV_PRAMDAC_GENERAL_CONTROL_DAC_SLEEP_DIS 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_GENERAL_CONTROL_DAC_SLEEP_EN 0x00000001 /* RW--V */ -#define NV_PRAMDAC_GENERAL_CONTROL_PALETTE_CLK 28:28 /* RWIVF */ -#define NV_PRAMDAC_GENERAL_CONTROL_PALETTE_CLK_EN 0x00000000 /* RWI-V */ -#define NV_PRAMDAC_GENERAL_CONTROL_PALETTE_CLK_DIS 0x00000001 /* RW--V */ - -/* Master Control */ -#define NV_PMC 0x00000FFF:0x00000000 /* RW--D */ -#define NV_PMC_BOOT_0 0x00000000 /* R--4R */ -#define NV_PMC_BOOT_0_MINOR_REVISION 3:0 /* C--VF */ -#define NV_PMC_BOOT_0_MINOR_REVISION_0 0x00000000 /* C---V */ -#define NV_PMC_BOOT_0_MAJOR_REVISION 7:4 /* C--VF */ -#define NV_PMC_BOOT_0_MAJOR_REVISION_A 0x00000000 /* C---V */ -#define NV_PMC_BOOT_0_MAJOR_REVISION_B 0x00000001 /* ----V */ -#define NV_PMC_BOOT_0_IMPLEMENTATION 11:8 /* C--VF */ -#define NV_PMC_BOOT_0_IMPLEMENTATION_NV4_0 0x00000000 /* C---V */ -#define NV_PMC_BOOT_0_ARCHITECTURE 15:12 /* C--VF */ -#define NV_PMC_BOOT_0_ARCHITECTURE_NV0 0x00000000 /* ----V */ -#define NV_PMC_BOOT_0_ARCHITECTURE_NV1 0x00000001 /* ----V */ -#define NV_PMC_BOOT_0_ARCHITECTURE_NV2 0x00000002 /* ----V */ -#define NV_PMC_BOOT_0_ARCHITECTURE_NV3 0x00000003 /* ----V */ -#define NV_PMC_BOOT_0_ARCHITECTURE_NV4 0x00000004 /* C---V */ -#define NV_PMC_BOOT_0_FIB_REVISION 19:16 /* C--VF */ -#define NV_PMC_BOOT_0_FIB_REVISION_0 0x00000000 /* C---V */ -#define NV_PMC_BOOT_0_MASK_REVISION 23:20 /* C--VF */ -#define NV_PMC_BOOT_0_MASK_REVISION_A 0x00000000 /* C---V */ -#define NV_PMC_BOOT_0_MASK_REVISION_B 0x00000001 /* ----V */ -#define NV_PMC_BOOT_0_MANUFACTURER 27:24 /* C--UF */ -#define NV_PMC_BOOT_0_MANUFACTURER_NVIDIA 0x00000000 /* C---V */ -#define NV_PMC_BOOT_0_FOUNDRY 31:28 /* C--VF */ -#define NV_PMC_BOOT_0_FOUNDRY_SGS 0x00000000 /* ----V */ -#define NV_PMC_BOOT_0_FOUNDRY_HELIOS 0x00000001 /* ----V */ -#define NV_PMC_BOOT_0_FOUNDRY_TSMC 0x00000002 /* C---V */ -#define NV_PMC_INTR_0 0x00000100 /* RW-4R */ -#define NV_PMC_INTR_0_PMEDIA 4:4 /* R--VF */ -#define NV_PMC_INTR_0_PMEDIA_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PMC_INTR_0_PMEDIA_PENDING 0x00000001 /* R---V */ -#define NV_PMC_INTR_0_PFIFO 8:8 /* R--VF */ -#define NV_PMC_INTR_0_PFIFO_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PMC_INTR_0_PFIFO_PENDING 0x00000001 /* R---V */ -#define NV_PMC_INTR_0_PGRAPH 12:12 /* R--VF */ -#define NV_PMC_INTR_0_PGRAPH_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PMC_INTR_0_PGRAPH_PENDING 0x00000001 /* R---V */ -#define NV_PMC_INTR_0_PVIDEO 16:16 /* R--VF */ -#define NV_PMC_INTR_0_PVIDEO_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PMC_INTR_0_PVIDEO_PENDING 0x00000001 /* R---V */ -#define NV_PMC_INTR_0_PTIMER 20:20 /* R--VF */ -#define NV_PMC_INTR_0_PTIMER_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PMC_INTR_0_PTIMER_PENDING 0x00000001 /* R---V */ -#define NV_PMC_INTR_0_PCRTC 24:24 /* R--VF */ -#define NV_PMC_INTR_0_PCRTC_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PMC_INTR_0_PCRTC_PENDING 0x00000001 /* R---V */ -#define NV_PMC_INTR_0_PBUS 28:28 /* R--VF */ -#define NV_PMC_INTR_0_PBUS_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PMC_INTR_0_PBUS_PENDING 0x00000001 /* R---V */ -#define NV_PMC_INTR_0_SOFTWARE 31:31 /* RWIVF */ -#define NV_PMC_INTR_0_SOFTWARE_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PMC_INTR_0_SOFTWARE_PENDING 0x00000001 /* RW--V */ -#define NV_PMC_INTR_EN_0 0x00000140 /* RW-4R */ -#define NV_PMC_INTR_EN_0_INTA 1:0 /* RWIVF */ -#define NV_PMC_INTR_EN_0_INTA_DISABLED 0x00000000 /* RWI-V */ -#define NV_PMC_INTR_EN_0_INTA_HARDWARE 0x00000001 /* RW--V */ -#define NV_PMC_INTR_EN_0_INTA_SOFTWARE 0x00000002 /* RW--V */ -#define NV_PMC_INTR_READ_0 0x00000160 /* R--4R */ -#define NV_PMC_INTR_READ_0_INTA 0:0 /* R--VF */ -#define NV_PMC_INTR_READ_0_INTA_LOW 0x00000000 /* R---V */ -#define NV_PMC_INTR_READ_0_INTA_HIGH 0x00000001 /* R---V */ -#define NV_PMC_ENABLE 0x00000200 /* RW-4R */ -#define NV_PMC_ENABLE_PMEDIA 4:4 /* RWIVF */ -#define NV_PMC_ENABLE_PMEDIA_DISABLED 0x00000000 /* RWI-V */ -#define NV_PMC_ENABLE_PMEDIA_ENABLED 0x00000001 /* RW--V */ -#define NV_PMC_ENABLE_PFIFO 8:8 /* RWIVF */ -#define NV_PMC_ENABLE_PFIFO_DISABLED 0x00000000 /* RWI-V */ -#define NV_PMC_ENABLE_PFIFO_ENABLED 0x00000001 /* RW--V */ -#define NV_PMC_ENABLE_PGRAPH 12:12 /* RWIVF */ -#define NV_PMC_ENABLE_PGRAPH_DISABLED 0x00000000 /* RWI-V */ -#define NV_PMC_ENABLE_PGRAPH_ENABLED 0x00000001 /* RW--V */ -#define NV_PMC_ENABLE_PPMI 16:16 /* RWIVF */ -#define NV_PMC_ENABLE_PPMI_DISABLED 0x00000000 /* RWI-V */ -#define NV_PMC_ENABLE_PPMI_ENABLED 0x00000001 /* RW--V */ -#define NV_PMC_ENABLE_PFB 20:20 /* RWIVF */ -#define NV_PMC_ENABLE_PFB_DISABLED 0x00000000 /* RW--V */ -#define NV_PMC_ENABLE_PFB_ENABLED 0x00000001 /* RWI-V */ -#define NV_PMC_ENABLE_PCRTC 24:24 /* RWIVF */ -#define NV_PMC_ENABLE_PCRTC_DISABLED 0x00000000 /* RW--V */ -#define NV_PMC_ENABLE_PCRTC_ENABLED 0x00000001 /* RWI-V */ -#define NV_PMC_ENABLE_PVIDEO 28:28 /* RWIVF */ -#define NV_PMC_ENABLE_PVIDEO_DISABLED 0x00000000 /* RWI-V */ -#define NV_PMC_ENABLE_PVIDEO_ENABLED 0x00000001 /* RW--V */ - -/* dev_timer.ref */ -#define NV_PTIMER 0x00009FFF:0x00009000 /* RW--D */ -#define NV_PTIMER_INTR_0 0x00009100 /* RW-4R */ -#define NV_PTIMER_INTR_0_ALARM 0:0 /* RWXVF */ -#define NV_PTIMER_INTR_0_ALARM_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PTIMER_INTR_0_ALARM_PENDING 0x00000001 /* R---V */ -#define NV_PTIMER_INTR_0_ALARM_RESET 0x00000001 /* -W--V */ -#define NV_PTIMER_INTR_EN_0 0x00009140 /* RW-4R */ -#define NV_PTIMER_INTR_EN_0_ALARM 0:0 /* RWIVF */ -#define NV_PTIMER_INTR_EN_0_ALARM_DISABLED 0x00000000 /* RWI-V */ -#define NV_PTIMER_INTR_EN_0_ALARM_ENABLED 0x00000001 /* RW--V */ -#define NV_PTIMER_NUMERATOR 0x00009200 /* RW-4R */ -#define NV_PTIMER_NUMERATOR_VALUE 15:0 /* RWIUF */ -#define NV_PTIMER_NUMERATOR_VALUE_0 0x00000000 /* RWI-V */ -#define NV_PTIMER_DENOMINATOR 0x00009210 /* RW-4R */ -#define NV_PTIMER_DENOMINATOR_VALUE 15:0 /* RWIUF */ -#define NV_PTIMER_DENOMINATOR_VALUE_0 0x00000000 /* RWI-V */ -#define NV_PTIMER_TIME_0 0x00009400 /* RW-4R */ -#define NV_PTIMER_TIME_0_NSEC 31:5 /* RWXUF */ -#define NV_PTIMER_TIME_1 0x00009410 /* RW-4R */ -#define NV_PTIMER_TIME_1_NSEC 28:0 /* RWXUF */ -#define NV_PTIMER_ALARM_0 0x00009420 /* RW-4R */ -#define NV_PTIMER_ALARM_0_NSEC 31:5 /* RWXUF */ - -/* dev_fifo.ref */ -#define NV_PFIFO 0x00003FFF:0x00002000 /* RW--D */ -#define NV_PFIFO_DELAY_0 0x00002040 /* RW-4R */ -#define NV_PFIFO_DELAY_0_WAIT_RETRY 9:0 /* RWIUF */ -#define NV_PFIFO_DELAY_0_WAIT_RETRY_0 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_TIMESLICE 0x00002044 /* RW-4R */ -#define NV_PFIFO_DMA_TIMESLICE_SELECT 16:0 /* RWIUF */ -#define NV_PFIFO_DMA_TIMESLICE_SELECT_1 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_TIMESLICE_SELECT_16K 0x00003fff /* RW--V */ -#define NV_PFIFO_DMA_TIMESLICE_SELECT_32K 0x00007fff /* RW--V */ -#define NV_PFIFO_DMA_TIMESLICE_SELECT_64K 0x0000ffff /* RW--V */ -#define NV_PFIFO_DMA_TIMESLICE_SELECT_128K 0x0001ffff /* RW--V */ -#define NV_PFIFO_DMA_TIMESLICE_TIMEOUT 24:24 /* RWIUF */ -#define NV_PFIFO_DMA_TIMESLICE_TIMEOUT_DISABLED 0x00000000 /* RW--V */ -#define NV_PFIFO_DMA_TIMESLICE_TIMEOUT_ENABLED 0x00000001 /* RWI-V */ -#define NV_PFIFO_PIO_TIMESLICE 0x00002048 /* RW-4R */ -#define NV_PFIFO_PIO_TIMESLICE_SELECT 16:0 /* RWIUF */ -#define NV_PFIFO_PIO_TIMESLICE_SELECT_1 0x00000000 /* RWI-V */ -#define NV_PFIFO_PIO_TIMESLICE_SELECT_16K 0x00003fff /* RW--V */ -#define NV_PFIFO_PIO_TIMESLICE_SELECT_32K 0x00007fff /* RW--V */ -#define NV_PFIFO_PIO_TIMESLICE_SELECT_64K 0x0000ffff /* RW--V */ -#define NV_PFIFO_PIO_TIMESLICE_SELECT_128K 0x0001ffff /* RW--V */ -#define NV_PFIFO_PIO_TIMESLICE_TIMEOUT 24:24 /* RWIUF */ -#define NV_PFIFO_PIO_TIMESLICE_TIMEOUT_DISABLED 0x00000000 /* RW--V */ -#define NV_PFIFO_PIO_TIMESLICE_TIMEOUT_ENABLED 0x00000001 /* RWI-V */ -#define NV_PFIFO_TIMESLICE 0x0000204C /* RW-4R */ -#define NV_PFIFO_TIMESLICE_TIMER 17:0 /* RWIUF */ -#define NV_PFIFO_TIMESLICE_TIMER_EXPIRED 0x0003FFFF /* RWI-V */ -#define NV_PFIFO_NEXT_CHANNEL 0x00002050 /* RW-4R */ -#define NV_PFIFO_NEXT_CHANNEL_CHID 3:0 /* RWXUF */ -#define NV_PFIFO_NEXT_CHANNEL_MODE 8:8 /* RWXVF */ -#define NV_PFIFO_NEXT_CHANNEL_MODE_PIO 0x00000000 /* RW--V */ -#define NV_PFIFO_NEXT_CHANNEL_MODE_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_NEXT_CHANNEL_SWITCH 12:12 /* RWIVF */ -#define NV_PFIFO_NEXT_CHANNEL_SWITCH_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_NEXT_CHANNEL_SWITCH_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DEBUG_0 0x00002080 /* R--4R */ -#define NV_PFIFO_DEBUG_0_CACHE_ERROR0 0:0 /* R-XVF */ -#define NV_PFIFO_DEBUG_0_CACHE_ERROR0_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PFIFO_DEBUG_0_CACHE_ERROR0_PENDING 0x00000001 /* R---V */ -#define NV_PFIFO_DEBUG_0_CACHE_ERROR1 4:4 /* R-XVF */ -#define NV_PFIFO_DEBUG_0_CACHE_ERROR1_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PFIFO_DEBUG_0_CACHE_ERROR1_PENDING 0x00000001 /* R---V */ -#define NV_PFIFO_INTR_0 0x00002100 /* RW-4R */ -#define NV_PFIFO_INTR_0_CACHE_ERROR 0:0 /* RWXVF */ -#define NV_PFIFO_INTR_0_CACHE_ERROR_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PFIFO_INTR_0_CACHE_ERROR_PENDING 0x00000001 /* R---V */ -#define NV_PFIFO_INTR_0_CACHE_ERROR_RESET 0x00000001 /* -W--V */ -#define NV_PFIFO_INTR_0_RUNOUT 4:4 /* RWXVF */ -#define NV_PFIFO_INTR_0_RUNOUT_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PFIFO_INTR_0_RUNOUT_PENDING 0x00000001 /* R---V */ -#define NV_PFIFO_INTR_0_RUNOUT_RESET 0x00000001 /* -W--V */ -#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW 8:8 /* RWXVF */ -#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW_PENDING 0x00000001 /* R---V */ -#define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW_RESET 0x00000001 /* -W--V */ -#define NV_PFIFO_INTR_0_DMA_PUSHER 12:12 /* RWXVF */ -#define NV_PFIFO_INTR_0_DMA_PUSHER_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PFIFO_INTR_0_DMA_PUSHER_PENDING 0x00000001 /* R---V */ -#define NV_PFIFO_INTR_0_DMA_PUSHER_RESET 0x00000001 /* -W--V */ -#define NV_PFIFO_INTR_0_DMA_PT 16:16 /* RWXVF */ -#define NV_PFIFO_INTR_0_DMA_PT_NOT_PENDING 0x00000000 /* R---V */ -#define NV_PFIFO_INTR_0_DMA_PT_PENDING 0x00000001 /* R---V */ -#define NV_PFIFO_INTR_0_DMA_PT_RESET 0x00000001 /* -W--V */ -#define NV_PFIFO_INTR_EN_0 0x00002140 /* RW-4R */ -#define NV_PFIFO_INTR_EN_0_CACHE_ERROR 0:0 /* RWIVF */ -#define NV_PFIFO_INTR_EN_0_CACHE_ERROR_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_INTR_EN_0_CACHE_ERROR_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_INTR_EN_0_RUNOUT 4:4 /* RWIVF */ -#define NV_PFIFO_INTR_EN_0_RUNOUT_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_INTR_EN_0_RUNOUT_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW 8:8 /* RWIVF */ -#define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_INTR_EN_0_DMA_PUSHER 12:12 /* RWIVF */ -#define NV_PFIFO_INTR_EN_0_DMA_PUSHER_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_INTR_EN_0_DMA_PUSHER_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_INTR_EN_0_DMA_PT 16:16 /* RWIVF */ -#define NV_PFIFO_INTR_EN_0_DMA_PT_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_INTR_EN_0_DMA_PT_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_RAMHT 0x00002210 /* RW-4R */ -#define NV_PFIFO_RAMHT_BASE_ADDRESS 8:4 /* RWIUF */ -#define NV_PFIFO_RAMHT_BASE_ADDRESS_10000 0x00000010 /* RWI-V */ -#define NV_PFIFO_RAMHT_SIZE 17:16 /* RWIUF */ -#define NV_PFIFO_RAMHT_SIZE_4K 0x00000000 /* RWI-V */ -#define NV_PFIFO_RAMHT_SIZE_8K 0x00000001 /* RW--V */ -#define NV_PFIFO_RAMHT_SIZE_16K 0x00000002 /* RW--V */ -#define NV_PFIFO_RAMHT_SIZE_32K 0x00000003 /* RW--V */ -#define NV_PFIFO_RAMHT_SEARCH 25:24 /* RWIUF */ -#define NV_PFIFO_RAMHT_SEARCH_16 0x00000000 /* RWI-V */ -#define NV_PFIFO_RAMHT_SEARCH_32 0x00000001 /* RW--V */ -#define NV_PFIFO_RAMHT_SEARCH_64 0x00000002 /* RW--V */ -#define NV_PFIFO_RAMHT_SEARCH_128 0x00000003 /* RW--V */ -#define NV_PFIFO_RAMFC 0x00002214 /* RW-4R */ -#define NV_PFIFO_RAMFC_BASE_ADDRESS 8:1 /* RWIUF */ -#define NV_PFIFO_RAMFC_BASE_ADDRESS_11000 0x00000088 /* RWI-V */ -#define NV_PFIFO_RAMRO 0x00002218 /* RW-4R */ -#define NV_PFIFO_RAMRO_BASE_ADDRESS 8:1 /* RWIUF */ -#define NV_PFIFO_RAMRO_BASE_ADDRESS_11200 0x00000089 /* RWI-V */ -#define NV_PFIFO_RAMRO_BASE_ADDRESS_12000 0x00000090 /* RW--V */ -#define NV_PFIFO_RAMRO_SIZE 16:16 /* RWIVF */ -#define NV_PFIFO_RAMRO_SIZE_512 0x00000000 /* RWI-V */ -#define NV_PFIFO_RAMRO_SIZE_8K 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHES 0x00002500 /* RW-4R */ -#define NV_PFIFO_CACHES_REASSIGN 0:0 /* RWIVF */ -#define NV_PFIFO_CACHES_REASSIGN_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHES_REASSIGN_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHES_DMA_SUSPEND 4:4 /* R--VF */ -#define NV_PFIFO_CACHES_DMA_SUSPEND_IDLE 0x00000000 /* R---V */ -#define NV_PFIFO_CACHES_DMA_SUSPEND_BUSY 0x00000001 /* R---V */ -#define NV_PFIFO_MODE 0x00002504 /* RW-4R */ -#define NV_PFIFO_MODE_CHANNEL_0 0:0 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_0_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_0_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_1 1:1 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_1_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_1_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_2 2:2 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_2_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_2_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_3 3:3 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_3_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_3_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_4 4:4 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_4_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_4_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_5 5:5 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_5_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_5_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_6 6:6 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_6_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_6_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_7 7:7 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_7_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_7_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_8 8:8 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_8_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_8_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_9 9:9 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_9_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_9_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_10 10:10 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_10_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_10_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_11 11:11 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_11_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_11_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_12 12:12 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_12_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_12_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_13 13:13 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_13_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_13_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_14 14:14 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_14_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_14_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_MODE_CHANNEL_15 15:15 /* RWIVF */ -#define NV_PFIFO_MODE_CHANNEL_15_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_MODE_CHANNEL_15_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA 0x00002508 /* RW-4R */ -#define NV_PFIFO_DMA_CHANNEL_0 0:0 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_0_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_0_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_1 1:1 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_1_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_1_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_2 2:2 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_2_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_2_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_3 3:3 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_3_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_3_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_4 4:4 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_4_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_4_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_5 5:5 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_5_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_5_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_6 6:6 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_6_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_6_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_7 7:7 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_7_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_7_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_8 8:8 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_8_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_8_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_9 9:9 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_9_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_9_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_10 10:10 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_10_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_10_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_11 11:11 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_11_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_11_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_12 12:12 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_12_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_12_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_13 13:13 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_13_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_13_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_14 14:14 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_14_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_14_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_DMA_CHANNEL_15 15:15 /* RWIVF */ -#define NV_PFIFO_DMA_CHANNEL_15_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PFIFO_DMA_CHANNEL_15_PENDING 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE 0x0000250C /* RW-4R */ -#define NV_PFIFO_SIZE_CHANNEL_0 0:0 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_0_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_0_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_1 1:1 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_1_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_1_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_2 2:2 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_2_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_2_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_3 3:3 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_3_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_3_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_4 4:4 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_4_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_4_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_5 5:5 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_5_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_5_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_6 6:6 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_6_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_6_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_7 7:7 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_7_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_7_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_8 8:8 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_8_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_8_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_9 9:9 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_9_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_9_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_10 10:10 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_10_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_10_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_11 11:11 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_11_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_11_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_12 12:12 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_12_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_12_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_13 13:13 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_13_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_13_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_14 14:14 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_14_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_14_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_SIZE_CHANNEL_15 15:15 /* RWIVF */ -#define NV_PFIFO_SIZE_CHANNEL_15_124_BYTES 0x00000000 /* RWI-V */ -#define NV_PFIFO_SIZE_CHANNEL_15_512_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_PUSH0 0x00003000 /* RW-4R */ -#define NV_PFIFO_CACHE0_PUSH0_ACCESS 0:0 /* RWIVF */ -#define NV_PFIFO_CACHE0_PUSH0_ACCESS_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE0_PUSH0_ACCESS_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_PUSH0 0x00003200 /* RW-4R */ -#define NV_PFIFO_CACHE1_PUSH0_ACCESS 0:0 /* RWIVF */ -#define NV_PFIFO_CACHE1_PUSH0_ACCESS_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE1_PUSH0_ACCESS_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_PUSH1 0x00003004 /* RW-4R */ -#define NV_PFIFO_CACHE0_PUSH1_CHID 3:0 /* RWXUF */ -#define NV_PFIFO_CACHE1_PUSH1 0x00003204 /* RW-4R */ -#define NV_PFIFO_CACHE1_PUSH1_CHID 3:0 /* RWXUF */ -#define NV_PFIFO_CACHE1_PUSH1_MODE 8:8 /* RWIVF */ -#define NV_PFIFO_CACHE1_PUSH1_MODE_PIO 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE1_PUSH1_MODE_DMA 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_PUSH 0x00003220 /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_PUSH_ACCESS 0:0 /* RWIVF */ -#define NV_PFIFO_CACHE1_DMA_PUSH_ACCESS_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE1_DMA_PUSH_ACCESS_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_PUSH_STATE 4:4 /* R--VF */ -#define NV_PFIFO_CACHE1_DMA_PUSH_STATE_IDLE 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE1_DMA_PUSH_STATE_BUSY 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE1_DMA_PUSH_BUFFER 8:8 /* R--VF */ -#define NV_PFIFO_CACHE1_DMA_PUSH_BUFFER_NOT_EMPTY 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE1_DMA_PUSH_BUFFER_EMPTY 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE1_DMA_PUSH_STATUS 12:12 /* RWIVF */ -#define NV_PFIFO_CACHE1_DMA_PUSH_STATUS_RUNNING 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE1_DMA_PUSH_STATUS_SUSPENDED 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH 0x00003224 /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG 7:3 /* RWIUF */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_16_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_24_BYTES 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_32_BYTES 0x00000003 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_40_BYTES 0x00000004 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_48_BYTES 0x00000005 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_56_BYTES 0x00000006 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_64_BYTES 0x00000007 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_72_BYTES 0x00000008 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_80_BYTES 0x00000009 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_88_BYTES 0x0000000A /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_96_BYTES 0x0000000B /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_104_BYTES 0x0000000C /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES 0x0000000D /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_120_BYTES 0x0000000E /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES 0x0000000F /* RWI-V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_136_BYTES 0x00000010 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_144_BYTES 0x00000011 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_152_BYTES 0x00000012 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_160_BYTES 0x00000013 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_168_BYTES 0x00000014 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_176_BYTES 0x00000015 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_184_BYTES 0x00000016 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_192_BYTES 0x00000017 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_200_BYTES 0x00000018 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_208_BYTES 0x00000019 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_216_BYTES 0x0000001A /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_224_BYTES 0x0000001B /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_232_BYTES 0x0000001C /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_240_BYTES 0x0000001D /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_248_BYTES 0x0000001E /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_256_BYTES 0x0000001F /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE 15:13 /* RWIUF */ -#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_32_BYTES 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_64_BYTES 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_96_BYTES 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES 0x00000003 /* RWI-V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_160_BYTES 0x00000004 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_192_BYTES 0x00000005 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_224_BYTES 0x00000006 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_256_BYTES 0x00000007 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS 19:16 /* RWIUF */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_0 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_1 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_2 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_3 0x00000003 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 0x00000004 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_5 0x00000005 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_6 0x00000006 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_7 0x00000007 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 0x00000008 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_9 0x00000009 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_10 0x0000000A /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_11 0x0000000B /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_12 0x0000000C /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_13 0x0000000D /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_14 0x0000000E /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15 0x0000000F /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_PUT 0x00003240 /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_PUT_OFFSET 28:2 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_GET 0x00003244 /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_GET_OFFSET 28:2 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_STATE 0x00003228 /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_STATE_METHOD 12:2 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_STATE_SUBCHANNEL 15:13 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT 28:18 /* RWIUF */ -#define NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT_0 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE1_DMA_STATE_ERROR 31:30 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_STATE_ERROR_NONE 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_STATE_ERROR_NON_CACHE 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_STATE_ERROR_RESERVED_CMD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_STATE_ERROR_PROTECTION 0x00000003 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_INSTANCE 0x0000322C /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_INSTANCE_ADDRESS 15:0 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_CTL 0x00003230 /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_CTL_ADJUST 11:2 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_TABLE 12:12 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_TABLE_NOT_PRESENT 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_TABLE_PRESENT 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_ENTRY 13:13 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_ENTRY_NOT_LINEAR 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_CTL_PAGE_ENTRY_LINEAR 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_CTL_TARGET_NODE 17:16 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_CTL_TARGET_NODE_PCI 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_CTL_TARGET_NODE_AGP 0x00000003 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_CTL_AT_INFO 31:31 /* RWIUF */ -#define NV_PFIFO_CACHE1_DMA_CTL_AT_INFO_INVALID 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_CTL_AT_INFO_VALID 0x00000001 /* RWI-V */ -#define NV_PFIFO_CACHE1_DMA_LIMIT 0x00003234 /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_LIMIT_OFFSET 28:2 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_TLB_TAG 0x00003238 /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_TLB_TAG_ADDRESS 28:12 /* RWXUF */ -#define NV_PFIFO_CACHE1_DMA_TLB_TAG_STATE 0:0 /* RWIUF */ -#define NV_PFIFO_CACHE1_DMA_TLB_TAG_STATE_INVALID 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE1_DMA_TLB_TAG_STATE_VALID 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_DMA_TLB_PTE 0x0000323C /* RW-4R */ -#define NV_PFIFO_CACHE1_DMA_TLB_PTE_FRAME_ADDRESS 31:12 /* RWXUF */ -#define NV_PFIFO_CACHE0_PULL0 0x00003050 /* RW-4R */ -#define NV_PFIFO_CACHE0_PULL0_ACCESS 0:0 /* RWIVF */ -#define NV_PFIFO_CACHE0_PULL0_ACCESS_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE0_PULL0_ACCESS_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_PULL0_HASH 4:4 /* R-XVF */ -#define NV_PFIFO_CACHE0_PULL0_HASH_SUCCEEDED 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE0_PULL0_HASH_FAILED 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE0_PULL0_DEVICE 8:8 /* R-XVF */ -#define NV_PFIFO_CACHE0_PULL0_DEVICE_HARDWARE 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE0_PULL0_DEVICE_SOFTWARE 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE0_PULL0_HASH_STATE 12:12 /* R-XVF */ -#define NV_PFIFO_CACHE0_PULL0_HASH_STATE_IDLE 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE0_PULL0_HASH_STATE_BUSY 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE1_PULL0 0x00003250 /* RW-4R */ -#define NV_PFIFO_CACHE1_PULL0_ACCESS 0:0 /* RWIVF */ -#define NV_PFIFO_CACHE1_PULL0_ACCESS_DISABLED 0x00000000 /* RWI-V */ -#define NV_PFIFO_CACHE1_PULL0_ACCESS_ENABLED 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_PULL0_HASH 4:4 /* R-XVF */ -#define NV_PFIFO_CACHE1_PULL0_HASH_SUCCEEDED 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE1_PULL0_HASH_FAILED 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE1_PULL0_DEVICE 8:8 /* R-XVF */ -#define NV_PFIFO_CACHE1_PULL0_DEVICE_HARDWARE 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE1_PULL0_DEVICE_SOFTWARE 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE1_PULL0_HASH_STATE 12:12 /* R-XVF */ -#define NV_PFIFO_CACHE1_PULL0_HASH_STATE_IDLE 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE1_PULL0_HASH_STATE_BUSY 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE0_PULL1 0x00003054 /* RW-4R */ -#define NV_PFIFO_CACHE0_PULL1_ENGINE 1:0 /* RWXUF */ -#define NV_PFIFO_CACHE0_PULL1_ENGINE_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE0_PULL1_ENGINE_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_PULL1_ENGINE_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_PULL1 0x00003254 /* RW-4R */ -#define NV_PFIFO_CACHE1_PULL1_ENGINE 1:0 /* RWXUF */ -#define NV_PFIFO_CACHE1_PULL1_ENGINE_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_PULL1_ENGINE_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_PULL1_ENGINE_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE0_HASH 0x00003058 /* RW-4R */ -#define NV_PFIFO_CACHE0_HASH_INSTANCE 15:0 /* RWXUF */ -#define NV_PFIFO_CACHE0_HASH_VALID 16:16 /* RWXVF */ -#define NV_PFIFO_CACHE1_HASH 0x00003258 /* RW-4R */ -#define NV_PFIFO_CACHE1_HASH_INSTANCE 15:0 /* RWXUF */ -#define NV_PFIFO_CACHE1_HASH_VALID 16:16 /* RWXVF */ -#define NV_PFIFO_CACHE0_STATUS 0x00003014 /* R--4R */ -#define NV_PFIFO_CACHE0_STATUS_LOW_MARK 4:4 /* R--VF */ -#define NV_PFIFO_CACHE0_STATUS_LOW_MARK_NOT_EMPTY 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE0_STATUS_LOW_MARK_EMPTY 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE0_STATUS_HIGH_MARK 8:8 /* R--VF */ -#define NV_PFIFO_CACHE0_STATUS_HIGH_MARK_NOT_FULL 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE0_STATUS_HIGH_MARK_FULL 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE1_STATUS 0x00003214 /* R--4R */ -#define NV_PFIFO_CACHE1_STATUS_LOW_MARK 4:4 /* R--VF */ -#define NV_PFIFO_CACHE1_STATUS_LOW_MARK_NOT_EMPTY 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE1_STATUS_LOW_MARK_EMPTY 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE1_STATUS_HIGH_MARK 8:8 /* R--VF */ -#define NV_PFIFO_CACHE1_STATUS_HIGH_MARK_NOT_FULL 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE1_STATUS_HIGH_MARK_FULL 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE1_STATUS1 0x00003218 /* R--4R */ -#define NV_PFIFO_CACHE1_STATUS1_RANOUT 0:0 /* R-XVF */ -#define NV_PFIFO_CACHE1_STATUS1_RANOUT_FALSE 0x00000000 /* R---V */ -#define NV_PFIFO_CACHE1_STATUS1_RANOUT_TRUE 0x00000001 /* R---V */ -#define NV_PFIFO_CACHE0_PUT 0x00003010 /* RW-4R */ -#define NV_PFIFO_CACHE0_PUT_ADDRESS 2:2 /* RWXUF */ -#define NV_PFIFO_CACHE1_PUT 0x00003210 /* RW-4R */ -#define NV_PFIFO_CACHE1_PUT_ADDRESS 9:2 /* RWXUF */ -#define NV_PFIFO_CACHE0_GET 0x00003070 /* RW-4R */ -#define NV_PFIFO_CACHE0_GET_ADDRESS 2:2 /* RWXUF */ -#define NV_PFIFO_CACHE1_GET 0x00003270 /* RW-4R */ -#define NV_PFIFO_CACHE1_GET_ADDRESS 9:2 /* RWXUF */ -#define NV_PFIFO_CACHE0_ENGINE 0x00003080 /* RW-4R */ -#define NV_PFIFO_CACHE0_ENGINE_0 1:0 /* RWXUF */ -#define NV_PFIFO_CACHE0_ENGINE_0_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_0_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_0_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_1 5:4 /* RWXUF */ -#define NV_PFIFO_CACHE0_ENGINE_1_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_1_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_1_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_2 9:8 /* RWXUF */ -#define NV_PFIFO_CACHE0_ENGINE_2_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_2_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_2_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_3 13:12 /* RWXUF */ -#define NV_PFIFO_CACHE0_ENGINE_3_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_3_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_3_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_4 17:16 /* RWXUF */ -#define NV_PFIFO_CACHE0_ENGINE_4_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_4_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_4_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_5 21:20 /* RWXUF */ -#define NV_PFIFO_CACHE0_ENGINE_5_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_5_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_5_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_6 25:24 /* RWXUF */ -#define NV_PFIFO_CACHE0_ENGINE_6_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_6_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_6_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_7 29:28 /* RWXUF */ -#define NV_PFIFO_CACHE0_ENGINE_7_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_7_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE0_ENGINE_7_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE 0x00003280 /* RW-4R */ -#define NV_PFIFO_CACHE1_ENGINE_0 1:0 /* RWXUF */ -#define NV_PFIFO_CACHE1_ENGINE_0_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_0_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_0_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_1 5:4 /* RWXUF */ -#define NV_PFIFO_CACHE1_ENGINE_1_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_1_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_1_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_2 9:8 /* RWXUF */ -#define NV_PFIFO_CACHE1_ENGINE_2_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_2_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_2_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_3 13:12 /* RWXUF */ -#define NV_PFIFO_CACHE1_ENGINE_3_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_3_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_3_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_4 17:16 /* RWXUF */ -#define NV_PFIFO_CACHE1_ENGINE_4_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_4_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_4_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_5 21:20 /* RWXUF */ -#define NV_PFIFO_CACHE1_ENGINE_5_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_5_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_5_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_6 25:24 /* RWXUF */ -#define NV_PFIFO_CACHE1_ENGINE_6_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_6_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_6_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_7 29:28 /* RWXUF */ -#define NV_PFIFO_CACHE1_ENGINE_7_SW 0x00000000 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_7_GRAPHICS 0x00000001 /* RW--V */ -#define NV_PFIFO_CACHE1_ENGINE_7_DVD 0x00000002 /* RW--V */ -#define NV_PFIFO_CACHE0_METHOD(i) (0x00003100+(i)*8) /* RW-4A */ -#define NV_PFIFO_CACHE0_METHOD__SIZE_1 1 /* */ -#define NV_PFIFO_CACHE0_METHOD_ADDRESS 12:2 /* RWXUF */ -#define NV_PFIFO_CACHE0_METHOD_SUBCHANNEL 15:13 /* RWXUF */ -#define NV_PFIFO_CACHE1_METHOD(i) (0x00003800+(i)*8) /* RW-4A */ -#define NV_PFIFO_CACHE1_METHOD__SIZE_1 128 /* */ -#define NV_PFIFO_CACHE1_METHOD_ADDRESS 12:2 /* RWXUF */ -#define NV_PFIFO_CACHE1_METHOD_SUBCHANNEL 15:13 /* RWXUF */ -#define NV_PFIFO_CACHE1_METHOD_ALIAS(i) (0x00003C00+(i)*8) /* RW-4A */ -#define NV_PFIFO_CACHE1_METHOD_ALIAS__SIZE_1 128 /* */ -#define NV_PFIFO_CACHE0_DATA(i) (0x00003104+(i)*8) /* RW-4A */ -#define NV_PFIFO_CACHE0_DATA__SIZE_1 1 /* */ -#define NV_PFIFO_CACHE0_DATA_VALUE 31:0 /* RWXVF */ -#define NV_PFIFO_CACHE1_DATA(i) (0x00003804+(i)*8) /* RW-4A */ -#define NV_PFIFO_CACHE1_DATA__SIZE_1 128 /* */ -#define NV_PFIFO_CACHE1_DATA_VALUE 31:0 /* RWXVF */ -#define NV_PFIFO_CACHE1_DATA_ALIAS(i) (0x00003C04+(i)*8) /* RW-4A */ -#define NV_PFIFO_CACHE1_DATA_ALIAS__SIZE_1 128 /* */ -#define NV_PFIFO_DEVICE(i) (0x00002800+(i)*4) /* R--4A */ -#define NV_PFIFO_DEVICE__SIZE_1 128 /* */ -#define NV_PFIFO_DEVICE_CHID 3:0 /* R--UF */ -#define NV_PFIFO_DEVICE_SWITCH 24:24 /* R--VF */ -#define NV_PFIFO_DEVICE_SWITCH_UNAVAILABLE 0x00000000 /* R---V */ -#define NV_PFIFO_DEVICE_SWITCH_AVAILABLE 0x00000001 /* R---V */ -#define NV_PFIFO_RUNOUT_STATUS 0x00002400 /* R--4R */ -#define NV_PFIFO_RUNOUT_STATUS_RANOUT 0:0 /* R--VF */ -#define NV_PFIFO_RUNOUT_STATUS_RANOUT_FALSE 0x00000000 /* R---V */ -#define NV_PFIFO_RUNOUT_STATUS_RANOUT_TRUE 0x00000001 /* R---V */ -#define NV_PFIFO_RUNOUT_STATUS_LOW_MARK 4:4 /* R--VF */ -#define NV_PFIFO_RUNOUT_STATUS_LOW_MARK_NOT_EMPTY 0x00000000 /* R---V */ -#define NV_PFIFO_RUNOUT_STATUS_LOW_MARK_EMPTY 0x00000001 /* R---V */ -#define NV_PFIFO_RUNOUT_STATUS_HIGH_MARK 8:8 /* R--VF */ -#define NV_PFIFO_RUNOUT_STATUS_HIGH_MARK_NOT_FULL 0x00000000 /* R---V */ -#define NV_PFIFO_RUNOUT_STATUS_HIGH_MARK_FULL 0x00000001 /* R---V */ -#define NV_PFIFO_RUNOUT_PUT 0x00002410 /* RW-4R */ -#define NV_PFIFO_RUNOUT_PUT_ADDRESS 12:3 /* RWXUF */ -#define NV_PFIFO_RUNOUT_PUT_ADDRESS__SIZE_0 8:3 /* RWXUF */ -#define NV_PFIFO_RUNOUT_PUT_ADDRESS__SIZE_1 12:3 /* RWXUF */ -#define NV_PFIFO_RUNOUT_GET 0x00002420 /* RW-4R */ -#define NV_PFIFO_RUNOUT_GET_ADDRESS 13:3 /* RWXUF */ -/* dev_graphics.ref */ -#define NV_PGRAPH 0x00401FFF:0x00400000 /* RW--D */ -#define NV_PGRAPH_DEBUG_0 0x00400080 /* RW-4R */ -#define NV_PGRAPH_DEBUG_1 0x00400084 /* RW-4R */ -#define NV_PGRAPH_DEBUG_2 0x00400088 /* RW-4R */ -#define NV_PGRAPH_DEBUG_3 0x0040008C /* RW-4R */ -#define NV_PGRAPH_INTR 0x00400100 /* RW-4R */ -#define NV_PGRAPH_INTR_NOTIFY 0:0 /* RWIVF */ -#define NV_PGRAPH_INTR_NOTIFY_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_INTR_NOTIFY_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_INTR_NOTIFY_RESET 0x00000001 /* -W--C */ -#define NV_PGRAPH_INTR_MISSING_HW 4:4 /* RWIVF */ -#define NV_PGRAPH_INTR_MISSING_HW_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_INTR_MISSING_HW_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_INTR_MISSING_HW_RESET 0x00000001 /* -W--C */ -#define NV_PGRAPH_INTR_TLB_PRESENT_A 8:8 /* RWIVF */ -#define NV_PGRAPH_INTR_TLB_PRESENT_A_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_INTR_TLB_PRESENT_A_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_INTR_TLB_PRESENT_A_RESET 0x00000001 /* -W--C */ -#define NV_PGRAPH_INTR_TLB_PRESENT_B 9:9 /* RWIVF */ -#define NV_PGRAPH_INTR_TLB_PRESENT_B_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_INTR_TLB_PRESENT_B_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_INTR_TLB_PRESENT_B_RESET 0x00000001 /* -W--C */ -#define NV_PGRAPH_INTR_CONTEXT_SWITCH 12:12 /* RWIVF */ -#define NV_PGRAPH_INTR_CONTEXT_SWITCH_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_INTR_CONTEXT_SWITCH_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_INTR_CONTEXT_SWITCH_RESET 0x00000001 /* -W--C */ -#define NV_PGRAPH_INTR_BUFFER_NOTIFY 16:16 /* RWIVF */ -#define NV_PGRAPH_INTR_BUFFER_NOTIFY_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_INTR_BUFFER_NOTIFY_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_INTR_BUFFER_NOTIFY_RESET 0x00000001 /* -W--C */ -#define NV_PGRAPH_NSTATUS 0x00400104 /* RW-4R */ -#define NV_PGRAPH_NSTATUS_STATE_IN_USE 11:11 /* RWIVF */ -#define NV_PGRAPH_NSTATUS_STATE_IN_USE_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PGRAPH_NSTATUS_STATE_IN_USE_PENDING 0x00000001 /* RW--V */ -#define NV_PGRAPH_NSTATUS_INVALID_STATE 12:12 /* RWIVF */ -#define NV_PGRAPH_NSTATUS_INVALID_STATE_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PGRAPH_NSTATUS_INVALID_STATE_PENDING 0x00000001 /* RW--V */ -#define NV_PGRAPH_NSTATUS_BAD_ARGUMENT 13:13 /* RWIVF */ -#define NV_PGRAPH_NSTATUS_BAD_ARGUMENT_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PGRAPH_NSTATUS_BAD_ARGUMENT_PENDING 0x00000001 /* RW--V */ -#define NV_PGRAPH_NSTATUS_PROTECTION_FAULT 14:14 /* RWIVF */ -#define NV_PGRAPH_NSTATUS_PROTECTION_FAULT_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PGRAPH_NSTATUS_PROTECTION_FAULT_PENDING 0x00000001 /* RW--V */ -#define NV_PGRAPH_NSOURCE 0x00400108 /* R--4R */ -#define NV_PGRAPH_NSOURCE_NOTIFICATION 0:0 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_NOTIFICATION_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_NOTIFICATION_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_DATA_ERROR 1:1 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_DATA_ERROR_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_DATA_ERROR_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_PROTECTION_ERROR 2:2 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_PROTECTION_ERROR_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_PROTECTION_ERROR_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_RANGE_EXCEPTION 3:3 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_RANGE_EXCEPTION_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_RANGE_EXCEPTION_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_LIMIT_COLOR 4:4 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_LIMIT_COLOR_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_LIMIT_COLOR_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_LIMIT_ZETA_ 5:5 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_LIMIT_ZETA_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_LIMIT_ZETA_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_ILLEGAL_MTHD 6:6 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_ILLEGAL_MTHD_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_ILLEGAL_MTHD_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_DMA_R_PROTECTION 7:7 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_DMA_R_PROTECTION_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_DMA_R_PROTECTION_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_DMA_W_PROTECTION 8:8 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_DMA_W_PROTECTION_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_DMA_W_PROTECTION_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_FORMAT_EXCEPTION 9:9 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_FORMAT_EXCEPTION_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_FORMAT_EXCEPTION_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_PATCH_EXCEPTION 10:10 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_PATCH_EXCEPTION_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_PATCH_EXCEPTION_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_STATE_INVALID 11:11 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_STATE_INVALID_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_STATE_INVALID_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_DOUBLE_NOTIFY 12:12 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_DOUBLE_NOTIFY_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_DOUBLE_NOTIFY_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_NOTIFY_IN_USE 13:13 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_NOTIFY_IN_USE_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_NOTIFY_IN_USE_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_METHOD_CNT 14:14 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_METHOD_CNT_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_METHOD_CNT_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_NSOURCE_BFR_NOTIFICATION 15:15 /* R-IVF */ -#define NV_PGRAPH_NSOURCE_BFR_NOTIFICATION_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_NSOURCE_BFR_NOTIFICATION_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_INTR_EN 0x00400140 /* RW-4R */ -#define NV_PGRAPH_INTR_EN_NOTIFY 0:0 /* RWIVF */ -#define NV_PGRAPH_INTR_EN_NOTIFY_DISABLED 0x00000000 /* RWI-V */ -#define NV_PGRAPH_INTR_EN_NOTIFY_ENABLED 0x00000001 /* RW--V */ -#define NV_PGRAPH_INTR_EN_MISSING_HW 4:4 /* RWIVF */ -#define NV_PGRAPH_INTR_EN_MISSING_HW_DISABLED 0x00000000 /* RWI-V */ -#define NV_PGRAPH_INTR_EN_MISSING_HW_ENABLED 0x00000001 /* RW--V */ -#define NV_PGRAPH_INTR_EN_TLB_PRESENT_A 8:8 /* RWIVF */ -#define NV_PGRAPH_INTR_EN_TLB_PRESENT_A_DISABLED 0x00000000 /* RWI-V */ -#define NV_PGRAPH_INTR_EN_TLB_PRESENT_A_ENABLED 0x00000001 /* RW--V */ -#define NV_PGRAPH_INTR_EN_TLB_PRESENT_B 9:9 /* RWIVF */ -#define NV_PGRAPH_INTR_EN_TLB_PRESENT_B_DISABLED 0x00000000 /* RWI-V */ -#define NV_PGRAPH_INTR_EN_TLB_PRESENT_B_ENABLED 0x00000001 /* RW--V */ -#define NV_PGRAPH_INTR_EN_CONTEXT_SWITCH 12:12 /* RWIVF */ -#define NV_PGRAPH_INTR_EN_CONTEXT_SWITCH_DISABLED 0x00000000 /* RWI-V */ -#define NV_PGRAPH_INTR_EN_CONTEXT_SWITCH_ENABLED 0x00000001 /* RW--V */ -#define NV_PGRAPH_INTR_EN_BUFFER_NOTIFY 16:16 /* RWIVF */ -#define NV_PGRAPH_INTR_EN_BUFFER_NOTIFY_DISABLED 0x00000000 /* RWI-V */ -#define NV_PGRAPH_INTR_EN_BUFFER_NOTIFY_ENABLED 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1 0x00400160 /* RW-4R */ -#define NV_PGRAPH_CTX_SWITCH1_GRCLASS 7:0 /* RWXVF */ -#define NV_PGRAPH_CTX_SWITCH1_CHROMA_KEY 12:12 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH1_CHROMA_KEY_DISABLE 0x00000000 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_CHROMA_KEY_ENABLE 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_USER_CLIP 13:13 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH1_USER_CLIP_DISABLE 0x00000000 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_USER_CLIP_ENABLE 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_SWIZZLE 14:14 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH1_SWIZZLE_DISABLE 0x00000000 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_SWIZZLE_ENABLE 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG 17:15 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_SRCCOPY_AND 0x00000000 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_ROP_AND 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_BLEND_AND 0x00000002 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_SRCCOPY 0x00000003 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_SRCCOPY_PRE 0x00000004 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG_BLEND_PRE 0x00000005 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_STATUS 24:24 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_STATUS_INVALID 0x00000000 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_PATCH_STATUS_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_CONTEXT_SURFACE 25:25 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH1_CONTEXT_SURFACE_INVALID 0x00000000 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_CONTEXT_SURFACE_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH1_VOLATILE_RESET 31:31 /* CWIVF */ -#define NV_PGRAPH_CTX_SWITCH1_VOLATILE_RESET_IGNORE 0x00000000 /* CWI-V */ -#define NV_PGRAPH_CTX_SWITCH1_VOLATILE_RESET_ENABLED 0x00000001 /* -W--T */ -#define NV_PGRAPH_CTX_SWITCH2 0x00400164 /* RW-4R */ -#define NV_PGRAPH_CTX_SWITCH2_MONO_FORMAT 1:0 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH2_MONO_FORMAT_INVALID 0x00 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_MONO_FORMAT_CGA6_M1 0x01 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_MONO_FORMAT_LE_M1 0x02 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT 13:8 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_INVALID 0x00 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_Y8 0x01 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X16A8Y8 0x02 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X24Y8 0x03 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_A1R5G5B5 0x06 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X1R5G5B5 0x07 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X16A1R5G5B5 0x08 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X17R5G5B5 0x09 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_R5G6B5 0x0A /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_A16R5G6B5 0x0B /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X16R5G6B5 0x0C /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_A8R8G8B8 0x0D /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X8R8G8B8 0x0E /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_Y16 0x0F /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_A16Y16 0x10 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_X16Y16 0x11 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_V8YB8U8YA8 0x12 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_YB8V8YA8U8 0x13 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_COLOR_FORMAT_LE_Y32 0x14 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH2_NOTIFY_INSTANCE 31:16 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH2_NOTIFY_INSTANCE_INVALID 0x0000 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH3 0x00400168 /* RW-4R */ -#define NV_PGRAPH_CTX_SWITCH3_DMA_INSTANCE_0 15:0 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH3_DMA_INSTANCE_0_INVALID 0x0000 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH3_DMA_INSTANCE_1 31:16 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH3_DMA_INSTANCE_1_INVALID 0x0000 /* RW--V */ -#define NV_PGRAPH_CTX_SWITCH4 0x0040016C /* RW-4R */ -#define NV_PGRAPH_CTX_SWITCH4_USER_INSTANCE 15:0 /* RWXUF */ -#define NV_PGRAPH_CTX_SWITCH4_USER_INSTANCE_INVALID 0x0000 /* RW--V */ -#define NV_PGRAPH_CTX_CACHE1(i) (0x00400180+(i)*4) /* RW-4A */ -#define NV_PGRAPH_CTX_CACHE1__SIZE_1 8 /* */ -#define NV_PGRAPH_CTX_CACHE1_GRCLASS 7:0 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE1_CHROMA_KEY 12:12 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE1_USER_CLIP 13:13 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE1_SWIZZLE 14:14 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE1_PATCH_CONFIG 19:15 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE1_SPARE1 20:20 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE1_PATCH_STATUS 24:24 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE1_CONTEXT_SURFACE 25:25 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE2(i) (0x004001a0+(i)*4) /* RW-4A */ -#define NV_PGRAPH_CTX_CACHE2__SIZE_1 8 /* */ -#define NV_PGRAPH_CTX_CACHE2_MONO_FORMAT 1:0 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE2_COLOR_FORMAT 13:8 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE2_NOTIFY_INSTANCE 31:16 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE3(i) (0x004001c0+(i)*4) /* RW-4A */ -#define NV_PGRAPH_CTX_CACHE3__SIZE_1 8 /* */ -#define NV_PGRAPH_CTX_CACHE3_DMA_INSTANCE_0 15:0 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE3_DMA_INSTANCE_1 31:16 /* RWXVF */ -#define NV_PGRAPH_CTX_CACHE4(i) (0x004001e0+(i)*4) /* RW-4A */ -#define NV_PGRAPH_CTX_CACHE4__SIZE_1 8 /* */ -#define NV_PGRAPH_CTX_CACHE4_USER_INSTANCE 15:0 /* RWXVF */ -#define NV_PGRAPH_CTX_CONTROL 0x00400170 /* RW-4R */ -#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME 1:0 /* RWIVF */ -#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_33US 0x00000000 /* RWI-V */ -#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_262US 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_2MS 0x00000002 /* RW--V */ -#define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME_17MS 0x00000003 /* RW--V */ -#define NV_PGRAPH_CTX_CONTROL_TIME 8:8 /* RWIVF */ -#define NV_PGRAPH_CTX_CONTROL_TIME_EXPIRED 0x00000000 /* RWI-V */ -#define NV_PGRAPH_CTX_CONTROL_TIME_NOT_EXPIRED 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_CONTROL_CHID 16:16 /* RWIVF */ -#define NV_PGRAPH_CTX_CONTROL_CHID_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_CTX_CONTROL_CHID_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_CONTROL_CHANGE 20:20 /* R--VF */ -#define NV_PGRAPH_CTX_CONTROL_CHANGE_UNAVAILABLE 0x00000000 /* R---V */ -#define NV_PGRAPH_CTX_CONTROL_CHANGE_AVAILABLE 0x00000001 /* R---V */ -#define NV_PGRAPH_CTX_CONTROL_SWITCHING 24:24 /* RWIVF */ -#define NV_PGRAPH_CTX_CONTROL_SWITCHING_IDLE 0x00000000 /* RWI-V */ -#define NV_PGRAPH_CTX_CONTROL_SWITCHING_BUSY 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_CONTROL_DEVICE 28:28 /* RWIVF */ -#define NV_PGRAPH_CTX_CONTROL_DEVICE_DISABLED 0x00000000 /* RWI-V */ -#define NV_PGRAPH_CTX_CONTROL_DEVICE_ENABLED 0x00000001 /* RW--V */ -#define NV_PGRAPH_CTX_USER 0x00400174 /* RW-4R */ -#define NV_PGRAPH_CTX_USER_SUBCH 15:13 /* RWIVF */ -#define NV_PGRAPH_CTX_USER_SUBCH_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_CTX_USER_CHID 27:24 /* RWIVF */ -#define NV_PGRAPH_CTX_USER_CHID_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_FIFO 0x00400720 /* RW-4R */ -#define NV_PGRAPH_FIFO_ACCESS 0:0 /* RWIVF */ -#define NV_PGRAPH_FIFO_ACCESS_DISABLED 0x00000000 /* RW--V */ -#define NV_PGRAPH_FIFO_ACCESS_ENABLED 0x00000001 /* RWI-V */ -#define NV_PGRAPH_FFINTFC_FIFO_0(i) (0x00400730+(i)*4) /* RW-4A */ -#define NV_PGRAPH_FFINTFC_FIFO_0__SIZE_1 4 /* */ -#define NV_PGRAPH_FFINTFC_FIFO_0_TAG 0:0 /* RWXVF */ -#define NV_PGRAPH_FFINTFC_FIFO_0_TAG_MTHD 0x00000000 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_TAG_CHSW 0x00000001 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH 3:1 /* RWXVF */ -#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_0 0x00000000 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_1 0x00000001 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_2 0x00000002 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_3 0x00000003 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_4 0x00000004 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_5 0x00000005 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_6 0x00000006 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_SUBCH_7 0x00000007 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_0_MTHD 14:4 /* RWXVF */ -#define NV_PGRAPH_FFINTFC_FIFO_0_MTHD_CTX_SWITCH 0x00000000 /* RW--V */ -#define NV_PGRAPH_FFINTFC_FIFO_1(i) (0x00400740+(i)*4) /* RW-4A */ -#define NV_PGRAPH_FFINTFC_FIFO_1__SIZE_1 4 /* */ -#define NV_PGRAPH_FFINTFC_FIFO_1_ARGUMENT 31:0 /* RWXVF */ -#define NV_PGRAPH_FFINTFC_FIFO_PTR 0x00400750 /* RW-4R */ -#define NV_PGRAPH_FFINTFC_FIFO_PTR_WRITE 2:0 /* RWIVF */ -#define NV_PGRAPH_FFINTFC_FIFO_PTR_WRITE_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_FFINTFC_FIFO_PTR_READ 6:4 /* RWIVF */ -#define NV_PGRAPH_FFINTFC_FIFO_PTR_READ_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_FFINTFC_ST2 0x00400754 /* RW-4R */ -#define NV_PGRAPH_FFINTFC_ST2_STATUS 0:0 /* RWIVF */ -#define NV_PGRAPH_FFINTFC_ST2_STATUS_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_FFINTFC_ST2_STATUS_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_MTHD 11:1 /* RWIVF */ -#define NV_PGRAPH_FFINTFC_ST2_MTHD_CTX_SWITCH 0x00000000 /* RWI-V */ -#define NV_PGRAPH_FFINTFC_ST2_SUBCH 14:12 /* RWIVF */ -#define NV_PGRAPH_FFINTFC_ST2_SUBCH_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_FFINTFC_ST2_SUBCH_1 0x00000001 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_SUBCH_2 0x00000002 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_SUBCH_3 0x00000003 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_SUBCH_4 0x00000004 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_SUBCH_5 0x00000005 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_SUBCH_6 0x00000006 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_SUBCH_7 0x00000007 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID 18:15 /* RWIVF */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_1 0x00000001 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_2 0x00000002 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_3 0x00000003 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_4 0x00000004 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_5 0x00000005 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_6 0x00000006 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_7 0x00000007 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_8 0x00000008 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_9 0x00000009 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_10 0x0000000A /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_11 0x0000000B /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_12 0x0000000C /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_13 0x0000000D /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_14 0x0000000E /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_15 0x0000000F /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_STATUS 19:19 /* RWIVF */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_STATUS_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_FFINTFC_ST2_CHID_STATUS_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_FFINTFC_ST2_D 0x00400758 /* RW-4R */ -#define NV_PGRAPH_FFINTFC_ST2_D_ARGUMENT 31:0 /* RWIVF */ -#define NV_PGRAPH_FFINTFC_ST2_D_ARGUMENT_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATUS 0x00400700 /* R--4R */ -#define NV_PGRAPH_STATUS_STATE 0:0 /* R-IVF */ -#define NV_PGRAPH_STATUS_STATE_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_STATE_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_XY_LOGIC 4:4 /* R-IVF */ -#define NV_PGRAPH_STATUS_XY_LOGIC_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_XY_LOGIC_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_FE 5:5 /* R-IVF */ -#define NV_PGRAPH_STATUS_FE_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_FE_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_RASTERIZER 6:6 /* R-IVF */ -#define NV_PGRAPH_STATUS_RASTERIZER_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_RASTERIZER_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_PORT_NOTIFY 8:8 /* R-IVF */ -#define NV_PGRAPH_STATUS_PORT_NOTIFY_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_PORT_NOTIFY_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_PORT_REGISTER 12:12 /* R-IVF */ -#define NV_PGRAPH_STATUS_PORT_REGISTER_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_PORT_REGISTER_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_PORT_DMA 16:16 /* R-IVF */ -#define NV_PGRAPH_STATUS_PORT_DMA_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_PORT_DMA_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_DMA_ENGINE 17:17 /* R-IVF */ -#define NV_PGRAPH_STATUS_DMA_ENGINE_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_DMA_ENGINE_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_DMA_NOTIFY 20:20 /* R-IVF */ -#define NV_PGRAPH_STATUS_DMA_NOTIFY_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_DMA_NOTIFY_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_DMA_BUFFER_NOTIFY 21:21 /* R-IVF */ -#define NV_PGRAPH_STATUS_DMA_BUFFER_NOTIFY_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_DMA_BUFFER_NOTIFY_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_D3D 24:24 /* R-IVF */ -#define NV_PGRAPH_STATUS_D3D_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_D3D_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_CACHE 25:25 /* R-IVF */ -#define NV_PGRAPH_STATUS_CACHE_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_CACHE_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_LIGHTING 26:26 /* R-IVF */ -#define NV_PGRAPH_STATUS_LIGHTING_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_LIGHTING_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_PREROP 27:27 /* R-IVF */ -#define NV_PGRAPH_STATUS_PREROP_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_PREROP_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_ROP 28:28 /* R-IVF */ -#define NV_PGRAPH_STATUS_ROP_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_ROP_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_STATUS_PORT_USER 29:29 /* R-IVF */ -#define NV_PGRAPH_STATUS_PORT_USER_IDLE 0x00000000 /* R-I-V */ -#define NV_PGRAPH_STATUS_PORT_USER_BUSY 0x00000001 /* R---V */ -#define NV_PGRAPH_TRAPPED_ADDR 0x00400704 /* R--4R */ -#define NV_PGRAPH_TRAPPED_ADDR_MTHD 12:2 /* R-XUF */ -#define NV_PGRAPH_TRAPPED_ADDR_SUBCH 15:13 /* R-XUF */ -#define NV_PGRAPH_TRAPPED_ADDR_CHID 27:24 /* R-XUF */ -#define NV_PGRAPH_TRAPPED_DATA 0x00400708 /* R--4R */ -#define NV_PGRAPH_TRAPPED_DATA_VALUE 31:0 /* R-XVF */ -#define NV_PGRAPH_SURFACE 0x0040070C /* RW-4R */ -#define NV_PGRAPH_SURFACE_TYPE 1:0 /* RWIVF */ -#define NV_PGRAPH_SURFACE_TYPE_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_SURFACE_TYPE_NON_SWIZZLE 0x00000001 /* RW--V */ -#define NV_PGRAPH_SURFACE_TYPE_SWIZZLE 0x00000002 /* RW--V */ -#define NV_PGRAPH_NOTIFY 0x00400714 /* RW-4R */ -#define NV_PGRAPH_NOTIFY_BUFFER_REQ 0:0 /* RWIVF */ -#define NV_PGRAPH_NOTIFY_BUFFER_REQ_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PGRAPH_NOTIFY_BUFFER_REQ_PENDING 0x00000001 /* RW--V */ -#define NV_PGRAPH_NOTIFY_BUFFER_STYLE 8:8 /* RWIVF */ -#define NV_PGRAPH_NOTIFY_BUFFER_STYLE_WRITE_ONLY 0x00000000 /* RWI-V */ -#define NV_PGRAPH_NOTIFY_BUFFER_STYLE_WRITE_THEN_AWAKEN 0x00000001 /* RW--V */ -#define NV_PGRAPH_NOTIFY_REQ 16:16 /* RWIVF */ -#define NV_PGRAPH_NOTIFY_REQ_NOT_PENDING 0x00000000 /* RWI-V */ -#define NV_PGRAPH_NOTIFY_REQ_PENDING 0x00000001 /* RW--V */ -#define NV_PGRAPH_NOTIFY_STYLE 20:20 /* RWIVF */ -#define NV_PGRAPH_NOTIFY_STYLE_WRITE_ONLY 0x00000000 /* RWI-V */ -#define NV_PGRAPH_NOTIFY_STYLE_WRITE_THEN_AWAKEN 0x00000001 /* RW--V */ -#define NV_PGRAPH_BOFFSET(i) (0x00400640+(i)*4) /* RW-4A */ -#define NV_PGRAPH_BOFFSET__SIZE_1 6 /* */ -#define NV_PGRAPH_BOFFSET_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BOFFSET_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BOFFSET0 0x00400640 /* RW-4R */ -#define NV_PGRAPH_BOFFSET0__ALIAS_1 NV_PGRAPH_BOFFSET(0) /* */ -#define NV_PGRAPH_BOFFSET0_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BOFFSET0_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BOFFSET1 0x00400644 /* RW-4R */ -#define NV_PGRAPH_BOFFSET1__ALIAS_1 NV_PGRAPH_BOFFSET(1) /* */ -#define NV_PGRAPH_BOFFSET1_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BOFFSET1_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BOFFSET2 0x00400648 /* RW-4R */ -#define NV_PGRAPH_BOFFSET2__ALIAS_1 NV_PGRAPH_BOFFSET(2) /* */ -#define NV_PGRAPH_BOFFSET2_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BOFFSET2_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BOFFSET3 0x0040064C /* RW-4R */ -#define NV_PGRAPH_BOFFSET3__ALIAS_1 NV_PGRAPH_BOFFSET(3) /* */ -#define NV_PGRAPH_BOFFSET3_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BOFFSET3_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BOFFSET4 0x00400650 /* RW-4R */ -#define NV_PGRAPH_BOFFSET4__ALIAS_1 NV_PGRAPH_BOFFSET(4) /* */ -#define NV_PGRAPH_BOFFSET4_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BOFFSET4_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BOFFSET5 0x00400654 /* RW-4R */ -#define NV_PGRAPH_BOFFSET5__ALIAS_1 NV_PGRAPH_BOFFSET(5) /* */ -#define NV_PGRAPH_BOFFSET5_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BOFFSET5_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BBASE(i) (0x00400658+(i)*4) /* RW-4A */ -#define NV_PGRAPH_BBASE__SIZE_1 6 /* */ -#define NV_PGRAPH_BBASE_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BBASE_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BBASE0 0x00400658 /* RW-4R */ -#define NV_PGRAPH_BBASE0__ALIAS_1 NV_PGRAPH_BBASE(0) /* */ -#define NV_PGRAPH_BBASE0_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BBASE0_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BBASE1 0x0040065c /* RW-4R */ -#define NV_PGRAPH_BBASE1__ALIAS_1 NV_PGRAPH_BBASE(1) /* */ -#define NV_PGRAPH_BBASE1_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BBASE1_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BBASE2 0x00400660 /* RW-4R */ -#define NV_PGRAPH_BBASE2__ALIAS_1 NV_PGRAPH_BBASE(2) /* */ -#define NV_PGRAPH_BBASE2_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BBASE2_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BBASE3 0x00400664 /* RW-4R */ -#define NV_PGRAPH_BBASE3__ALIAS_1 NV_PGRAPH_BBASE(3) /* */ -#define NV_PGRAPH_BBASE3_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BBASE3_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BBASE4 0x00400668 /* RW-4R */ -#define NV_PGRAPH_BBASE4__ALIAS_1 NV_PGRAPH_BBASE(4) /* */ -#define NV_PGRAPH_BBASE4_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BBASE4_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BBASE5 0x0040066C /* RW-4R */ -#define NV_PGRAPH_BBASE5__ALIAS_1 NV_PGRAPH_BBASE(5) /* */ -#define NV_PGRAPH_BBASE5_LINADRS 23:0 /* RWIUF */ -#define NV_PGRAPH_BBASE5_LINADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPITCH(i) (0x00400670+(i)*4) /* RW-4A */ -#define NV_PGRAPH_BPITCH__SIZE_1 5 /* */ -#define NV_PGRAPH_BPITCH_VALUE 12:0 /* RWIUF */ -#define NV_PGRAPH_BPITCH_VALUE_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPITCH0 0x00400670 /* RW-4R */ -#define NV_PGRAPH_BPITCH0__ALIAS_1 NV_PGRAPH_BPITCH(0) /* */ -#define NV_PGRAPH_BPITCH0_VALUE 12:0 /* RWIUF */ -#define NV_PGRAPH_BPITCH0_VALUE_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPITCH1 0x00400674 /* RW-4R */ -#define NV_PGRAPH_BPITCH1__ALIAS_1 NV_PGRAPH_BPITCH(1) /* */ -#define NV_PGRAPH_BPITCH1_VALUE 12:0 /* RWIUF */ -#define NV_PGRAPH_BPITCH1_VALUE_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPITCH2 0x00400678 /* RW-4R */ -#define NV_PGRAPH_BPITCH2__ALIAS_1 NV_PGRAPH_BPITCH(2) /* */ -#define NV_PGRAPH_BPITCH2_VALUE 12:0 /* RWIUF */ -#define NV_PGRAPH_BPITCH2_VALUE_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPITCH3 0x0040067C /* RW-4R */ -#define NV_PGRAPH_BPITCH3__ALIAS_1 NV_PGRAPH_BPITCH(3) /* */ -#define NV_PGRAPH_BPITCH3_VALUE 12:0 /* RWIUF */ -#define NV_PGRAPH_BPITCH3_VALUE_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPITCH4 0x00400680 /* RW-4R */ -#define NV_PGRAPH_BPITCH4__ALIAS_1 NV_PGRAPH_BPITCH(4) /* */ -#define NV_PGRAPH_BPITCH4_VALUE 12:0 /* RWIUF */ -#define NV_PGRAPH_BPITCH4_VALUE_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BLIMIT(i) (0x00400684+(i)*4) /* RW-4A */ -#define NV_PGRAPH_BLIMIT__SIZE_1 6 /* */ -#define NV_PGRAPH_BLIMIT_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_BLIMIT_TYPE 31:31 /* RWIVF */ -#define NV_PGRAPH_BLIMIT_TYPE_IN_MEMORY 0x00000000 /* RW--V */ -#define NV_PGRAPH_BLIMIT_TYPE_NULL 0x00000001 /* RWI-V */ -#define NV_PGRAPH_BLIMIT0 0x00400684 /* RW-4R */ -#define NV_PGRAPH_BLIMIT0__ALIAS_1 NV_PGRAPH_BLIMIT(0) /* */ -#define NV_PGRAPH_BLIMIT0_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_BLIMIT0_TYPE 31:31 /* RWIVF */ -#define NV_PGRAPH_BLIMIT0_TYPE_IN_MEMORY 0x00000000 /* RW--V */ -#define NV_PGRAPH_BLIMIT0_TYPE_NULL 0x00000001 /* RWI-V */ -#define NV_PGRAPH_BLIMIT1 0x00400688 /* RW-4R */ -#define NV_PGRAPH_BLIMIT1__ALIAS_1 NV_PGRAPH_BLIMIT(1) /* */ -#define NV_PGRAPH_BLIMIT1_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_BLIMIT1_TYPE 31:31 /* RWIVF */ -#define NV_PGRAPH_BLIMIT1_TYPE_IN_MEMORY 0x00000000 /* RW--V */ -#define NV_PGRAPH_BLIMIT1_TYPE_NULL 0x00000001 /* RWI-V */ -#define NV_PGRAPH_BLIMIT2 0x0040068c /* RW-4R */ -#define NV_PGRAPH_BLIMIT2__ALIAS_1 NV_PGRAPH_BLIMIT(2) /* */ -#define NV_PGRAPH_BLIMIT2_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_BLIMIT2_TYPE 31:31 /* RWIVF */ -#define NV_PGRAPH_BLIMIT2_TYPE_IN_MEMORY 0x00000000 /* RW--V */ -#define NV_PGRAPH_BLIMIT2_TYPE_NULL 0x00000001 /* RWI-V */ -#define NV_PGRAPH_BLIMIT3 0x00400690 /* RW-4R */ -#define NV_PGRAPH_BLIMIT3__ALIAS_1 NV_PGRAPH_BLIMIT(3) /* */ -#define NV_PGRAPH_BLIMIT3_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_BLIMIT3_TYPE 31:31 /* RWIVF */ -#define NV_PGRAPH_BLIMIT3_TYPE_IN_MEMORY 0x00000000 /* RW--V */ -#define NV_PGRAPH_BLIMIT3_TYPE_NULL 0x00000001 /* RWI-V */ -#define NV_PGRAPH_BLIMIT4 0x00400694 /* RW-4R */ -#define NV_PGRAPH_BLIMIT4__ALIAS_1 NV_PGRAPH_BLIMIT(4) /* */ -#define NV_PGRAPH_BLIMIT4_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_BLIMIT4_TYPE 31:31 /* RWIVF */ -#define NV_PGRAPH_BLIMIT4_TYPE_IN_MEMORY 0x00000000 /* RW--V */ -#define NV_PGRAPH_BLIMIT4_TYPE_NULL 0x00000001 /* RWI-V */ -#define NV_PGRAPH_BLIMIT5 0x00400698 /* RW-4R */ -#define NV_PGRAPH_BLIMIT5__ALIAS_1 NV_PGRAPH_BLIMIT(5) /* */ -#define NV_PGRAPH_BLIMIT5_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_BLIMIT5_TYPE 31:31 /* RWIVF */ -#define NV_PGRAPH_BLIMIT5_TYPE_IN_MEMORY 0x00000000 /* RW--V */ -#define NV_PGRAPH_BLIMIT5_TYPE_NULL 0x00000001 /* RWI-V */ -#define NV_PGRAPH_BSWIZZLE2 0x0040069c /* RW-4R */ -#define NV_PGRAPH_BSWIZZLE2_WIDTH 19:16 /* RWIUF */ -#define NV_PGRAPH_BSWIZZLE2_WIDTH_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BSWIZZLE2_HEIGHT 27:24 /* RWIUF */ -#define NV_PGRAPH_BSWIZZLE2_HEIGHT_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BSWIZZLE5 0x004006a0 /* RW-4R */ -#define NV_PGRAPH_BSWIZZLE5_WIDTH 19:16 /* RWIUF */ -#define NV_PGRAPH_BSWIZZLE5_WIDTH_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BSWIZZLE5_HEIGHT 27:24 /* RWIUF */ -#define NV_PGRAPH_BSWIZZLE5_HEIGHT_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPIXEL 0x00400724 /* RW-4R */ -#define NV_PGRAPH_BPIXEL_DEPTH0 3:0 /* RWIVF */ -#define NV_PGRAPH_BPIXEL_DEPTH0_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_Y8 0x00000001 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_X1R5G5B5_Z1R5G5B5 0x00000002 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_X1R5G5B5_O1R5G5B5 0x00000003 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_A1R5G5B5 0x00000004 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_R5G6B5 0x00000005 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_Y16 0x00000006 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_X8R8G8B8_Z8R8G8B8 0x00000007 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_X8R8G8B8_O1Z7R8G8B8 0x00000008 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_X1A7R8G8B8_Z1A7R8G8B8 0x00000009 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_X1A7R8G8B8_O1A7R8G8B8 0x0000000a /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_X8R8G8B8_O8R8G8B8 0x0000000b /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_A8R8G8B8 0x0000000c /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_Y32 0x0000000d /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_V8YB8U8YA8 0x0000000e /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH0_YB8V8YA8U8 0x0000000f /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1 7:4 /* RWIVF */ -#define NV_PGRAPH_BPIXEL_DEPTH1_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_Y8 0x00000001 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_X1R5G5B5_Z1R5G5B5 0x00000002 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_X1R5G5B5_O1R5G5B5 0x00000003 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_A1R5G5B5 0x00000004 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_R5G6B5 0x00000005 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_Y16 0x00000006 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_X8R8G8B8_Z8R8G8B8 0x00000007 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_X8R8G8B8_O1Z7R8G8B8 0x00000008 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_X1A7R8G8B8_Z1A7R8G8B8 0x00000009 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_X1A7R8G8B8_O1A7R8G8B8 0x0000000a /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_X8R8G8B8_O8R8G8B8 0x0000000b /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_A8R8G8B8 0x0000000c /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_Y32 0x0000000d /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_V8YB8U8YA8 0x0000000e /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH1_YB8V8YA8U8 0x0000000f /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2 11:8 /* RWIVF */ -#define NV_PGRAPH_BPIXEL_DEPTH2_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_Y8 0x00000001 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_X1R5G5B5_Z1R5G5B5 0x00000002 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_X1R5G5B5_O1R5G5B5 0x00000003 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_A1R5G5B5 0x00000004 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_R5G6B5 0x00000005 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_Y16 0x00000006 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_X8R8G8B8_Z8R8G8B8 0x00000007 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_X8R8G8B8_O1Z7R8G8B8 0x00000008 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_X1A7R8G8B8_Z1A7R8G8B8 0x00000009 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_X1A7R8G8B8_O1A7R8G8B8 0x0000000a /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_X8R8G8B8_O8R8G8B8 0x0000000b /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_A8R8G8B8 0x0000000c /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_Y32 0x0000000d /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_V8YB8U8YA8 0x0000000e /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH2_YB8V8YA8U8 0x0000000f /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3 15:12 /* RWIVF */ -#define NV_PGRAPH_BPIXEL_DEPTH3_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_Y8 0x00000001 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_X1R5G5B5_Z1R5G5B5 0x00000002 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_X1R5G5B5_O1R5G5B5 0x00000003 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_A1R5G5B5 0x00000004 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_R5G6B5 0x00000005 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_Y16 0x00000006 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_X8R8G8B8_Z8R8G8B8 0x00000007 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_X8R8G8B8_O1Z7R8G8B8 0x00000008 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_X1A7R8G8B8_Z1A7R8G8B8 0x00000009 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_X1A7R8G8B8_O1A7R8G8B8 0x0000000a /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_X8R8G8B8_O8R8G8B8 0x0000000b /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_A8R8G8B8 0x0000000c /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_Y32 0x0000000d /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_V8YB8U8YA8 0x0000000e /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH3_YB8V8YA8U8 0x0000000f /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4 19:16 /* RWIVF */ -#define NV_PGRAPH_BPIXEL_DEPTH4_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_Y8 0x00000001 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_X1R5G5B5_Z1R5G5B5 0x00000002 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_X1R5G5B5_O1R5G5B5 0x00000003 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_A1R5G5B5 0x00000004 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_R5G6B5 0x00000005 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_Y16 0x00000006 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_X8R8G8B8_Z8R8G8B8 0x00000007 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_X8R8G8B8_O1Z7R8G8B8 0x00000008 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_X1A7R8G8B8_Z1A7R8G8B8 0x00000009 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_X1A7R8G8B8_O1A7R8G8B8 0x0000000a /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_X8R8G8B8_O8R8G8B8 0x0000000b /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_A8R8G8B8 0x0000000c /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_Y32 0x0000000d /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_V8YB8U8YA8 0x0000000e /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH4_YB8V8YA8U8 0x0000000f /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5 23:20 /* RWIVF */ -#define NV_PGRAPH_BPIXEL_DEPTH5_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_Y8 0x00000001 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_X1R5G5B5_Z1R5G5B5 0x00000002 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_X1R5G5B5_O1R5G5B5 0x00000003 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_A1R5G5B5 0x00000004 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_R5G6B5 0x00000005 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_Y16 0x00000006 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_X8R8G8B8_Z8R8G8B8 0x00000007 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_X8R8G8B8_O1Z7R8G8B8 0x00000008 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_X1A7R8G8B8_Z1A7R8G8B8 0x00000009 /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_X1A7R8G8B8_O1A7R8G8B8 0x0000000a /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_X8R8G8B8_O8R8G8B8 0x0000000b /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_A8R8G8B8 0x0000000c /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_Y32 0x0000000d /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_V8YB8U8YA8 0x0000000e /* RW--V */ -#define NV_PGRAPH_BPIXEL_DEPTH5_YB8V8YA8U8 0x0000000f /* RW--V */ -#define NV_PGRAPH_LIMIT_VIOL_PIX 0x00400610 /* RW-4R */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_ADRS 23:0 /* RWIVF */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_ADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_BLIT 29:29 /* RWIVF */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_BLIT_NO_VIOL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_BLIT_VIOL 0x00000001 /* RW--V */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_LIMIT 30:30 /* RWIVF */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_LIMIT_NO_VIOL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_LIMIT_VIOL 0x00000001 /* RW--V */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_OVRFLW 31:31 /* RWIVF */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_OVRFLW_NO_VIOL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_LIMIT_VIOL_PIX_OVRFLW_VIOL 0x00000001 /* RW--V */ -#define NV_PGRAPH_LIMIT_VIOL_Z 0x00400614 /* RW-4R */ -#define NV_PGRAPH_LIMIT_VIOL_Z_ADRS 23:0 /* RWIVF */ -#define NV_PGRAPH_LIMIT_VIOL_Z_ADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_LIMIT_VIOL_Z_LIMIT 30:30 /* RWIVF */ -#define NV_PGRAPH_LIMIT_VIOL_Z_LIMIT_NO_VIOL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_LIMIT_VIOL_Z_LIMIT_VIOL 0x00000001 /* RW--V */ -#define NV_PGRAPH_LIMIT_VIOL_Z_OVRFLW 31:31 /* RWIVF */ -#define NV_PGRAPH_LIMIT_VIOL_Z_OVRFLW_NO_VIOL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_LIMIT_VIOL_Z_OVRFLW_VIOL 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE 0x00400710 /* RW-4R */ -#define NV_PGRAPH_STATE_BUFFER_0 0:0 /* RWIVF */ -#define NV_PGRAPH_STATE_BUFFER_0_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_BUFFER_0_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_BUFFER_1 1:1 /* RWIVF */ -#define NV_PGRAPH_STATE_BUFFER_1_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_BUFFER_1_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_BUFFER_2 2:2 /* RWIVF */ -#define NV_PGRAPH_STATE_BUFFER_2_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_BUFFER_2_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_BUFFER_3 3:3 /* RWIVF */ -#define NV_PGRAPH_STATE_BUFFER_3_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_BUFFER_3_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_BUFFER_4 4:4 /* RWIVF */ -#define NV_PGRAPH_STATE_BUFFER_4_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_BUFFER_4_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_BUFFER_5 5:5 /* RWIVF */ -#define NV_PGRAPH_STATE_BUFFER_5_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_BUFFER_5_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_PITCH_0 8:8 /* RWIVF */ -#define NV_PGRAPH_STATE_PITCH_0_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_PITCH_0_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_PITCH_1 9:9 /* RWIVF */ -#define NV_PGRAPH_STATE_PITCH_1_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_PITCH_1_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_PITCH_2 10:10 /* RWIVF */ -#define NV_PGRAPH_STATE_PITCH_2_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_PITCH_2_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_PITCH_3 11:11 /* RWIVF */ -#define NV_PGRAPH_STATE_PITCH_3_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_PITCH_3_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_PITCH_4 12:12 /* RWIVF */ -#define NV_PGRAPH_STATE_PITCH_4_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_PITCH_4_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_CHROMA_COLOR 16:16 /* RWIVF */ -#define NV_PGRAPH_STATE_CHROMA_COLOR_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_CHROMA_COLOR_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_CHROMA_COLORFMT 17:17 /* RWIVF */ -#define NV_PGRAPH_STATE_CHROMA_COLORFMT_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_CHROMA_COLORFMT_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_CPATTERN_COLORFMT 20:20 /* RWIVF */ -#define NV_PGRAPH_STATE_CPATTERN_COLORFMT_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_CPATTERN_COLORFMT_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_CPATTERN_MONOFMT 21:21 /* RWIVF */ -#define NV_PGRAPH_STATE_CPATTERN_MONOFMT_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_CPATTERN_MONOFMT_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_CPATTERN_SELECT 22:22 /* RWIVF */ -#define NV_PGRAPH_STATE_CPATTERN_SELECT_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_CPATTERN_SELECT_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_PATTERN_COLOR0 24:24 /* RWIVF */ -#define NV_PGRAPH_STATE_PATTERN_COLOR0_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_PATTERN_COLOR0_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_PATTERN_COLOR1 25:25 /* RWIVF */ -#define NV_PGRAPH_STATE_PATTERN_COLOR1_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_PATTERN_COLOR1_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_PATTERN_PATT0 26:26 /* RWIVF */ -#define NV_PGRAPH_STATE_PATTERN_PATT0_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_PATTERN_PATT0_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_STATE_PATTERN_PATT1 27:27 /* RWIVF */ -#define NV_PGRAPH_STATE_PATTERN_PATT1_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_STATE_PATTERN_PATT1_VALID 0x00000001 /* RW--V */ -#define NV_PGRAPH_CACHE_INDEX 0x00400728 /* RW-4R */ -#define NV_PGRAPH_CACHE_INDEX_BANK 2:2 /* RWXVF */ -#define NV_PGRAPH_CACHE_INDEX_BANK_10 0x00000000 /* RW--V */ -#define NV_PGRAPH_CACHE_INDEX_BANK_32 0x00000001 /* RW--V */ -#define NV_PGRAPH_CACHE_INDEX_ADRS 12:3 /* RWXVF */ -#define NV_PGRAPH_CACHE_INDEX_ADRS_0 0x00000000 /* RW--V */ -#define NV_PGRAPH_CACHE_INDEX_ADRS_1024 0x00000400 /* RW--V */ -#define NV_PGRAPH_CACHE_INDEX_OP 14:13 /* RWXVF */ -#define NV_PGRAPH_CACHE_INDEX_OP_WR_CACHE 0x00000000 /* RW--V */ -#define NV_PGRAPH_CACHE_INDEX_OP_RD_CACHE 0x00000001 /* RW--V */ -#define NV_PGRAPH_CACHE_INDEX_OP_RD_INDEX 0x00000002 /* RW--V */ -#define NV_PGRAPH_CACHE_RAM 0x0040072c /* RW-4R */ -#define NV_PGRAPH_CACHE_RAM_VALUE 31:0 /* RWXVF */ -#define NV_PGRAPH_DMA_PITCH 0x00400760 /* RW-4R */ -#define NV_PGRAPH_DMA_PITCH_S0 15:0 /* RWXSF */ -#define NV_PGRAPH_DMA_PITCH_S1 31:16 /* RWXSF */ -#define NV_PGRAPH_DVD_COLORFMT 0x00400764 /* RW-4R */ -#define NV_PGRAPH_DVD_COLORFMT_IMAGE 5:0 /* RWNVF */ -#define NV_PGRAPH_DVD_COLORFMT_IMAGE_FORMAT_INVALID 0x00 /* RWN-V */ -#define NV_PGRAPH_DVD_COLORFMT_IMAGE_FORMAT_LE_V8YB8U8YA8 0x12 /* RW--V */ -#define NV_PGRAPH_DVD_COLORFMT_IMAGE_FORMAT_LE_YB8V8YA8U8 0x13 /* RW--V */ -#define NV_PGRAPH_DVD_COLORFMT_OVLY 9:8 /* RWNVF */ -#define NV_PGRAPH_DVD_COLORFMT_OVLY_FORMAT_INVALID 0x00 /* RWN-V */ -#define NV_PGRAPH_DVD_COLORFMT_OVLY_FORMAT_LE_A8Y8U8V8 0x01 /* RW--V */ -#define NV_PGRAPH_DVD_COLORFMT_OVLY_FORMAT_LE_A4V6YB6A4U6YA6 0x02 /* RW--V */ -#define NV_PGRAPH_DVD_COLORFMT_OVLY_FORMAT_TRANSPARENT 0x03 /* RW--V */ -#define NV_PGRAPH_SCALED_FORMAT 0x00400768 /* RW-4R */ -#define NV_PGRAPH_SCALED_FORMAT_ORIGIN 17:16 /* RWIVF */ -#define NV_PGRAPH_SCALED_FORMAT_ORIGIN_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_SCALED_FORMAT_ORIGIN_CENTER 0x00000001 /* RW--V */ -#define NV_PGRAPH_SCALED_FORMAT_ORIGIN_CORNER 0x00000002 /* RW--V */ -#define NV_PGRAPH_SCALED_FORMAT_INTERPOLATOR 24:24 /* RWIVF */ -#define NV_PGRAPH_SCALED_FORMAT_INTERPOLATOR_ZOH 0x00000000 /* RWI-V */ -#define NV_PGRAPH_SCALED_FORMAT_INTERPOLATOR_FOH 0x00000001 /* RW--V */ -#define NV_PGRAPH_PATT_COLOR0 0x00400800 /* RW-4R */ -#define NV_PGRAPH_PATT_COLOR0_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_PATT_COLOR1 0x00400804 /* RW-4R */ -#define NV_PGRAPH_PATT_COLOR1_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_PATT_COLORRAM(i) (0x00400900+(i)*4) /* R--4A */ -#define NV_PGRAPH_PATT_COLORRAM__SIZE_1 64 /* */ -#define NV_PGRAPH_PATT_COLORRAM_VALUE 23:0 /* R--UF */ -#define NV_PGRAPH_PATTERN(i) (0x00400808+(i)*4) /* RW-4A */ -#define NV_PGRAPH_PATTERN__SIZE_1 2 /* */ -#define NV_PGRAPH_PATTERN_BITMAP 31:0 /* RWXVF */ -#define NV_PGRAPH_PATTERN_SHAPE 0x00400810 /* RW-4R */ -#define NV_PGRAPH_PATTERN_SHAPE_VALUE 1:0 /* RWXVF */ -#define NV_PGRAPH_PATTERN_SHAPE_VALUE_8X_8Y 0x00000000 /* RW--V */ -#define NV_PGRAPH_PATTERN_SHAPE_VALUE_64X_1Y 0x00000001 /* RW--V */ -#define NV_PGRAPH_PATTERN_SHAPE_VALUE_1X_64Y 0x00000002 /* RW--V */ -#define NV_PGRAPH_PATTERN_SHAPE_SELECT 4:4 /* RWXVF */ -#define NV_PGRAPH_PATTERN_SHAPE_SELECT_2COLOR 0x00000000 /* RW--V */ -#define NV_PGRAPH_PATTERN_SHAPE_SELECT_FULLCOLOR 0x00000001 /* RW--V */ -#define NV_PGRAPH_MONO_COLOR0 0x00400600 /* RW-4R */ -#define NV_PGRAPH_MONO_COLOR0_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_ROP3 0x00400604 /* RW-4R */ -#define NV_PGRAPH_ROP3_VALUE 7:0 /* RWXVF */ -#define NV_PGRAPH_CHROMA 0x00400814 /* RW-4R */ -#define NV_PGRAPH_CHROMA_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_BETA_AND 0x00400608 /* RW-4R */ -#define NV_PGRAPH_BETA_AND_VALUE_FRACTION 30:23 /* RWXUF */ -#define NV_PGRAPH_BETA_PREMULT 0x0040060c /* RW-4R */ -#define NV_PGRAPH_BETA_PREMULT_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_CONTROL0 0x00400818 /* RW-4R */ -#define NV_PGRAPH_CONTROL1 0x0040081c /* RW-4R */ -#define NV_PGRAPH_CONTROL2 0x00400820 /* RW-4R */ -#define NV_PGRAPH_BLEND 0x00400824 /* RW-4R */ -#define NV_PGRAPH_DPRAM_INDEX 0x00400828 /* RW-4R */ -#define NV_PGRAPH_DPRAM_INDEX_ADRS 6:0 /* RWIVF */ -#define NV_PGRAPH_DPRAM_INDEX_ADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_DPRAM_INDEX_SELECT 10:8 /* RWIVF */ -#define NV_PGRAPH_DPRAM_INDEX_SELECT_ADRS_0 0x00000000 /* RWI-V */ -#define NV_PGRAPH_DPRAM_INDEX_SELECT_ADRS_1 0x00000001 /* RW--V */ -#define NV_PGRAPH_DPRAM_INDEX_SELECT_DATA_0 0x00000002 /* RW--V */ -#define NV_PGRAPH_DPRAM_INDEX_SELECT_DATA_1 0x00000003 /* RW--V */ -#define NV_PGRAPH_DPRAM_INDEX_SELECT_WE_0 0x00000004 /* RW--V */ -#define NV_PGRAPH_DPRAM_INDEX_SELECT_WE_1 0x00000005 /* RW--V */ -#define NV_PGRAPH_DPRAM_INDEX_SELECT_ALPHA_0 0x00000006 /* RW--V */ -#define NV_PGRAPH_DPRAM_INDEX_SELECT_ALPHA_1 0x00000007 /* RW--V */ -#define NV_PGRAPH_DPRAM_DATA 0x0040082c /* RW-4R */ -#define NV_PGRAPH_DPRAM_DATA_VALUE 31:0 /* RWXVF */ -#define NV_PGRAPH_DPRAM_ADRS_0 0x0040082c /* RW-4R */ -#define NV_PGRAPH_DPRAM_ADRS_0__ALIAS_1 NV_PGRAPH_DPRAM_DATA /* */ -#define NV_PGRAPH_DPRAM_ADRS_0_VALUE 19:0 /* RWXVF */ -#define NV_PGRAPH_DPRAM_ADRS_1 0x0040082c /* RW-4R */ -#define NV_PGRAPH_DPRAM_ADRS_1__ALIAS_1 NV_PGRAPH_DPRAM_DATA /* */ -#define NV_PGRAPH_DPRAM_ADRS_1_VALUE 19:0 /* RWXVF */ -#define NV_PGRAPH_DPRAM_DATA_0 0x0040082c /* RW-4R */ -#define NV_PGRAPH_DPRAM_DATA_0__ALIAS_1 NV_PGRAPH_DPRAM_DATA /* */ -#define NV_PGRAPH_DPRAM_DATA_0_VALUE 31:0 /* RWXVF */ -#define NV_PGRAPH_DPRAM_DATA_1 0x0040082c /* RW-4R */ -#define NV_PGRAPH_DPRAM_DATA_1__ALIAS_1 NV_PGRAPH_DPRAM_DATA /* */ -#define NV_PGRAPH_DPRAM_DATA_1_VALUE 31:0 /* RWXVF */ -#define NV_PGRAPH_DPRAM_WE_0 0x0040082c /* RW-4R */ -#define NV_PGRAPH_DPRAM_WE_0__ALIAS_1 NV_PGRAPH_DPRAM_DATA /* */ -#define NV_PGRAPH_DPRAM_WE_0_VALUE 23:0 /* RWXVF */ -#define NV_PGRAPH_DPRAM_WE_1 0x0040082c /* RW-4R */ -#define NV_PGRAPH_DPRAM_WE_1__ALIAS_1 NV_PGRAPH_DPRAM_DATA /* */ -#define NV_PGRAPH_DPRAM_WE_1_VALUE 23:0 /* RWXVF */ -#define NV_PGRAPH_DPRAM_ALPHA_0 0x0040082c /* RW-4R */ -#define NV_PGRAPH_DPRAM_ALPHA_0__ALIAS_1 NV_PGRAPH_DPRAM_DATA /* */ -#define NV_PGRAPH_DPRAM_ALPHA_0_VALUE 31:0 /* RWXVF */ -#define NV_PGRAPH_DPRAM_ALPHA_1 0x0040082c /* RW-4R */ -#define NV_PGRAPH_DPRAM_ALPHA_1__ALIAS_1 NV_PGRAPH_DPRAM_DATA /* */ -#define NV_PGRAPH_DPRAM_ALPHA_1_VALUE 31:0 /* RWXVF */ -#define NV_PGRAPH_STORED_FMT 0x00400830 /* RW-4R */ -#define NV_PGRAPH_STORED_FMT_MONO0 5:0 /* RWXVF */ -#define NV_PGRAPH_STORED_FMT_PATT0 13:8 /* RWXVF */ -#define NV_PGRAPH_STORED_FMT_PATT1 21:16 /* RWXVF */ -#define NV_PGRAPH_STORED_FMT_CHROMA 29:24 /* RWXVF */ -#define NV_PGRAPH_FORMATS 0x00400618 /* RW-4R */ -#define NV_PGRAPH_FORMATS_ROP 2:0 /* R-XVF */ -#define NV_PGRAPH_FORMATS_ROP_Y8 0x00000000 /* -W--V */ -#define NV_PGRAPH_FORMATS_ROP_RGB15 0x00000001 /* -W--V */ -#define NV_PGRAPH_FORMATS_ROP_RGB16 0x00000002 /* -W--V */ -#define NV_PGRAPH_FORMATS_ROP_Y16 0x00000003 /* -W--V */ -#define NV_PGRAPH_FORMATS_ROP_INVALID 0x00000004 /* -W--V */ -#define NV_PGRAPH_FORMATS_ROP_RGB24 0x00000005 /* -W--V */ -#define NV_PGRAPH_FORMATS_ROP_RGB30 0x00000006 /* -W--V */ -#define NV_PGRAPH_FORMATS_ROP_Y32 0x00000007 /* -W--V */ -#define NV_PGRAPH_FORMATS_SRC 9:4 /* R-XVF */ -#define NV_PGRAPH_FORMATS_SRC_INVALID 0x00000000 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_Y8 0x00000001 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_X16A8Y8 0x00000002 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_X24Y8 0x00000003 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_A1R5G5B5 0x00000006 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_X1R5G5B5 0x00000007 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_X16A1R5G5B5 0x00000008 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_X17R5G5B5 0x00000009 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_R5G6B5 0x0000000A /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_A16R5G6B5 0x0000000B /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_X16R5G6B5 0x0000000C /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_A8R8G8B8 0x0000000D /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_X8R8G8B8 0x0000000E /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_Y16 0x0000000F /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_A16Y16 0x00000010 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_X16Y16 0x00000011 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_V8YB8U8YA8 0x00000012 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_YB8V8YA8U8 0x00000013 /* RW--V */ -#define NV_PGRAPH_FORMATS_SRC_LE_Y32 0x00000014 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB 15:12 /* R-XVF */ -#define NV_PGRAPH_FORMATS_FB_INVALID 0x00000000 /* RWI-V */ -#define NV_PGRAPH_FORMATS_FB_Y8 0x00000001 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_X1R5G5B5_Z1R5G5B5 0x00000002 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_X1R5G5B5_O1R5G5B5 0x00000003 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_A1R5G5B5 0x00000004 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_R5G6B5 0x00000005 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_Y16 0x00000006 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_X8R8G8B8_Z8R8G8B8 0x00000007 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_X8R8G8B8_O1Z7R8G8B8 0x00000008 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_X1A7R8G8B8_Z1A7R8G8B8 0x00000009 /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_X1A7R8G8B8_O1A7R8G8B8 0x0000000a /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_X8R8G8B8_O8R8G8B8 0x0000000b /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_A8R8G8B8 0x0000000c /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_Y32 0x0000000d /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_V8YB8U8YA8 0x0000000e /* RW--V */ -#define NV_PGRAPH_FORMATS_FB_YB8V8YA8U8 0x0000000f /* RW--V */ -#define NV_PGRAPH_ABS_X_RAM(i) (0x00400400+(i)*4) /* RW-4A */ -#define NV_PGRAPH_ABS_X_RAM__SIZE_1 32 /* */ -#define NV_PGRAPH_ABS_X_RAM_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_X_RAM_BPORT(i) (0x00400c00+(i)*4) /* R--4A */ -#define NV_PGRAPH_X_RAM_BPORT__SIZE_1 32 /* */ -#define NV_PGRAPH_X_RAM_BPORT_VALUE 31:0 /* R--UF */ -#define NV_PGRAPH_ABS_Y_RAM(i) (0x00400480+(i)*4) /* RW-4A */ -#define NV_PGRAPH_ABS_Y_RAM__SIZE_1 32 /* */ -#define NV_PGRAPH_ABS_Y_RAM_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_Y_RAM_BPORT(i) (0x00400c80+(i)*4) /* R--4A */ -#define NV_PGRAPH_Y_RAM_BPORT__SIZE_1 32 /* */ -#define NV_PGRAPH_Y_RAM_BPORT_VALUE 31:0 /* R--UF */ -#define NV_PGRAPH_XY_LOGIC_MISC0 0x00400514 /* RW-4R */ -#define NV_PGRAPH_XY_LOGIC_MISC0_COUNTER 17:0 /* RWBUF */ -#define NV_PGRAPH_XY_LOGIC_MISC0_COUNTER_0 0x00000000 /* RWB-V */ -#define NV_PGRAPH_XY_LOGIC_MISC0_DIMENSION 20:20 /* RWVVF */ -#define NV_PGRAPH_XY_LOGIC_MISC0_DIMENSION_NONZERO 0x00000000 /* RWV-V */ -#define NV_PGRAPH_XY_LOGIC_MISC0_DIMENSION_ZERO 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC0_INDEX 31:28 /* RWBUF */ -#define NV_PGRAPH_XY_LOGIC_MISC0_INDEX_0 0x00000000 /* RWB-V */ -#define NV_PGRAPH_XY_LOGIC_MISC1 0x00400518 /* RW-4R */ -#define NV_PGRAPH_XY_LOGIC_MISC1_INITIAL 0:0 /* RWNVF */ -#define NV_PGRAPH_XY_LOGIC_MISC1_INITIAL_NEEDED 0x00000000 /* RWN-V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_INITIAL_DONE 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPX 4:4 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPX_NOTNULL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPX_NULL 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPY 5:5 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPY_NOTNULL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_XTRACLIPY_NULL 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XIMAX 12:12 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XIMAX_UUMAX 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XIMAX_IMAGEMAX 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_YIMAX 16:16 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_YIMAX_UUMAX 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_YIMAX_IMAGEMAX 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XXTRA 20:20 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XXTRA_CLIPMAX 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC1_SEL_XXTRA_IMAGEMAX 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC2 0x0040051C /* RW-4R */ -#define NV_PGRAPH_XY_LOGIC_MISC2_HANDOFF 0:0 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC2_HANDOFF_DISABLE 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_HANDOFF_ENABLE 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPX 4:4 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPX_NOTNULL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPX_NULL 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPY 5:5 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPY_NOTNULL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_XTRACLIPY_NULL 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XIMAX 12:12 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XIMAX_UCMAX 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XIMAX_IMAGEMAX 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_YIMAX 16:16 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_YIMAX_UCMAX 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_YIMAX_IMAGEMAX 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XXTRA 20:20 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XXTRA_CLIPMAX 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC2_SEL_XXTRA_IMAGEMAX 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC3 0x00400520 /* RW-4R */ -#define NV_PGRAPH_XY_LOGIC_MISC3_WDIMY_EQ_0 0:0 /* RWXVF */ -#define NV_PGRAPH_XY_LOGIC_MISC3_WDIMY_EQ_0_NULL 0x00000000 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC3_WDIMY_EQ_0_TRUE 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WDIMY 4:4 /* RWXVF */ -#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WDIMY_NULL 0x00000000 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WDIMY_TRUE 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WX 8:8 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WX_NULL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC3_RELOAD_WX_TRUE 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_ALG 12:12 /* RWIVF */ -#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_ALG_NULL 0x00000000 /* RWI-V */ -#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_ALG_TRUE 0x00000001 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_DIMX 22:16 /* RWXUF */ -#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_DIMX_0 0x00000000 /* RW--V */ -#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_WDIMX 30:24 /* RWXUF */ -#define NV_PGRAPH_XY_LOGIC_MISC3_TEXT_WDIMX_0 0x00000000 /* RW--V */ -#define NV_PGRAPH_X_MISC 0x00400500 /* RW-4R */ -#define NV_PGRAPH_X_MISC_BIT33_0 0:0 /* RWNVF */ -#define NV_PGRAPH_X_MISC_BIT33_0_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_X_MISC_BIT33_1 1:1 /* RWNVF */ -#define NV_PGRAPH_X_MISC_BIT33_1_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_X_MISC_BIT33_2 2:2 /* RWNVF */ -#define NV_PGRAPH_X_MISC_BIT33_2_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_X_MISC_BIT33_3 3:3 /* RWNVF */ -#define NV_PGRAPH_X_MISC_BIT33_3_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_X_MISC_RANGE_0 4:4 /* RWNVF */ -#define NV_PGRAPH_X_MISC_RANGE_0_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_X_MISC_RANGE_1 5:5 /* RWNVF */ -#define NV_PGRAPH_X_MISC_RANGE_1_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_X_MISC_RANGE_2 6:6 /* RWNVF */ -#define NV_PGRAPH_X_MISC_RANGE_2_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_X_MISC_RANGE_3 7:7 /* RWNVF */ -#define NV_PGRAPH_X_MISC_RANGE_3_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_X_MISC_ADDER_OUTPUT 29:28 /* RWXVF */ -#define NV_PGRAPH_X_MISC_ADDER_OUTPUT_EQ_0 0x00000000 /* RW--V */ -#define NV_PGRAPH_X_MISC_ADDER_OUTPUT_LT_0 0x00000001 /* RW--V */ -#define NV_PGRAPH_X_MISC_ADDER_OUTPUT_GT_0 0x00000002 /* RW--V */ -#define NV_PGRAPH_Y_MISC 0x00400504 /* RW-4R */ -#define NV_PGRAPH_Y_MISC_BIT33_0 0:0 /* RWNVF */ -#define NV_PGRAPH_Y_MISC_BIT33_0_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_Y_MISC_BIT33_1 1:1 /* RWNVF */ -#define NV_PGRAPH_Y_MISC_BIT33_1_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_Y_MISC_BIT33_2 2:2 /* RWNVF */ -#define NV_PGRAPH_Y_MISC_BIT33_2_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_Y_MISC_BIT33_3 3:3 /* RWNVF */ -#define NV_PGRAPH_Y_MISC_BIT33_3_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_Y_MISC_RANGE_0 4:4 /* RWNVF */ -#define NV_PGRAPH_Y_MISC_RANGE_0_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_Y_MISC_RANGE_1 5:5 /* RWNVF */ -#define NV_PGRAPH_Y_MISC_RANGE_1_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_Y_MISC_RANGE_2 6:6 /* RWNVF */ -#define NV_PGRAPH_Y_MISC_RANGE_2_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_Y_MISC_RANGE_3 7:7 /* RWNVF */ -#define NV_PGRAPH_Y_MISC_RANGE_3_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_Y_MISC_ADDER_OUTPUT 29:28 /* RWXVF */ -#define NV_PGRAPH_Y_MISC_ADDER_OUTPUT_EQ_0 0x00000000 /* RW--V */ -#define NV_PGRAPH_Y_MISC_ADDER_OUTPUT_LT_0 0x00000001 /* RW--V */ -#define NV_PGRAPH_Y_MISC_ADDER_OUTPUT_GT_0 0x00000002 /* RW--V */ -#define NV_PGRAPH_ABS_UCLIP_XMIN 0x0040053C /* RW-4R */ -#define NV_PGRAPH_ABS_UCLIP_XMIN_VALUE 15:0 /* RWXSF */ -#define NV_PGRAPH_ABS_UCLIP_XMAX 0x00400544 /* RW-4R */ -#define NV_PGRAPH_ABS_UCLIP_XMAX_VALUE 17:0 /* RWXSF */ -#define NV_PGRAPH_ABS_UCLIP_YMIN 0x00400540 /* RW-4R */ -#define NV_PGRAPH_ABS_UCLIP_YMIN_VALUE 15:0 /* RWXSF */ -#define NV_PGRAPH_ABS_UCLIP_YMAX 0x00400548 /* RW-4R */ -#define NV_PGRAPH_ABS_UCLIP_YMAX_VALUE 17:0 /* RWXSF */ -#define NV_PGRAPH_ABS_UCLIPA_XMIN 0x00400560 /* RW-4R */ -#define NV_PGRAPH_ABS_UCLIPA_XMIN_VALUE 15:0 /* RWXSF */ -#define NV_PGRAPH_ABS_UCLIPA_XMAX 0x00400568 /* RW-4R */ -#define NV_PGRAPH_ABS_UCLIPA_XMAX_VALUE 17:0 /* RWXSF */ -#define NV_PGRAPH_ABS_UCLIPA_YMIN 0x00400564 /* RW-4R */ -#define NV_PGRAPH_ABS_UCLIPA_YMIN_VALUE 15:0 /* RWXSF */ -#define NV_PGRAPH_ABS_UCLIPA_YMAX 0x0040056C /* RW-4R */ -#define NV_PGRAPH_ABS_UCLIPA_YMAX_VALUE 17:0 /* RWXSF */ -#define NV_PGRAPH_SOURCE_COLOR 0x0040050C /* RW-4R */ -#define NV_PGRAPH_SOURCE_COLOR_VALUE 31:0 /* RWNVF */ -#define NV_PGRAPH_SOURCE_COLOR_VALUE_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_VALID1 0x00400508 /* RW-4R */ -#define NV_PGRAPH_VALID1_VLD 22:0 /* RWNVF */ -#define NV_PGRAPH_VALID1_VLD_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_VALID1_CLIP_MIN 28:28 /* RWIVF */ -#define NV_PGRAPH_VALID1_CLIP_MIN_NO_ERROR 0x00000000 /* RWI-V */ -#define NV_PGRAPH_VALID1_CLIP_MIN_ONLY 0x00000001 /* RW--V */ -#define NV_PGRAPH_VALID1_CLIPA_MIN 29:29 /* RWIVF */ -#define NV_PGRAPH_VALID1_CLIPA_MIN_NO_ERROR 0x00000000 /* RWI-V */ -#define NV_PGRAPH_VALID1_CLIPA_MIN_ONLY 0x00000001 /* RW--V */ -#define NV_PGRAPH_VALID1_CLIP_MAX 30:30 /* RWIVF */ -#define NV_PGRAPH_VALID1_CLIP_MAX_NO_ERROR 0x00000000 /* RWI-V */ -#define NV_PGRAPH_VALID1_CLIP_MAX_ONLY 0x00000001 /* RW--V */ -#define NV_PGRAPH_VALID1_CLIPA_MAX 31:31 /* RWIVF */ -#define NV_PGRAPH_VALID1_CLIPA_MAX_NO_ERROR 0x00000000 /* RWI-V */ -#define NV_PGRAPH_VALID1_CLIPA_MAX_ONLY 0x00000001 /* RW--V */ -#define NV_PGRAPH_VALID2 0x00400578 /* RW-4R */ -#define NV_PGRAPH_VALID2_VLD2 28:0 /* RWNVF */ -#define NV_PGRAPH_VALID2_VLD2_0 0x00000000 /* RWN-V */ -#define NV_PGRAPH_ABS_ICLIP_XMAX 0x00400534 /* RW-4R */ -#define NV_PGRAPH_ABS_ICLIP_XMAX_VALUE 17:0 /* RWXSF */ -#define NV_PGRAPH_ABS_ICLIP_YMAX 0x00400538 /* RW-4R */ -#define NV_PGRAPH_ABS_ICLIP_YMAX_VALUE 17:0 /* RWXSF */ -#define NV_PGRAPH_CLIPX_0 0x00400524 /* RW-4R */ -#define NV_PGRAPH_CLIPX_0_CLIP0_MIN 1:0 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP0_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP0_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP0_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP0_MAX 3:2 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP0_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP0_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP0_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP1_MIN 5:4 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP1_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP1_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP1_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP1_MAX 7:6 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP1_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP1_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP1_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP2_MIN 9:8 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP2_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP2_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP2_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP2_MAX 11:10 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP2_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP2_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP2_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP3_MIN 13:12 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP3_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP3_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP3_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP3_MAX 15:14 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP3_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP3_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP3_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP4_MIN 17:16 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP4_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP4_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP4_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP4_MAX 19:18 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP4_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP4_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP4_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP5_MIN 21:20 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP5_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP5_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP5_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP5_MAX 23:22 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP5_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP5_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP5_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP6_MIN 25:24 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP6_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP6_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP6_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP6_MAX 27:26 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP6_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP6_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP6_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP7_MIN 29:28 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP7_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP7_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP7_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP7_MAX 31:30 /* RWNVF */ -#define NV_PGRAPH_CLIPX_0_CLIP7_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_0_CLIP7_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_0_CLIP7_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1 0x00400528 /* RW-4R */ -#define NV_PGRAPH_CLIPX_1_CLIP8_MIN 1:0 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP8_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP8_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP8_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP8_MAX 3:2 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP8_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP8_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP8_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP9_MIN 5:4 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP9_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP9_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP9_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP9_MAX 7:6 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP9_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP9_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP9_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP10_MIN 9:8 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP10_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP10_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP10_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP10_MAX 11:10 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP10_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP10_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP10_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP11_MIN 13:12 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP11_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP11_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP11MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP11_MAX 15:14 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP11_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP11_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP11_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP12_MIN 17:16 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP12_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP12_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP12_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP12_MAX 19:18 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP12_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP12_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP12_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP13_MIN 21:20 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP13_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP13_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP13_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP13_MAX 23:22 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP13_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP13_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP13_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP14_MIN 25:24 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP14_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP14_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP14_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP14_MAX 27:26 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP14_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP14_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP14_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP15_MIN 29:28 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP15_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP15_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP15_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP15_MAX 31:30 /* RWNVF */ -#define NV_PGRAPH_CLIPX_1_CLIP15_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPX_1_CLIP15_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPX_1_CLIP15_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0 0x0040052c /* RW-4R */ -#define NV_PGRAPH_CLIPY_0_CLIP0_MIN 1:0 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP0_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP0_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP0_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP0_MAX 3:2 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP0_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP0_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP0_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP1_MIN 5:4 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP1_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP1_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP1_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP1_MAX 7:6 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP1_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP1_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP1_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP2_MIN 9:8 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP2_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP2_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP2_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP2_MAX 11:10 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP2_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP2_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP2_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP3_MIN 13:12 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP3_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP3_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP3_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP3_MAX 15:14 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP3_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP3_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP3_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP4_MIN 17:16 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP4_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP4_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP4_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP4_MAX 19:18 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP4_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP4_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP4_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP5_MIN 21:20 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP5_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP5_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP5_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP5_MAX 23:22 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP5_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP5_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP5_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP6_MIN 25:24 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP6_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP6_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP6_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP6_MAX 27:26 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP6_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP6_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP6_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP7_MIN 29:28 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP7_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP7_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP7_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP7_MAX 31:30 /* RWNVF */ -#define NV_PGRAPH_CLIPY_0_CLIP7_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_0_CLIP7_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_0_CLIP7_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1 0x00400530 /* RW-4R */ -#define NV_PGRAPH_CLIPY_1_CLIP8_MIN 1:0 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP8_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP8_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP8_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP8_MAX 3:2 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP8_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP8_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP8_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP9_MIN 5:4 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP9_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP9_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP9_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP9_MAX 7:6 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP9_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP9_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP9_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP10_MIN 9:8 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP10_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP10_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP10_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP10_MAX 11:10 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP10_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP10_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP10_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP11_MIN 13:12 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP11_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP11_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP11MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP11_MAX 15:14 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP11_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP11_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP11_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP12_MIN 17:16 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP12_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP12_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP12_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP12_MAX 19:18 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP12_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP12_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP12_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP13_MIN 21:20 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP13_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP13_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP13_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP13_MAX 23:22 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP13_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP13_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP13_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP14_MIN 25:24 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP14_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP14_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP14_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP14_MAX 27:26 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP14_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP14_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP14_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP15_MIN 29:28 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP15_MIN_GT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP15_MIN_LT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP15_MIN_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP15_MAX 31:30 /* RWNVF */ -#define NV_PGRAPH_CLIPY_1_CLIP15_MAX_LT 0x00000000 /* RW--V */ -#define NV_PGRAPH_CLIPY_1_CLIP15_MAX_GT 0x00000001 /* RWN-V */ -#define NV_PGRAPH_CLIPY_1_CLIP15_MAX_EQ 0x00000002 /* RW--V */ -#define NV_PGRAPH_MISC24_0 0x00400510 /* RW-4R */ -#define NV_PGRAPH_MISC24_0_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_MISC24_1 0x00400570 /* RW-4R */ -#define NV_PGRAPH_MISC24_1_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_MISC24_2 0x00400574 /* RW-4R */ -#define NV_PGRAPH_MISC24_2_VALUE 23:0 /* RWXUF */ -#define NV_PGRAPH_PASSTHRU_0 0x0040057C /* RW-4R */ -#define NV_PGRAPH_PASSTHRU_0_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_PASSTHRU_1 0x00400580 /* RW-4R */ -#define NV_PGRAPH_PASSTHRU_1_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_PASSTHRU_2 0x00400584 /* RW-4R */ -#define NV_PGRAPH_PASSTHRU_2_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_U_RAM(i) (0x00400d00+(i)*4) /* RW-4A */ -#define NV_PGRAPH_U_RAM__SIZE_1 16 /* */ -#define NV_PGRAPH_U_RAM_VALUE 31:6 /* RWXFF */ -#define NV_PGRAPH_V_RAM(i) (0x00400d40+(i)*4) /* RW-4A */ -#define NV_PGRAPH_V_RAM__SIZE_1 16 /* */ -#define NV_PGRAPH_V_RAM_VALUE 31:6 /* RWXFF */ -#define NV_PGRAPH_M_RAM(i) (0x00400d80+(i)*4) /* RW-4A */ -#define NV_PGRAPH_M_RAM__SIZE_1 16 /* */ -#define NV_PGRAPH_M_RAM_VALUE 31:6 /* RWXFF */ -#define NV_PGRAPH_DMA_START_0 0x00401000 /* RW-4R */ -#define NV_PGRAPH_DMA_START_0_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_START_1 0x00401004 /* RW-4R */ -#define NV_PGRAPH_DMA_START_1_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_LENGTH 0x00401008 /* RW-4R */ -#define NV_PGRAPH_DMA_LENGTH_VALUE 21:0 /* RWXUF */ -#define NV_PGRAPH_DMA_MISC 0x0040100C /* RW-4R */ -#define NV_PGRAPH_DMA_MISC_COUNT 15:0 /* RWXUF */ -#define NV_PGRAPH_DMA_MISC_FMT_SRC 18:16 /* RWXVF */ -#define NV_PGRAPH_DMA_MISC_FMT_DST 22:20 /* RWXVF */ -#define NV_PGRAPH_DMA_DATA_0 0x00401020 /* RW-4R */ -#define NV_PGRAPH_DMA_DATA_0_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_DATA_1 0x00401024 /* RW-4R */ -#define NV_PGRAPH_DMA_DATA_1_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_RM 0x00401030 /* RW-4R */ -#define NV_PGRAPH_DMA_RM_ASSIST_A 0:0 /* RWIVF */ -#define NV_PGRAPH_DMA_RM_ASSIST_A_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_DMA_RM_ASSIST_A_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_DMA_RM_ASSIST_A_RESET 0x00000001 /* -W--C */ -#define NV_PGRAPH_DMA_RM_ASSIST_B 1:1 /* RWIVF */ -#define NV_PGRAPH_DMA_RM_ASSIST_B_NOT_PENDING 0x00000000 /* R-I-V */ -#define NV_PGRAPH_DMA_RM_ASSIST_B_PENDING 0x00000001 /* R---V */ -#define NV_PGRAPH_DMA_RM_ASSIST_B_RESET 0x00000001 /* -W--C */ -#define NV_PGRAPH_DMA_RM_WRITE_REQ 4:4 /* CWIVF */ -#define NV_PGRAPH_DMA_RM_WRITE_REQ_NOT_PENDING 0x00000000 /* CWI-V */ -#define NV_PGRAPH_DMA_RM_WRITE_REQ_PENDING 0x00000001 /* -W--T */ -#define NV_PGRAPH_DMA_A_XLATE_INST 0x00401040 /* RW-4R */ -#define NV_PGRAPH_DMA_A_XLATE_INST_VALUE 15:0 /* RWXUF */ -#define NV_PGRAPH_DMA_A_CONTROL 0x00401044 /* RW-4R */ -#define NV_PGRAPH_DMA_A_CONTROL_PAGE_TABLE 12:12 /* RWIVF */ -#define NV_PGRAPH_DMA_A_CONTROL_PAGE_TABLE_NOT_PRESENT 0x00000000 /* RWI-V */ -#define NV_PGRAPH_DMA_A_CONTROL_PAGE_TABLE_PRESENT 0x00000001 /* RW--V */ -#define NV_PGRAPH_DMA_A_CONTROL_PAGE_ENTRY 13:13 /* RWXVF */ -#define NV_PGRAPH_DMA_A_CONTROL_PAGE_ENTRY_NOT_LINEAR 0x00000000 /* RW--V */ -#define NV_PGRAPH_DMA_A_CONTROL_PAGE_ENTRY_LINEAR 0x00000001 /* RW--V */ -#define NV_PGRAPH_DMA_A_CONTROL_TARGET_NODE 17:16 /* RWXUF */ -#define NV_PGRAPH_DMA_A_CONTROL_TARGET_NODE_NVM 0x00000000 /* RW--V */ -#define NV_PGRAPH_DMA_A_CONTROL_TARGET_NODE_PCI 0x00000002 /* RW--V */ -#define NV_PGRAPH_DMA_A_CONTROL_TARGET_NODE_AGP 0x00000003 /* RW--V */ -#define NV_PGRAPH_DMA_A_CONTROL_ADJUST 31:20 /* RWXUF */ -#define NV_PGRAPH_DMA_A_LIMIT 0x00401048 /* RW-4R */ -#define NV_PGRAPH_DMA_A_LIMIT_OFFSET 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_A_TLB_PTE 0x0040104C /* RW-4R */ -#define NV_PGRAPH_DMA_A_TLB_PTE_ACCESS 1:1 /* RWXVF */ -#define NV_PGRAPH_DMA_A_TLB_PTE_ACCESS_READ_ONLY 0x00000000 /* RW--V */ -#define NV_PGRAPH_DMA_A_TLB_PTE_ACCESS_READ_WRITE 0x00000001 /* RW--V */ -#define NV_PGRAPH_DMA_A_TLB_PTE_FRAME_ADDRESS 31:12 /* RWXUF */ -#define NV_PGRAPH_DMA_A_TLB_TAG 0x00401050 /* RW-4R */ -#define NV_PGRAPH_DMA_A_TLB_TAG_ADDRESS 31:12 /* RWXUF */ -#define NV_PGRAPH_DMA_A_ADJ_OFFSET 0x00401054 /* RW-4R */ -#define NV_PGRAPH_DMA_A_ADJ_OFFSET_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_A_OFFSET 0x00401058 /* RW-4R */ -#define NV_PGRAPH_DMA_A_OFFSET_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_A_SIZE 0x0040105C /* RW-4R */ -#define NV_PGRAPH_DMA_A_SIZE_VALUE 24:0 /* RWXUF */ -#define NV_PGRAPH_DMA_A_Y_SIZE 0x00401060 /* RW-4R */ -#define NV_PGRAPH_DMA_A_Y_SIZE_VALUE 10:0 /* RWXUF */ -#define NV_PGRAPH_DMA_B_XLATE_INST 0x00401080 /* RW-4R */ -#define NV_PGRAPH_DMA_B_XLATE_INST_VALUE 15:0 /* RWXUF */ -#define NV_PGRAPH_DMA_B_CONTROL 0x00401084 /* RW-4R */ -#define NV_PGRAPH_DMA_B_CONTROL_PAGE_TABLE 12:12 /* RWIVF */ -#define NV_PGRAPH_DMA_B_CONTROL_PAGE_TABLE_NOT_PRESENT 0x00000000 /* RWI-V */ -#define NV_PGRAPH_DMA_B_CONTROL_PAGE_TABLE_PRESENT 0x00000001 /* RW--V */ -#define NV_PGRAPH_DMA_B_CONTROL_PAGE_ENTRY 13:13 /* RWXVF */ -#define NV_PGRAPH_DMA_B_CONTROL_PAGE_ENTRY_NOT_LINEAR 0x00000000 /* RW--V */ -#define NV_PGRAPH_DMA_B_CONTROL_PAGE_ENTRY_LINEAR 0x00000001 /* RW--V */ -#define NV_PGRAPH_DMA_B_CONTROL_TARGET_NODE 17:16 /* RWXUF */ -#define NV_PGRAPH_DMA_B_CONTROL_TARGET_NODE_NVM 0x00000000 /* RW--V */ -#define NV_PGRAPH_DMA_B_CONTROL_TARGET_NODE_PCI 0x00000002 /* RW--V */ -#define NV_PGRAPH_DMA_B_CONTROL_TARGET_NODE_AGP 0x00000003 /* RW--V */ -#define NV_PGRAPH_DMA_B_CONTROL_ADJUST 31:20 /* RWXUF */ -#define NV_PGRAPH_DMA_B_LIMIT 0x00401088 /* RW-4R */ -#define NV_PGRAPH_DMA_B_LIMIT_OFFSET 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_B_TLB_PTE 0x0040108C /* RW-4R */ -#define NV_PGRAPH_DMA_B_TLB_PTE_ACCESS 1:1 /* RWXVF */ -#define NV_PGRAPH_DMA_B_TLB_PTE_ACCESS_READ_ONLY 0x00000000 /* RW--V */ -#define NV_PGRAPH_DMA_B_TLB_PTE_ACCESS_READ_WRITE 0x00000001 /* RW--V */ -#define NV_PGRAPH_DMA_B_TLB_PTE_FRAME_ADDRESS 31:12 /* RWXUF */ -#define NV_PGRAPH_DMA_B_TLB_TAG 0x00401090 /* RW-4R */ -#define NV_PGRAPH_DMA_B_TLB_TAG_ADDRESS 31:12 /* RWXUF */ -#define NV_PGRAPH_DMA_B_ADJ_OFFSET 0x00401094 /* RW-4R */ -#define NV_PGRAPH_DMA_B_ADJ_OFFSET_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_B_OFFSET 0x00401098 /* RW-4R */ -#define NV_PGRAPH_DMA_B_OFFSET_VALUE 31:0 /* RWXUF */ -#define NV_PGRAPH_DMA_B_SIZE 0x0040109C /* RW-4R */ -#define NV_PGRAPH_DMA_B_SIZE_VALUE 24:0 /* RWXUF */ -#define NV_PGRAPH_DMA_B_Y_SIZE 0x004010A0 /* RW-4R */ -#define NV_PGRAPH_DMA_B_Y_SIZE_VALUE 10:0 /* RWXUF */ - -/* Framebuffer registers */ -#define NV_PFB 0x00100FFF:0x00100000 /* RW--D */ -#define NV_PFB_BOOT_0 0x00100000 /* RW-4R */ -#define NV_PFB_BOOT_0_RAM_AMOUNT 1:0 /* RW-VF */ -#define NV_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 /* RW--V */ -#define NV_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001 /* RW--V */ -#define NV_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002 /* RW--V */ -#define NV_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003 /* RW--V */ -#define NV_PFB_BOOT_0_RAM_WIDTH_128 2:2 /* RW-VF */ -#define NV_PFB_BOOT_0_RAM_WIDTH_128_OFF 0x00000000 /* RW--V */ -#define NV_PFB_BOOT_0_RAM_WIDTH_128_ON 0x00000001 /* RW--V */ -#define NV_PFB_BOOT_0_RAM_TYPE 4:3 /* RW-VF */ -#define NV_PFB_BOOT_0_RAM_TYPE_256K 0x00000000 /* RW--V */ -#define NV_PFB_BOOT_0_RAM_TYPE_512K_2BANK 0x00000001 /* RW--V */ -#define NV_PFB_BOOT_0_RAM_TYPE_512K_4BANK 0x00000002 /* RW--V */ -#define NV_PFB_BOOT_0_RAM_TYPE_1024K_2BANK 0x00000003 /* RW--V */ -#define NV_PFB_CONFIG_0 0x00100200 /* RW-4R */ -#define NV_PFB_CONFIG_0_TYPE 14:0 /* RWIVF */ -#define NV_PFB_CONFIG_0_TYPE_OLD1024_FIXED_8BPP 0x00000120 /* RW--V */ -#define NV_PFB_CONFIG_0_TYPE_OLD1024_FIXED_16BPP 0x00000220 /* RW--V */ -#define NV_PFB_CONFIG_0_TYPE_OLD1024_FIXED_32BPP 0x00000320 /* RW--V */ -#define NV_PFB_CONFIG_0_TYPE_OLD1024_VAR_8BPP 0x00004120 /* RW--V */ -#define NV_PFB_CONFIG_0_TYPE_OLD1024_VAR_16BPP 0x00004220 /* RW--V */ -#define NV_PFB_CONFIG_0_TYPE_OLD1024_VAR_32BPP 0x00004320 /* RW--V */ -#define NV_PFB_CONFIG_0_TYPE_TETRIS 0x00002000 /* RW--V */ -#define NV_PFB_CONFIG_0_TYPE_NOTILING 0x00001114 /* RWI-V */ -#define NV_PFB_CONFIG_0_TETRIS_MODE 17:15 /* RWI-F */ -#define NV_PFB_CONFIG_0_TETRIS_MODE_PASS 0x00000000 /* RWI-V */ -#define NV_PFB_CONFIG_0_TETRIS_MODE_1 0x00000001 /* RW--V */ -#define NV_PFB_CONFIG_0_TETRIS_MODE_2 0x00000002 /* RW--V */ -#define NV_PFB_CONFIG_0_TETRIS_MODE_3 0x00000003 /* RW--V */ -#define NV_PFB_CONFIG_0_TETRIS_MODE_4 0x00000004 /* RW--V */ -#define NV_PFB_CONFIG_0_TETRIS_MODE_5 0x00000005 /* RW--V */ -#define NV_PFB_CONFIG_0_TETRIS_MODE_6 0x00000006 /* RW--V */ -#define NV_PFB_CONFIG_0_TETRIS_MODE_7 0x00000007 /* RW--V */ -#define NV_PFB_CONFIG_0_TETRIS_SHIFT 19:18 /* RWI-F */ -#define NV_PFB_CONFIG_0_TETRIS_SHIFT_0 0x00000000 /* RWI-V */ -#define NV_PFB_CONFIG_0_TETRIS_SHIFT_1 0x00000001 /* RW--V */ -#define NV_PFB_CONFIG_0_TETRIS_SHIFT_2 0x00000002 /* RW--V */ -#define NV_PFB_CONFIG_0_BANK_SWAP 22:20 /* RWI-F */ -#define NV_PFB_CONFIG_0_BANK_SWAP_OFF 0x00000000 /* RWI-V */ -#define NV_PFB_CONFIG_0_BANK_SWAP_1M 0x00000001 /* RW--V */ -#define NV_PFB_CONFIG_0_BANK_SWAP_2M 0x00000005 /* RW--V */ -#define NV_PFB_CONFIG_0_BANK_SWAP_4M 0x00000007 /* RW--V */ -#define NV_PFB_CONFIG_0_UNUSED 23:23 /* RW-VF */ -#define NV_PFB_CONFIG_0_SCRAMBLE_EN 29:29 /* RWIVF */ -#define NV_PFB_CONFIG_0_SCRAMBLE_EN_INIT 0x00000000 /* RW--V */ -#define NV_PFB_CONFIG_0_SCRAMBLE_ACTIVE 0x00000001 /* RW--V */ -#define NV_PFB_CONFIG_0_PRAMIN_WR 28:28 /* RWIVF */ -#define NV_PFB_CONFIG_0_PRAMIN_WR_INIT 0x00000000 /* RW--V */ -#define NV_PFB_CONFIG_0_PRAMIN_WR_DISABLED 0x00000001 /* RW--V */ -#define NV_PFB_CONFIG_0_PRAMIN_WR_MASK 27:24 /* RWIVF */ -#define NV_PFB_CONFIG_0_PRAMIN_WR_MASK_INIT 0x00000000 /* RWI-V */ -#define NV_PFB_CONFIG_0_PRAMIN_WR_MASK_CLEAR 0x0000000f /* RWI-V */ -#define NV_PFB_CONFIG_1 0x00100204 /* RW-4R */ -#define NV_PFB_RTL 0x00100300 /* RW-4R */ -#define NV_PFB_RTL_H 0:0 /* RWIUF */ -#define NV_PFB_RTL_H_DEFAULT 0x00000000 /* RWI-V */ -#define NV_PFB_RTL_MC 1:1 /* RWIUF */ -#define NV_PFB_RTL_MC_DEFAULT 0x00000000 /* RWI-V */ -#define NV_PFB_RTL_V 2:2 /* RWIUF */ -#define NV_PFB_RTL_V_DEFAULT 0x00000000 /* RWI-V */ -#define NV_PFB_RTL_G 3:3 /* RWIUF */ -#define NV_PFB_RTL_G_DEFAULT 0x00000000 /* RWI-V */ -#define NV_PFB_RTL_GB 4:4 /* RWIUF */ -#define NV_PFB_RTL_GB_DEFAULT 0x00000000 /* RWI-V */ -#define NV_PFB_CONFIG_0_RESOLUTION 5:0 /* RWIVF */ -#define NV_PFB_CONFIG_0_RESOLUTION_320_PIXELS 0x0000000a /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_400_PIXELS 0x0000000d /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_480_PIXELS 0x0000000f /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_512_PIXELS 0x00000010 /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_640_PIXELS 0x00000014 /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_800_PIXELS 0x00000019 /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_960_PIXELS 0x0000001e /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_1024_PIXELS 0x00000020 /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_1152_PIXELS 0x00000024 /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_1280_PIXELS 0x00000028 /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_1600_PIXELS 0x00000032 /* RW--V */ -#define NV_PFB_CONFIG_0_RESOLUTION_DEFAULT 0x00000014 /* RWI-V */ -#define NV_PFB_CONFIG_0_PIXEL_DEPTH 9:8 /* RWIVF */ -#define NV_PFB_CONFIG_0_PIXEL_DEPTH_8_BITS 0x00000001 /* RW--V */ -#define NV_PFB_CONFIG_0_PIXEL_DEPTH_16_BITS 0x00000002 /* RW--V */ -#define NV_PFB_CONFIG_0_PIXEL_DEPTH_32_BITS 0x00000003 /* RW--V */ -#define NV_PFB_CONFIG_0_PIXEL_DEPTH_DEFAULT 0x00000001 /* RWI-V */ -#define NV_PFB_CONFIG_0_TILING 12:12 /* RWIVF */ -#define NV_PFB_CONFIG_0_TILING_ENABLED 0x00000000 /* RW--V */ -#define NV_PFB_CONFIG_0_TILING_DISABLED 0x00000001 /* RWI-V */ -#define NV_PFB_CONFIG_1_SGRAM100 3:3 /* RWIVF */ -#define NV_PFB_CONFIG_1_SGRAM100_ENABLED 0x00000000 /* RWI-V */ -#define NV_PFB_CONFIG_1_SGRAM100_DISABLED 0x00000001 /* RW--V */ -#define NV_PFB_DEBUG_0_CKE_ALWAYSON 29:29 /* RWIVF */ -#define NV_PFB_DEBUG_0_CKE_ALWAYSON_OFF 0x00000000 /* RW--V */ -#define NV_PFB_DEBUG_0_CKE_ALWAYSON_ON 0x00000001 /* RWI-V */ - -#define NV_PEXTDEV 0x00101FFF:0x00101000 /* RW--D */ -#define NV_PEXTDEV_BOOT_0 0x00101000 /* R--4R */ -#define NV_PEXTDEV_BOOT_0_STRAP_BUS_SPEED 0:0 /* R-XVF */ -#define NV_PEXTDEV_BOOT_0_STRAP_BUS_SPEED_33MHZ 0x00000000 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_BUS_SPEED_66MHZ 0x00000001 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_SUB_VENDOR 1:1 /* R-XVF */ -#define NV_PEXTDEV_BOOT_0_STRAP_SUB_VENDOR_NO_BIOS 0x00000000 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_SUB_VENDOR_BIOS 0x00000001 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE 3:2 /* R-XVF */ -#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE_SGRAM_256K 0x00000000 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE_SGRAM_512K_2BANK 0x00000001 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE_SGRAM_512K_4BANK 0x00000002 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_RAM_TYPE_1024K_2BANK 0x00000003 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_RAM_WIDTH 4:4 /* R-XVF */ -#define NV_PEXTDEV_BOOT_0_STRAP_RAM_WIDTH_64 0x00000000 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_RAM_WIDTH_128 0x00000001 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_BUS_TYPE 5:5 /* R-XVF */ -#define NV_PEXTDEV_BOOT_0_STRAP_BUS_TYPE_PCI 0x00000000 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_BUS_TYPE_AGP 0x00000001 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_CRYSTAL 6:6 /* R-XVF */ -#define NV_PEXTDEV_BOOT_0_STRAP_CRYSTAL_13500K 0x00000000 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_CRYSTAL_14318180 0x00000001 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE 8:7 /* R-XVF */ -#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE_SECAM 0x00000000 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE_NTSC 0x00000001 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE_PAL 0x00000002 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_TVMODE_DISABLED 0x00000003 /* R---V */ -#define NV_PEXTDEV_BOOT_0_STRAP_OVERWRITE 11:11 /* RWIVF */ -#define NV_PEXTDEV_BOOT_0_STRAP_OVERWRITE_DISABLED 0x00000000 /* RWI-V */ -#define NV_PEXTDEV_BOOT_0_STRAP_OVERWRITE_ENABLED 0x00000001 /* RW--V */ - -/* Extras */ -#define NV_PRAMIN 0x007FFFFF:0x00700000 /* RW--M */ -/*#define NV_PRAMIN 0x00FFFFFF:0x00C00000*/ -#define NV_PNVM 0x01FFFFFF:0x01000000 /* RW--M */ -/*#define NV_PNVM 0x00BFFFFF:0x00800000*/ -#define NV_CHAN0 0x0080ffff:0x00800000 - -/* FIFO subchannels */ -#define NV_UROP 0x43 -#define NV_UCHROMA 0x57 -#define NV_UCLIP 0x19 -#define NV_UPATT 0x18 -#define NV_ULIN 0x5C -#define NV_UTRI 0x5D -#define NV_URECT 0x5E -#define NV_UBLIT 0x5F -#define NV_UGLYPH 0x4B - -#endif /*__NV4REF_H__*/ - diff --git a/drivers/video/riva/nv_driver.c b/drivers/video/riva/nv_driver.c index be630a0..a110268 100644 --- a/drivers/video/riva/nv_driver.c +++ b/drivers/video/riva/nv_driver.c @@ -231,12 +231,14 @@ unsigned long riva_get_memlen(struct riva_par *par) case NV_ARCH_30: if(chipset == NV_CHIP_IGEFORCE2) { - dev = pci_find_slot(0, 1); + dev = pci_get_bus_and_slot(0, 1); pci_read_config_dword(dev, 0x7C, &amt); + pci_dev_put(dev); memlen = (((amt >> 6) & 31) + 1) * 1024; } else if (chipset == NV_CHIP_0x01F0) { - dev = pci_find_slot(0, 1); + dev = pci_get_bus_and_slot(0, 1); pci_read_config_dword(dev, 0x84, &amt); + pci_dev_put(dev); memlen = (((amt >> 4) & 127) + 1) * 1024; } else { switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) & diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c index e0b8c52..70bfd78 100644 --- a/drivers/video/riva/riva_hw.c +++ b/drivers/video/riva/riva_hw.c @@ -1118,8 +1118,9 @@ static void nForceUpdateArbitrationSettings unsigned int uMClkPostDiv; struct pci_dev *dev; - dev = pci_find_slot(0, 3); + dev = pci_get_bus_and_slot(0, 3); pci_read_config_dword(dev, 0x6C, &uMClkPostDiv); + pci_dev_put(dev); uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf; if(!uMClkPostDiv) uMClkPostDiv = 4; @@ -1132,8 +1133,9 @@ static void nForceUpdateArbitrationSettings sim_data.enable_video = 0; sim_data.enable_mp = 0; - dev = pci_find_slot(0, 1); + dev = pci_get_bus_and_slot(0, 1); pci_read_config_dword(dev, 0x7C, &sim_data.memory_type); + pci_dev_put(dev); sim_data.memory_type = (sim_data.memory_type >> 12) & 1; sim_data.memory_width = 64; @@ -2112,12 +2114,14 @@ static void nv10GetConfig * Fill in chip configuration. */ if(chipset == NV_CHIP_IGEFORCE2) { - dev = pci_find_slot(0, 1); + dev = pci_get_bus_and_slot(0, 1); pci_read_config_dword(dev, 0x7C, &amt); + pci_dev_put(dev); chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024; } else if(chipset == NV_CHIP_0x01F0) { - dev = pci_find_slot(0, 1); + dev = pci_get_bus_and_slot(0, 1); pci_read_config_dword(dev, 0x84, &amt); + pci_dev_put(dev); chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024; } else { switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) & 0x000000FF) diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c index 0405e83..a0e22ac 100644 --- a/drivers/video/riva/rivafb-i2c.c +++ b/drivers/video/riva/rivafb-i2c.c @@ -70,8 +70,6 @@ static int riva_gpio_getscl(void* data) if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x04) val = 1; - val = VGA_RD08(par->riva.PCIO, 0x3d5); - return val; } @@ -88,13 +86,16 @@ static int riva_gpio_getsda(void* data) return val; } -static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name) +static int __devinit riva_setup_i2c_bus(struct riva_i2c_chan *chan, + const char *name, + unsigned int i2c_class) { int rc; strcpy(chan->adapter.name, name); chan->adapter.owner = THIS_MODULE; chan->adapter.id = I2C_HW_B_RIVA; + chan->adapter.class = i2c_class; chan->adapter.algo_data = &chan->algo; chan->adapter.dev.parent = &chan->par->pdev->dev; chan->algo.setsda = riva_gpio_setsda; @@ -124,42 +125,38 @@ static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name) return rc; } -void riva_create_i2c_busses(struct riva_par *par) +void __devinit riva_create_i2c_busses(struct riva_par *par) { - par->bus = 3; - par->chan[0].par = par; par->chan[1].par = par; par->chan[2].par = par; - par->chan[0].ddc_base = 0x3e; - par->chan[1].ddc_base = 0x36; + par->chan[0].ddc_base = 0x36; + par->chan[1].ddc_base = 0x3e; par->chan[2].ddc_base = 0x50; - riva_setup_i2c_bus(&par->chan[0], "BUS1"); - riva_setup_i2c_bus(&par->chan[1], "BUS2"); - riva_setup_i2c_bus(&par->chan[2], "BUS3"); + riva_setup_i2c_bus(&par->chan[0], "BUS1", I2C_CLASS_HWMON); + riva_setup_i2c_bus(&par->chan[1], "BUS2", 0); + riva_setup_i2c_bus(&par->chan[2], "BUS3", 0); } void riva_delete_i2c_busses(struct riva_par *par) { - if (par->chan[0].par) - i2c_del_adapter(&par->chan[0].adapter); - par->chan[0].par = NULL; + int i; - if (par->chan[1].par) - i2c_del_adapter(&par->chan[1].adapter); - par->chan[1].par = NULL; - - if (par->chan[2].par) - i2c_del_adapter(&par->chan[2].adapter); - par->chan[2].par = NULL; + for (i = 0; i < 3; i++) { + if (!par->chan[i].par) + continue; + i2c_del_adapter(&par->chan[i].adapter); + par->chan[i].par = NULL; + } } -int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid) +int __devinit riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid) { u8 *edid = NULL; - edid = fb_ddc_read(&par->chan[conn-1].adapter); + if (par->chan[conn].par) + edid = fb_ddc_read(&par->chan[conn].adapter); if (out_edid) *out_edid = edid; diff --git a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h index 48ead6d..d9f107b 100644 --- a/drivers/video/riva/rivafb.h +++ b/drivers/video/riva/rivafb.h @@ -4,7 +4,6 @@ #include <linux/fb.h> #include <video/vga.h> #include <linux/i2c.h> -#include <linux/i2c-id.h> #include <linux/i2c-algo-bit.h> #include "riva_hw.h" @@ -61,7 +60,6 @@ struct riva_par { Bool SecondCRTC; int FlatPanel; struct pci_dev *pdev; - int bus; int cursor_reset; #ifdef CONFIG_MTRR struct { int vram; int vram_valid; } mtrr; diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 3091b20..d117358 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -65,7 +65,7 @@ static const struct svga_fb_format s3fb_formats[] = { static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, - 60000, 240000, 14318}; + 35000, 240000, 14318}; static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; @@ -164,7 +164,7 @@ MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, defau static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) { const u8 *font = map->data; - u8* fb = (u8 *) info->screen_base; + u8 __iomem *fb = (u8 __iomem *) info->screen_base; int i, c; if ((map->width != 8) || (map->height != 16) || @@ -177,20 +177,19 @@ static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) fb += 2; for (i = 0; i < map->height; i++) { for (c = 0; c < map->length; c++) { - fb[c * 4] = font[c * map->height + i]; + fb_writeb(font[c * map->height + i], fb + c * 4); } fb += 1024; } } - - static struct fb_tile_ops s3fb_tile_ops = { .fb_settile = svga_settile, .fb_tilecopy = svga_tilecopy, .fb_tilefill = svga_tilefill, .fb_tileblit = svga_tileblit, .fb_tilecursor = svga_tilecursor, + .fb_get_tilemax = svga_get_tilemax, }; static struct fb_tile_ops s3fb_fast_tile_ops = { @@ -199,6 +198,7 @@ static struct fb_tile_ops s3fb_fast_tile_ops = { .fb_tilefill = svga_tilefill, .fb_tileblit = svga_tileblit, .fb_tilecursor = svga_tilecursor, + .fb_get_tilemax = svga_get_tilemax, }; @@ -326,8 +326,13 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) { u16 m, n, r; u8 regval; + int rv; - svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node); + rv = svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node); + if (rv < 0) { + printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); + return; + } /* Set VGA misc register */ regval = vga_r(NULL, VGA_MIS_R); @@ -449,6 +454,10 @@ static int s3fb_set_par(struct fb_info *info) info->flags &= ~FBINFO_MISC_TILEBLITTING; info->tileops = NULL; + /* in 4bpp supports 8p wide tiles only, any tiles otherwise */ + info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0); + info->pixmap.blit_y = ~(u32)0; + offset_value = (info->var.xres_virtual * bpp) / 64; screen_size = info->var.yres_virtual * info->fix.line_length; } else { @@ -458,6 +467,10 @@ static int s3fb_set_par(struct fb_info *info) info->flags |= FBINFO_MISC_TILEBLITTING; info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops; + /* supports 8x16 tiles only */ + info->pixmap.blit_x = 1 << (8 - 1); + info->pixmap.blit_y = 1 << (16 - 1); + offset_value = info->var.xres_virtual / 16; screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64; } @@ -656,7 +669,7 @@ static int s3fb_set_par(struct fb_info *info) value = ((value * hmul) / 8) - 5; vga_wcrt(NULL, 0x3C, (value + 1) / 2); - memset((u8*)info->screen_base, 0x00, screen_size); + memset_io(info->screen_base, 0x00, screen_size); /* Device and screen back on */ svga_wcrt_mask(0x17, 0x80, 0x80); svga_wseq_mask(0x01, 0x00, 0x20); @@ -699,7 +712,7 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, break; case 16: if (regno >= 16) - return -EINVAL; + return 0; if (fb->var.green.length == 5) ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) | @@ -712,9 +725,9 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, case 24: case 32: if (regno >= 16) - return -EINVAL; + return 0; - ((u32*)fb->pseudo_palette)[regno] = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) | + ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8); break; default: @@ -767,12 +780,6 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) unsigned int offset; - /* Validate the offsets */ - if ((var->xoffset + var->xres) > var->xres_virtual) - return -EINVAL; - if ((var->yoffset + var->yres) > var->yres_virtual) - return -EINVAL; - /* Calculate the offset */ if (var->bits_per_pixel == 0) { offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); @@ -805,6 +812,7 @@ static struct fb_ops s3fb_ops = { .fb_fillrect = s3fb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = s3fb_imageblit, + .fb_get_caps = svga_get_caps, }; /* ------------------------------------------------------------------------- */ @@ -1061,6 +1069,7 @@ static int s3_pci_resume(struct pci_dev* dev) { struct fb_info *info = pci_get_drvdata(dev); struct s3fb_info *par = info->par; + int err; dev_info(&(dev->dev), "resume\n"); @@ -1075,7 +1084,13 @@ static int s3_pci_resume(struct pci_dev* dev) pci_set_power_state(dev, PCI_D0); pci_restore_state(dev); - pci_enable_device(dev); + err = pci_enable_device(dev); + if (err) { + mutex_unlock(&(par->open_lock)); + release_console_sem(); + dev_err(&(dev->dev), "error %d enabling device for resume\n", err); + return err; + } pci_set_master(dev); s3fb_set_par(info); diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 8db066c..35c1ce6 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -41,10 +41,6 @@ #define SAVAGE4_I2C_SCL_IN 0x00000008 #define SAVAGE4_I2C_SDA_IN 0x00000010 -#define SET_CR_IX(base, val) writeb((val), base + 0x8000 + VGA_CR_IX) -#define SET_CR_DATA(base, val) writeb((val), base + 0x8000 + VGA_CR_DATA) -#define GET_CR_DATA(base) readb(base + 0x8000 + VGA_CR_DATA) - static void savage4_gpio_setscl(void *data, int val) { struct savagefb_i2c_chan *chan = data; @@ -92,15 +88,15 @@ static void prosavage_gpio_setscl(void* data, int val) struct savagefb_i2c_chan *chan = data; u32 r; - SET_CR_IX(chan->ioaddr, chan->reg); - r = GET_CR_DATA(chan->ioaddr); + r = VGArCR(chan->reg, chan->par); r |= PROSAVAGE_I2C_ENAB; if (val) { r |= PROSAVAGE_I2C_SCL_OUT; } else { r &= ~PROSAVAGE_I2C_SCL_OUT; } - SET_CR_DATA(chan->ioaddr, r); + + VGAwCR(chan->reg, r, chan->par); } static void prosavage_gpio_setsda(void* data, int val) @@ -108,31 +104,29 @@ static void prosavage_gpio_setsda(void* data, int val) struct savagefb_i2c_chan *chan = data; unsigned int r; - SET_CR_IX(chan->ioaddr, chan->reg); - r = GET_CR_DATA(chan->ioaddr); + r = VGArCR(chan->reg, chan->par); r |= PROSAVAGE_I2C_ENAB; if (val) { r |= PROSAVAGE_I2C_SDA_OUT; } else { r &= ~PROSAVAGE_I2C_SDA_OUT; } - SET_CR_DATA(chan->ioaddr, r); + + VGAwCR(chan->reg, r, chan->par); } static int prosavage_gpio_getscl(void* data) { struct savagefb_i2c_chan *chan = data; - SET_CR_IX(chan->ioaddr, chan->reg); - return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SCL_IN)); + return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SCL_IN) ? 1 : 0; } static int prosavage_gpio_getsda(void* data) { struct savagefb_i2c_chan *chan = data; - SET_CR_IX(chan->ioaddr, chan->reg); - return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN)); + return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SDA_IN) ? 1 : 0; } static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h index e648a6c..8bfdfc3 100644 --- a/drivers/video/savage/savagefb.h +++ b/drivers/video/savage/savagefb.h @@ -15,6 +15,8 @@ #include <linux/i2c.h> #include <linux/i2c-id.h> #include <linux/i2c-algo-bit.h> +#include <linux/mutex.h> +#include <video/vga.h> #include "../edid.h" #ifdef SAVAGEFB_DEBUG @@ -189,8 +191,12 @@ struct savagefb_par { struct savagefb_i2c_chan chan; struct savage_reg state; struct savage_reg save; + struct savage_reg initial; + struct vgastate vgastate; + struct mutex open_lock; unsigned char *edid; u32 pseudo_palette[16]; + u32 open_count; int paletteEnabled; int pm_state; int display_type; @@ -203,7 +209,7 @@ struct savagefb_par { int clock[4]; int MCLK, REFCLK, LCDclk; struct { - u8 __iomem *vbase; + void __iomem *vbase; u32 pbase; u32 len; #ifdef CONFIG_MTRR @@ -212,7 +218,7 @@ struct savagefb_par { } video; struct { - volatile u8 __iomem *vbase; + void __iomem *vbase; u32 pbase; u32 len; } mmio; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 0166ec2..3d7507a 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -1623,8 +1623,46 @@ static void savagefb_restore_state(struct fb_info *info) savagefb_blank(FB_BLANK_UNBLANK, info); } +static int savagefb_open(struct fb_info *info, int user) +{ + struct savagefb_par *par = info->par; + + mutex_lock(&par->open_lock); + + if (!par->open_count) { + memset(&par->vgastate, 0, sizeof(par->vgastate)); + par->vgastate.flags = VGA_SAVE_CMAP | VGA_SAVE_FONTS | + VGA_SAVE_MODE; + par->vgastate.vgabase = par->mmio.vbase + 0x8000; + save_vga(&par->vgastate); + savage_get_default_par(par, &par->initial); + } + + par->open_count++; + mutex_unlock(&par->open_lock); + return 0; +} + +static int savagefb_release(struct fb_info *info, int user) +{ + struct savagefb_par *par = info->par; + + mutex_lock(&par->open_lock); + + if (par->open_count == 1) { + savage_set_default_par(par, &par->initial); + restore_vga(&par->vgastate); + } + + par->open_count--; + mutex_unlock(&par->open_lock); + return 0; +} + static struct fb_ops savagefb_ops = { .owner = THIS_MODULE, + .fb_open = savagefb_open, + .fb_release = savagefb_release, .fb_check_var = savagefb_check_var, .fb_set_par = savagefb_set_par, .fb_setcolreg = savagefb_setcolreg, @@ -2173,6 +2211,7 @@ static int __devinit savagefb_probe(struct pci_dev* dev, if (!info) return -ENOMEM; par = info->par; + mutex_init(&par->open_lock); err = pci_enable_device(dev); if (err) goto failed_enable; diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h index d048bd3..c149278 100644 --- a/drivers/video/sis/osdef.h +++ b/drivers/video/sis/osdef.h @@ -58,9 +58,6 @@ #define SIS_LINUX_KERNEL /* Linux kernel framebuffer */ #undef SIS_XORG_XF86 /* XFree86/X.org */ -#undef SIS_LINUX_KERNEL_24 -#undef SIS_LINUX_KERNEL_26 - #ifdef OutPortByte #undef OutPortByte #endif @@ -100,8 +97,6 @@ #define SIS315H #endif -#define SIS_LINUX_KERNEL_26 - #if !defined(SIS300) && !defined(SIS315H) #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set #warning sisfb will not work! diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h index 7d5ee21..d5e2d9c 100644 --- a/drivers/video/sis/sis.h +++ b/drivers/video/sis/sis.h @@ -27,11 +27,7 @@ #include <linux/version.h> #include "osdef.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #include <video/sisfb.h> -#else -#include <linux/sisfb.h> -#endif #include "vgatypes.h" #include "vstruct.h" @@ -40,33 +36,17 @@ #define VER_MINOR 8 #define VER_LEVEL 9 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #include <linux/spinlock.h> -#define SIS_PCI_GET_CLASS(a, b) pci_get_class(a, b) -#define SIS_PCI_GET_DEVICE(a,b,c) pci_get_device(a,b,c) -#define SIS_PCI_GET_SLOT(a,b) pci_get_slot(a,b) -#define SIS_PCI_PUT_DEVICE(a) pci_dev_put(a) + #ifdef CONFIG_COMPAT #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10) #include <linux/ioctl32.h> #define SIS_OLD_CONFIG_COMPAT #else -#include <linux/smp_lock.h> #define SIS_NEW_CONFIG_COMPAT #endif #endif /* CONFIG_COMPAT */ -#else /* 2.4 */ -#define SIS_PCI_GET_CLASS(a, b) pci_find_class(a, b) -#define SIS_PCI_GET_DEVICE(a,b,c) pci_find_device(a,b,c) -#define SIS_PCI_GET_SLOT(a,b) pci_find_slot(a,b) -#define SIS_PCI_PUT_DEVICE(a) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19) -#ifdef __x86_64__ /* Shouldn't we check for CONFIG_IA32_EMULATION here? */ -#include <asm/ioctl32.h> -#define SIS_OLD_CONFIG_COMPAT -#endif -#endif -#endif /* 2.4 */ + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) #define SIS_IOTYPE1 void __iomem #define SIS_IOTYPE2 __iomem @@ -498,26 +478,8 @@ struct sis_video_info { struct fb_var_screeninfo default_var; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) struct fb_fix_screeninfo sisfb_fix; u32 pseudo_palette[17]; -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - struct display sis_disp; - struct display_switch sisfb_sw; - struct { - u16 red, green, blue, pad; - } sis_palette[256]; - union { -#ifdef FBCON_HAS_CFB16 - u16 cfb16[16]; -#endif -#ifdef FBCON_HAS_CFB32 - u32 cfb32[16]; -#endif - } sis_fbcon_cmap; -#endif struct sisfb_monitor { u16 hmin; @@ -538,10 +500,6 @@ struct sis_video_info { int mni; /* Mode number index */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - int currcon; -#endif - unsigned long video_size; unsigned long video_base; unsigned long mmio_size; @@ -578,9 +536,6 @@ struct sis_video_info { int sisfb_tvplug; int sisfb_tvstd; int sisfb_nocrt2rate; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - int sisfb_inverse; -#endif u32 heapstart; /* offset */ SIS_IOTYPE1 *sisfb_heap_start; /* address */ @@ -646,9 +601,7 @@ struct sis_video_info { int modechanged; unsigned char modeprechange; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) u8 sisfb_lastrates[128]; -#endif int newrom; int haveXGIROM; diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 01197d7..a30e1e1 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -37,7 +37,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> -#include <linux/smp_lock.h> #include <linux/spinlock.h> #include <linux/errno.h> #include <linux/string.h> @@ -1948,7 +1947,7 @@ sisfb_get_northbridge(int basechipid) default: return NULL; } for(i = 0; i < nbridgenum; i++) { - if((pdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, + if((pdev = pci_get_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break; } @@ -4613,9 +4612,9 @@ sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev, unsigned short temp; int ret = 0; - while((pdev = SIS_PCI_GET_CLASS(PCI_CLASS_BRIDGE_HOST, pdev))) { + while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) { temp = pdev->vendor; - SIS_PCI_PUT_DEVICE(pdev); + pci_dev_put(pdev); if(temp == pcivendor) { ret = 1; break; @@ -5154,24 +5153,24 @@ sisfb_post_xgi(struct pci_dev *pdev) if(reg & 0x80) v2 |= 0x80; v2 |= 0x01; - if((mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0730, NULL))) { - SIS_PCI_PUT_DEVICE(mypdev); + if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) { + pci_dev_put(mypdev); if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4)) v2 &= 0xf9; v2 |= 0x08; v1 &= 0xfe; } else { - mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0735, NULL); + mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL); if(!mypdev) - mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0645, NULL); + mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL); if(!mypdev) - mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0650, NULL); + mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL); if(mypdev) { pci_read_config_dword(mypdev, 0x94, ®d); regd &= 0xfffffeff; pci_write_config_dword(mypdev, 0x94, regd); v1 &= 0xfe; - SIS_PCI_PUT_DEVICE(mypdev); + pci_dev_put(mypdev); } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) { v1 &= 0xfe; } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) || @@ -5194,13 +5193,13 @@ sisfb_post_xgi(struct pci_dev *pdev) if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) ) setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01); - if((mypdev = SIS_PCI_GET_DEVICE(0x10de, 0x01e0, NULL))) { + if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) { /* TODO: set CR5f &0xf1 | 0x01 for version 6570 * of nforce 2 ROM */ if(0) setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01); - SIS_PCI_PUT_DEVICE(mypdev); + pci_dev_put(mypdev); } } @@ -5236,9 +5235,9 @@ sisfb_post_xgi(struct pci_dev *pdev) setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f); setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f); v1 = bios[0x501]; - if((mypdev = SIS_PCI_GET_DEVICE(0x8086, 0x2530, NULL))) { + if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) { v1 = 0xf0; - SIS_PCI_PUT_DEVICE(mypdev); + pci_dev_put(mypdev); } outSISIDXREG(SISCR, 0x77, v1); } @@ -5947,7 +5946,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if(!ivideo->sisvga_enabled) { if(pci_enable_device(pdev)) { - if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge); + if(ivideo->nbridge) pci_dev_put(ivideo->nbridge); pci_set_drvdata(pdev, NULL); kfree(sis_fb_info); return -EIO; @@ -5974,7 +5973,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) "requiring Chrontel/GPIO setup\n", mychswtable[i].vendorName, mychswtable[i].cardName); - ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL); + ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL); break; } i++; @@ -5984,7 +5983,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef CONFIG_FB_SIS_315 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) { - ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3)); + ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3)); } #endif @@ -6149,9 +6148,9 @@ error_1: release_mem_region(ivideo->video_base, ivideo->video_size); error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size); error_3: vfree(ivideo->bios_abase); if(ivideo->lpcdev) - SIS_PCI_PUT_DEVICE(ivideo->lpcdev); + pci_dev_put(ivideo->lpcdev); if(ivideo->nbridge) - SIS_PCI_PUT_DEVICE(ivideo->nbridge); + pci_dev_put(ivideo->nbridge); pci_set_drvdata(pdev, NULL); if(!ivideo->sisvga_enabled) pci_disable_device(pdev); @@ -6331,70 +6330,6 @@ error_3: vfree(ivideo->bios_abase); sisfb_set_vparms(ivideo); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - - /* ---------------- For 2.4: Now switch the mode ------------------ */ - - printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n", - ivideo->video_width, ivideo->video_height, ivideo->video_bpp, - ivideo->refresh_rate); - - /* Determine whether or not acceleration is to be - * used. Need to know before pre/post_set_mode() - */ - ivideo->accel = 0; - ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT; - if(ivideo->sisfb_accel) { - ivideo->accel = -1; - ivideo->default_var.accel_flags |= FB_ACCELF_TEXT; - } - - /* Now switch the mode */ - sisfb_pre_setmode(ivideo); - - if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) { - printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n", - ivideo->mode_no); - ret = -EINVAL; - iounmap(ivideo->mmio_vbase); - goto error_0; - } - - outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); - - sisfb_post_setmode(ivideo); - - /* Maximize regardless of sisfb_max at startup */ - ivideo->default_var.yres_virtual = 32767; - - /* Force reset of x virtual in crtc_to_var */ - ivideo->default_var.xres_virtual = 0; - - /* Copy mode timing to var */ - sisfb_crtc_to_var(ivideo, &ivideo->default_var); - - /* Find out about screen pitch */ - sisfb_calc_pitch(ivideo, &ivideo->default_var); - sisfb_set_pitch(ivideo); - - /* Init the accelerator (does nothing currently) */ - sisfb_initaccel(ivideo); - - /* Init some fbinfo entries */ - sis_fb_info->node = -1; - sis_fb_info->flags = FBINFO_FLAG_DEFAULT; - sis_fb_info->fbops = &sisfb_ops; - sis_fb_info->disp = &ivideo->sis_disp; - sis_fb_info->blank = &sisfb_blank; - sis_fb_info->switch_con = &sisfb_switch; - sis_fb_info->updatevar = &sisfb_update_var; - sis_fb_info->changevar = NULL; - strcpy(sis_fb_info->fontname, sisfb_fontname); - - sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info); - -#else /* --------- For 2.6: Setup a somewhat sane default var ------------ */ - printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n", ivideo->video_width, ivideo->video_height, ivideo->video_bpp, ivideo->refresh_rate); @@ -6454,7 +6389,6 @@ error_3: vfree(ivideo->bios_abase); sis_fb_info->pseudo_palette = ivideo->pseudo_palette; fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); -#endif /* 2.6 */ printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags); @@ -6564,10 +6498,10 @@ static void __devexit sisfb_remove(struct pci_dev *pdev) vfree(ivideo->bios_abase); if(ivideo->lpcdev) - SIS_PCI_PUT_DEVICE(ivideo->lpcdev); + pci_dev_put(ivideo->lpcdev); if(ivideo->nbridge) - SIS_PCI_PUT_DEVICE(ivideo->nbridge); + pci_dev_put(ivideo->nbridge); #ifdef CONFIG_MTRR /* Release MTRR region */ diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index bb96cb6..836a612 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -14,7 +14,7 @@ * of it. * * First the roles of struct fb_info and struct display have changed. Struct - * display will go away. The way the the new framebuffer console code will + * display will go away. The way the new framebuffer console code will * work is that it will act to translate data about the tty/console in * struct vc_data to data in a device independent way in struct fb_info. Then * various functions in struct fb_ops will be called to store the device @@ -51,6 +51,7 @@ #include <linux/delay.h> #include <linux/fb.h> #include <linux/init.h> +#include <linux/pci.h> /* * This is just simple sample code. @@ -60,6 +61,11 @@ */ /* + * Driver data + */ +static char *mode_option __devinitdata; + +/* * If your driver supports multiple boards, you should make the * below data types arrays, or allocate them dynamically (using kmalloc()). */ @@ -78,7 +84,7 @@ struct xxx_par; * if we don't use modedb. If we do use modedb see xxxfb_init how to use it * to get a fb_var_screeninfo. Otherwise define a default var as well. */ -static struct fb_fix_screeninfo xxxfb_fix __initdata = { +static struct fb_fix_screeninfo xxxfb_fix __devinitdata = { .id = "FB's name", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_PSEUDOCOLOR, @@ -142,7 +148,7 @@ int xxxfb_setup(char*); * * Returns negative errno on error, or zero on success. */ -static int xxxfb_open(const struct fb_info *info, int user) +static int xxxfb_open(struct fb_info *info, int user) { return 0; } @@ -161,7 +167,7 @@ static int xxxfb_open(const struct fb_info *info, int user) * * Returns negative errno on error, or zero on success. */ -static int xxxfb_release(const struct fb_info *info, int user) +static int xxxfb_release(struct fb_info *info, int user) { return 0; } @@ -278,7 +284,7 @@ static int xxxfb_set_par(struct fb_info *info) */ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, - const struct fb_info *info) + struct fb_info *info) { if (regno >= 256) /* no. of hw registers */ return -EINVAL; @@ -416,7 +422,7 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, * Returns negative errno on error, or zero on success. */ static int xxxfb_pan_display(struct fb_var_screeninfo *var, - const struct fb_info *info) + struct fb_info *info) { /* * If your hardware does not support panning, _do_ _not_ implement this @@ -454,7 +460,7 @@ static int xxxfb_pan_display(struct fb_var_screeninfo *var, * Return !0 for any modes that are unimplemented. * */ -static int xxxfb_blank(int blank_mode, const struct fb_info *info) +static int xxxfb_blank(int blank_mode, struct fb_info *info) { /* ... */ return 0; @@ -483,7 +489,7 @@ static int xxxfb_blank(int blank_mode, const struct fb_info *info) * depending on the rastering operation with the value of color which * is in the current color depth format. */ -void xxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region) +void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region) { /* Meaning of struct fb_fillrect * @@ -623,19 +629,6 @@ void xxxfb_rotate(struct fb_info *info, int angle) } /** - * xxxfb_poll - NOT a required function. The purpose of this - * function is to provide a way for some process - * to wait until a specific hardware event occurs - * for the framebuffer device. - * - * @info: frame buffer structure that represents a single frame buffer - * @wait: poll table where we store process that await a event. - */ -void xxxfb_poll(struct fb_info *info, poll_table *wait) -{ -} - -/** * xxxfb_sync - NOT a required function. Normally the accel engine * for a graphics card take a specific amount of time. * Often we have to wait for the accelerator to finish @@ -647,21 +640,49 @@ void xxxfb_poll(struct fb_info *info, poll_table *wait) * If the driver has implemented its own hardware-based drawing function, * implementing this function is highly recommended. */ -void xxxfb_sync(struct fb_info *info) +int xxxfb_sync(struct fb_info *info) { + return 0; } /* + * Frame buffer operations + */ + +static struct fb_ops xxxfb_ops = { + .owner = THIS_MODULE, + .fb_open = xxxfb_open, + .fb_read = xxxfb_read, + .fb_write = xxxfb_write, + .fb_release = xxxfb_release, + .fb_check_var = xxxfb_check_var, + .fb_set_par = xxxfb_set_par, + .fb_setcolreg = xxxfb_setcolreg, + .fb_blank = xxxfb_blank, + .fb_pan_display = xxxfb_pan_display, + .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ + .fb_copyarea = xxxfb_copyarea, /* Needed !!! */ + .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ + .fb_cursor = xxxfb_cursor, /* Optional !!! */ + .fb_rotate = xxxfb_rotate, + .fb_sync = xxxfb_sync, + .fb_ioctl = xxxfb_ioctl, + .fb_mmap = xxxfb_mmap, +}; + +/* ------------------------------------------------------------------------- */ + + /* * Initialization */ /* static int __init xxfb_probe (struct device *device) -- for platform devs */ -static int __init xxxfb_probe(struct pci_dev *dev, - const_struct pci_device_id *ent) +static int __devinit xxxfb_probe(struct pci_dev *dev, + const struct pci_device_id *ent) { struct fb_info *info; struct xxx_par *par; - struct device = &dev->dev; /* for pci drivers */ + struct device* device = &dev->dev; /* for pci drivers */ int cmap_len, retval; /* @@ -684,7 +705,7 @@ static int __init xxxfb_probe(struct pci_dev *dev, info->screen_base = framebuffer_virtual_memory; info->fbops = &xxxfb_ops; info->fix = xxxfb_fix; /* this will be the only time xxxfb_fix will be - * used, so mark it as __initdata + * used, so mark it as __devinitdata */ info->pseudo_palette = pseudo_palette; /* The pseudopalette is an * 16-member array @@ -760,7 +781,7 @@ static int __init xxxfb_probe(struct pci_dev *dev, * * NOTE: This field is currently unused. */ - info->pixmap.scan_align = 32 + info->pixmap.scan_align = 32; /***************************** End optional stage ***************************/ /* @@ -770,13 +791,13 @@ static int __init xxxfb_probe(struct pci_dev *dev, if (!mode_option) mode_option = "640x480@60"; - retval = fb_find_mode(info->var, info, mode_option, NULL, 0, NULL, 8); + retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); if (!retval || retval == 4) return -EINVAL; /* This has to been done !!! */ - fb_alloc_cmap(info->cmap, cmap_len, 0); + fb_alloc_cmap(&info->cmap, cmap_len, 0); /* * The following is done in the case of having hardware with a static @@ -811,34 +832,77 @@ static int __init xxxfb_probe(struct pci_dev *dev, /* * Cleanup */ -/* static void __exit xxxfb_remove(struct device *device) */ -static void __exit xxxfb_remove(struct pci_dev *dev) +/* static void __devexit xxxfb_remove(struct device *device) */ +static void __devexit xxxfb_remove(struct pci_dev *dev) { - struct fb_info *info = pci_get_drv_data(dev); - /* or dev_get_drv_data(device); */ + struct fb_info *info = pci_get_drvdata(dev); + /* or dev_get_drvdata(device); */ if (info) { unregister_framebuffer(info); - fb_dealloc_cmap(&info.cmap); + fb_dealloc_cmap(&info->cmap); /* ... */ framebuffer_release(info); } +} + +#ifdef CONFIG_PCI +#ifdef CONFIG_PM +/** + * xxxfb_suspend - Optional but recommended function. Suspend the device. + * @dev: PCI device + * @msg: the suspend event code. + * + * See Documentation/power/devices.txt for more information + */ +static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct xxxfb_par *par = info->par; + + /* suspend here */ + return 0; +} + +/** + * xxxfb_resume - Optional but recommended function. Resume the device. + * @dev: PCI device + * + * See Documentation/power/devices.txt for more information + */ +static int xxxfb_resume(struct pci_dev *dev) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct xxxfb_par *par = info->par; + /* resume here */ return 0; } +#else +#define xxxfb_suspend NULL +#define xxxfb_resume NULL +#endif /* CONFIG_PM */ + +static struct pci_device_id xxxfb_id_table[] = { + { PCI_VENDOR_ID_XXX, PCI_DEVICE_ID_XXX, + PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, + PCI_CLASS_MASK, 0 }, + { 0, } +}; -#if CONFIG_PCI /* For PCI drivers */ static struct pci_driver xxxfb_driver = { .name = "xxxfb", - .id_table = xxxfb_devices, + .id_table = xxxfb_id_table, .probe = xxxfb_probe, .remove = __devexit_p(xxxfb_remove), - .suspend = xxxfb_suspend, /* optional */ - .resume = xxxfb_resume, /* optional */ + .suspend = xxxfb_suspend, /* optional but recommended */ + .resume = xxxfb_resume, /* optional but recommended */ }; -static int __init xxxfb_init(void) +MODULE_DEVICE_TABLE(pci, xxxfb_id_table); + +int __init xxxfb_init(void) { /* * For kernel boot options (in 'video=xxxfb:<options>' format) @@ -858,16 +922,53 @@ static void __exit xxxfb_exit(void) { pci_unregister_driver(&xxxfb_driver); } -#else +#else /* non PCI, platform drivers */ #include <linux/platform_device.h> /* for platform devices */ + +#ifdef CONFIG_PM +/** + * xxxfb_suspend - Optional but recommended function. Suspend the device. + * @dev: platform device + * @msg: the suspend event code. + * + * See Documentation/power/devices.txt for more information + */ +static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg) +{ + struct fb_info *info = platform_get_drvdata(dev); + struct xxxfb_par *par = info->par; + + /* suspend here */ + return 0; +} + +/** + * xxxfb_resume - Optional but recommended function. Resume the device. + * @dev: platform device + * + * See Documentation/power/devices.txt for more information + */ +static int xxxfb_resume(struct platform_dev *dev) +{ + struct fb_info *info = platform_get_drvdata(dev); + struct xxxfb_par *par = info->par; + + /* resume here */ + return 0; +} +#else +#define xxxfb_suspend NULL +#define xxxfb_resume NULL +#endif /* CONFIG_PM */ + static struct device_driver xxxfb_driver = { .name = "xxxfb", .bus = &platform_bus_type, .probe = xxxfb_probe, .remove = xxxfb_remove, - .suspend = xxxfb_suspend, /* optional */ - .resume = xxxfb_resume, /* optional */ + .suspend = xxxfb_suspend, /* optional but recommended */ + .resume = xxxfb_resume, /* optional but recommended */ }; static struct platform_device xxxfb_device = { @@ -903,8 +1004,9 @@ static void __exit xxxfb_exit(void) platform_device_unregister(&xxxfb_device); driver_unregister(&xxxfb_driver); } -#endif +#endif /* CONFIG_PCI */ +#ifdef MODULE /* * Setup */ @@ -917,34 +1019,7 @@ int __init xxxfb_setup(char *options) { /* Parse user speficied options (`video=xxxfb:') */ } - -/* ------------------------------------------------------------------------- */ - - /* - * Frame buffer operations - */ - -static struct fb_ops xxxfb_ops = { - .owner = THIS_MODULE, - .fb_open = xxxfb_open, - .fb_read = xxxfb_read, - .fb_write = xxxfb_write, - .fb_release = xxxfb_release, - .fb_check_var = xxxfb_check_var, - .fb_set_par = xxxfb_set_par, - .fb_setcolreg = xxxfb_setcolreg, - .fb_blank = xxxfb_blank, - .fb_pan_display = xxxfb_pan_display, - .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ - .fb_copyarea = xxxfb_copyarea, /* Needed !!! */ - .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ - .fb_cursor = xxxfb_cursor, /* Optional !!! */ - .fb_rotate = xxxfb_rotate, - .fb_poll = xxxfb_poll, - .fb_sync = xxxfb_sync, - .fb_ioctl = xxxfb_ioctl, - .fb_mmap = xxxfb_mmap, -}; +#endif /* MODULE */ /* ------------------------------------------------------------------------- */ @@ -954,6 +1029,6 @@ static struct fb_ops xxxfb_ops = { */ module_init(xxxfb_init); -module_exit(xxxfb_cleanup); +module_exit(xxxfb_remove); MODULE_LICENSE("GPL"); diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 0a44c44..c86df12 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -989,7 +989,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) ((info->cmap.green[fg_col] & 0xFC) << 3) | ((info->cmap.blue[fg_col] & 0xF8) >> 3); - dev_dbg(fbi->dev, "fgcol %08x, bgcol %08x\n", fg, bg); + dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg); writel(bg, base + SM501_OFF_HWC_COLOR_1_2); writel(fg, base + SM501_OFF_HWC_COLOR_3); diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 69f3b26..c97709e 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -64,7 +64,6 @@ #include <linux/fb.h> #include <linux/init.h> #include <linux/ioport.h> -#include <linux/pci.h> #include <asm/grfioctl.h> /* for HP-UX compatibility */ #include <asm/uaccess.h> diff --git a/drivers/video/sunxvr2500.c b/drivers/video/sunxvr2500.c new file mode 100644 index 0000000..4316c7f --- /dev/null +++ b/drivers/video/sunxvr2500.c @@ -0,0 +1,277 @@ +/* s3d.c: Sun 3DLABS XVR-2500 et al. driver for sparc64 systems + * + * Copyright (C) 2007 David S. Miller (davem@davemloft.net) + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/pci.h> +#include <linux/init.h> + +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/of_device.h> + +struct s3d_info { + struct fb_info *info; + struct pci_dev *pdev; + + char __iomem *fb_base; + unsigned long fb_base_phys; + + struct device_node *of_node; + + unsigned int width; + unsigned int height; + unsigned int depth; + unsigned int fb_size; + + u32 pseudo_palette[256]; +}; + +static int __devinit s3d_get_props(struct s3d_info *sp) +{ + sp->width = of_getintprop_default(sp->of_node, "width", 0); + sp->height = of_getintprop_default(sp->of_node, "height", 0); + sp->depth = of_getintprop_default(sp->of_node, "depth", 8); + + if (!sp->width || !sp->height) { + printk(KERN_ERR "s3d: Critical properties missing for %s\n", + pci_name(sp->pdev)); + return -EINVAL; + } + + return 0; +} + +static int s3d_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + u32 value; + + if (regno >= 256) + return 1; + + red >>= 8; + green >>= 8; + blue >>= 8; + + value = (blue << 24) | (green << 16) | (red << 8); + ((u32 *)info->pseudo_palette)[regno] = value; + + return 0; +} + +static struct fb_ops s3d_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = s3d_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int __devinit s3d_set_fbinfo(struct s3d_info *sp) +{ + struct fb_info *info = sp->info; + struct fb_var_screeninfo *var = &info->var; + + info->flags = FBINFO_DEFAULT; + info->fbops = &s3d_ops; + info->screen_base = sp->fb_base; + info->screen_size = sp->fb_size; + + info->pseudo_palette = sp->pseudo_palette; + + /* Fill fix common fields */ + strlcpy(info->fix.id, "s3d", sizeof(info->fix.id)); + info->fix.smem_start = sp->fb_base_phys; + info->fix.smem_len = sp->fb_size; + info->fix.type = FB_TYPE_PACKED_PIXELS; + if (sp->depth == 32 || sp->depth == 24) + info->fix.visual = FB_VISUAL_TRUECOLOR; + else + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + + var->xres = sp->width; + var->yres = sp->height; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + var->bits_per_pixel = sp->depth; + + var->red.offset = 8; + var->red.length = 8; + var->green.offset = 16; + var->green.length = 8; + var->blue.offset = 24; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + + if (fb_alloc_cmap(&info->cmap, 256, 0)) { + printk(KERN_ERR "s3d: Cannot allocate color map.\n"); + return -ENOMEM; + } + + return 0; +} + +static int __devinit s3d_pci_register(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct fb_info *info; + struct s3d_info *sp; + int err; + + err = pci_enable_device(pdev); + if (err < 0) { + printk(KERN_ERR "s3d: Cannot enable PCI device %s\n", + pci_name(pdev)); + goto err_out; + } + + info = framebuffer_alloc(sizeof(struct s3d_info), &pdev->dev); + if (!info) { + printk(KERN_ERR "s3d: Cannot allocate fb_info\n"); + err = -ENOMEM; + goto err_disable; + } + + sp = info->par; + sp->info = info; + sp->pdev = pdev; + sp->of_node = pci_device_to_OF_node(pdev); + if (!sp->of_node) { + printk(KERN_ERR "s3d: Cannot find OF node of %s\n", + pci_name(pdev)); + err = -ENODEV; + goto err_release_fb; + } + + sp->fb_base_phys = pci_resource_start (pdev, 1); + + err = pci_request_region(pdev, 1, "s3d framebuffer"); + if (err < 0) { + printk("s3d: Cannot request region 1 for %s\n", + pci_name(pdev)); + goto err_release_fb; + } + + err = s3d_get_props(sp); + if (err) + goto err_release_pci; + + /* XXX 'linebytes' is often wrong, it is equal to the width + * XXX with depth of 32 on my XVR-2500 which is clearly not + * XXX right. So we don't try to use it. + */ + switch (sp->depth) { + case 8: + info->fix.line_length = sp->width; + break; + case 16: + info->fix.line_length = sp->width * 2; + break; + case 24: + info->fix.line_length = sp->width * 3; + break; + case 32: + info->fix.line_length = sp->width * 4; + break; + } + sp->fb_size = info->fix.line_length * sp->height; + + sp->fb_base = ioremap(sp->fb_base_phys, sp->fb_size); + if (!sp->fb_base) + goto err_release_pci; + + err = s3d_set_fbinfo(sp); + if (err) + goto err_unmap_fb; + + pci_set_drvdata(pdev, info); + + printk("s3d: Found device at %s\n", pci_name(pdev)); + + err = register_framebuffer(info); + if (err < 0) { + printk(KERN_ERR "s3d: Could not register framebuffer %s\n", + pci_name(pdev)); + goto err_unmap_fb; + } + + return 0; + +err_unmap_fb: + iounmap(sp->fb_base); + +err_release_pci: + pci_release_region(pdev, 1); + +err_release_fb: + framebuffer_release(info); + +err_disable: + pci_disable_device(pdev); + +err_out: + return err; +} + +static void __devexit s3d_pci_unregister(struct pci_dev *pdev) +{ + struct fb_info *info = pci_get_drvdata(pdev); + struct s3d_info *sp = info->par; + + unregister_framebuffer(info); + + iounmap(sp->fb_base); + + pci_release_region(pdev, 1); + + framebuffer_release(info); + + pci_disable_device(pdev); +} + +static struct pci_device_id s3d_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002c), }, + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002d), }, + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002e), }, + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x002f), }, + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0030), }, + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0031), }, + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0032), }, + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x0033), }, + { 0, } +}; + +static struct pci_driver s3d_driver = { + .name = "s3d", + .id_table = s3d_pci_table, + .probe = s3d_pci_register, + .remove = __devexit_p(s3d_pci_unregister), +}; + +static int __init s3d_init(void) +{ + if (fb_get_options("s3d", NULL)) + return -ENODEV; + + return pci_register_driver(&s3d_driver); +} + +static void __exit s3d_exit(void) +{ + pci_unregister_driver(&s3d_driver); +} + +module_init(s3d_init); +module_exit(s3d_exit); + +MODULE_DESCRIPTION("framebuffer driver for Sun XVR-2500 graphics"); +MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c new file mode 100644 index 0000000..08880a6 --- /dev/null +++ b/drivers/video/sunxvr500.c @@ -0,0 +1,443 @@ +/* sunxvr500.c: Sun 3DLABS XVR-500 Expert3D driver for sparc64 systems + * + * Copyright (C) 2007 David S. Miller (davem@davemloft.net) + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/pci.h> +#include <linux/init.h> + +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/of_device.h> + +/* XXX This device has a 'dev-comm' property which aparently is + * XXX a pointer into the openfirmware's address space which is + * XXX a shared area the kernel driver can use to keep OBP + * XXX informed about the current resolution setting. The idea + * XXX is that the kernel can change resolutions, and as long + * XXX as the values in the 'dev-comm' area are accurate then + * XXX OBP can still render text properly to the console. + * XXX + * XXX I'm still working out the layout of this and whether there + * XXX are any signatures we need to look for etc. + */ +struct e3d_info { + struct fb_info *info; + struct pci_dev *pdev; + + spinlock_t lock; + + char __iomem *fb_base; + unsigned long fb_base_phys; + + unsigned long fb8_buf_diff; + unsigned long regs_base_phys; + + void __iomem *ramdac; + + struct device_node *of_node; + + unsigned int width; + unsigned int height; + unsigned int depth; + unsigned int fb_size; + + u32 fb_base_reg; + u32 fb8_0_off; + u32 fb8_1_off; + + u32 pseudo_palette[256]; +}; + +static int __devinit e3d_get_props(struct e3d_info *ep) +{ + ep->width = of_getintprop_default(ep->of_node, "width", 0); + ep->height = of_getintprop_default(ep->of_node, "height", 0); + ep->depth = of_getintprop_default(ep->of_node, "depth", 8); + + if (!ep->width || !ep->height) { + printk(KERN_ERR "e3d: Critical properties missing for %s\n", + pci_name(ep->pdev)); + return -EINVAL; + } + + return 0; +} + +/* My XVR-500 comes up, at 1280x768 and a FB base register value of + * 0x04000000, the following video layout register values: + * + * RAMDAC_VID_WH 0x03ff04ff + * RAMDAC_VID_CFG 0x1a0b0088 + * RAMDAC_VID_32FB_0 0x04000000 + * RAMDAC_VID_32FB_1 0x04800000 + * RAMDAC_VID_8FB_0 0x05000000 + * RAMDAC_VID_8FB_1 0x05200000 + * RAMDAC_VID_XXXFB 0x05400000 + * RAMDAC_VID_YYYFB 0x05c00000 + * RAMDAC_VID_ZZZFB 0x05e00000 + */ +/* Video layout registers */ +#define RAMDAC_VID_WH 0x00000070UL /* (height-1)<<16 | (width-1) */ +#define RAMDAC_VID_CFG 0x00000074UL /* 0x1a000088|(linesz_log2<<16) */ +#define RAMDAC_VID_32FB_0 0x00000078UL /* PCI base 32bpp FB buffer 0 */ +#define RAMDAC_VID_32FB_1 0x0000007cUL /* PCI base 32bpp FB buffer 1 */ +#define RAMDAC_VID_8FB_0 0x00000080UL /* PCI base 8bpp FB buffer 0 */ +#define RAMDAC_VID_8FB_1 0x00000084UL /* PCI base 8bpp FB buffer 1 */ +#define RAMDAC_VID_XXXFB 0x00000088UL /* PCI base of XXX FB */ +#define RAMDAC_VID_YYYFB 0x0000008cUL /* PCI base of YYY FB */ +#define RAMDAC_VID_ZZZFB 0x00000090UL /* PCI base of ZZZ FB */ + +/* CLUT registers */ +#define RAMDAC_INDEX 0x000000bcUL +#define RAMDAC_DATA 0x000000c0UL + +static void e3d_clut_write(struct e3d_info *ep, int index, u32 val) +{ + void __iomem *ramdac = ep->ramdac; + unsigned long flags; + + spin_lock_irqsave(&ep->lock, flags); + + writel(index, ramdac + RAMDAC_INDEX); + writel(val, ramdac + RAMDAC_DATA); + + spin_unlock_irqrestore(&ep->lock, flags); +} + +static int e3d_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + struct e3d_info *ep = info->par; + u32 red_8, green_8, blue_8; + u32 red_10, green_10, blue_10; + u32 value; + + if (regno >= 256) + return 1; + + red_8 = red >> 8; + green_8 = green >> 8; + blue_8 = blue >> 8; + + value = (blue_8 << 24) | (green_8 << 16) | (red_8 << 8); + ((u32 *)info->pseudo_palette)[regno] = value; + + + red_10 = red >> 6; + green_10 = green >> 6; + blue_10 = blue >> 6; + + value = (blue_10 << 20) | (green_10 << 10) | (red_10 << 0); + e3d_clut_write(ep, regno, value); + + return 0; +} + +/* XXX This is a bit of a hack. I can't figure out exactly how the + * XXX two 8bpp areas of the framebuffer work. I imagine there is + * XXX a WID attribute somewhere else in the framebuffer which tells + * XXX the ramdac which of the two 8bpp framebuffer regions to take + * XXX the pixel from. So, for now, render into both regions to make + * XXX sure the pixel shows up. + */ +static void e3d_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct e3d_info *ep = info->par; + unsigned long flags; + + spin_lock_irqsave(&ep->lock, flags); + cfb_imageblit(info, image); + info->screen_base += ep->fb8_buf_diff; + cfb_imageblit(info, image); + info->screen_base -= ep->fb8_buf_diff; + spin_unlock_irqrestore(&ep->lock, flags); +} + +static void e3d_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + struct e3d_info *ep = info->par; + unsigned long flags; + + spin_lock_irqsave(&ep->lock, flags); + cfb_fillrect(info, rect); + info->screen_base += ep->fb8_buf_diff; + cfb_fillrect(info, rect); + info->screen_base -= ep->fb8_buf_diff; + spin_unlock_irqrestore(&ep->lock, flags); +} + +static void e3d_copyarea(struct fb_info *info, const struct fb_copyarea *area) +{ + struct e3d_info *ep = info->par; + unsigned long flags; + + spin_lock_irqsave(&ep->lock, flags); + cfb_copyarea(info, area); + info->screen_base += ep->fb8_buf_diff; + cfb_copyarea(info, area); + info->screen_base -= ep->fb8_buf_diff; + spin_unlock_irqrestore(&ep->lock, flags); +} + +static struct fb_ops e3d_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = e3d_setcolreg, + .fb_fillrect = e3d_fillrect, + .fb_copyarea = e3d_copyarea, + .fb_imageblit = e3d_imageblit, +}; + +static int __devinit e3d_set_fbinfo(struct e3d_info *ep) +{ + struct fb_info *info = ep->info; + struct fb_var_screeninfo *var = &info->var; + + info->flags = FBINFO_DEFAULT; + info->fbops = &e3d_ops; + info->screen_base = ep->fb_base; + info->screen_size = ep->fb_size; + + info->pseudo_palette = ep->pseudo_palette; + + /* Fill fix common fields */ + strlcpy(info->fix.id, "e3d", sizeof(info->fix.id)); + info->fix.smem_start = ep->fb_base_phys; + info->fix.smem_len = ep->fb_size; + info->fix.type = FB_TYPE_PACKED_PIXELS; + if (ep->depth == 32 || ep->depth == 24) + info->fix.visual = FB_VISUAL_TRUECOLOR; + else + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + + var->xres = ep->width; + var->yres = ep->height; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + var->bits_per_pixel = ep->depth; + + var->red.offset = 8; + var->red.length = 8; + var->green.offset = 16; + var->green.length = 8; + var->blue.offset = 24; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + + if (fb_alloc_cmap(&info->cmap, 256, 0)) { + printk(KERN_ERR "e3d: Cannot allocate color map.\n"); + return -ENOMEM; + } + + return 0; +} + +static int __devinit e3d_pci_register(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct fb_info *info; + struct e3d_info *ep; + unsigned int line_length; + int err; + + err = pci_enable_device(pdev); + if (err < 0) { + printk(KERN_ERR "e3d: Cannot enable PCI device %s\n", + pci_name(pdev)); + goto err_out; + } + + info = framebuffer_alloc(sizeof(struct e3d_info), &pdev->dev); + if (!info) { + printk(KERN_ERR "e3d: Cannot allocate fb_info\n"); + err = -ENOMEM; + goto err_disable; + } + + ep = info->par; + ep->info = info; + ep->pdev = pdev; + spin_lock_init(&ep->lock); + ep->of_node = pci_device_to_OF_node(pdev); + if (!ep->of_node) { + printk(KERN_ERR "e3d: Cannot find OF node of %s\n", + pci_name(pdev)); + err = -ENODEV; + goto err_release_fb; + } + + /* Read the PCI base register of the frame buffer, which we + * need in order to interpret the RAMDAC_VID_*FB* values in + * the ramdac correctly. + */ + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, + &ep->fb_base_reg); + ep->fb_base_reg &= PCI_BASE_ADDRESS_MEM_MASK; + + ep->regs_base_phys = pci_resource_start (pdev, 1); + err = pci_request_region(pdev, 1, "e3d regs"); + if (err < 0) { + printk("e3d: Cannot request region 1 for %s\n", + pci_name(pdev)); + goto err_release_fb; + } + ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000); + if (!ep->ramdac) + goto err_release_pci1; + + ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0); + ep->fb8_0_off -= ep->fb_base_reg; + + ep->fb8_1_off = readl(ep->ramdac + RAMDAC_VID_8FB_1); + ep->fb8_1_off -= ep->fb_base_reg; + + ep->fb8_buf_diff = ep->fb8_1_off - ep->fb8_0_off; + + ep->fb_base_phys = pci_resource_start (pdev, 0); + ep->fb_base_phys += ep->fb8_0_off; + + err = pci_request_region(pdev, 0, "e3d framebuffer"); + if (err < 0) { + printk("e3d: Cannot request region 0 for %s\n", + pci_name(pdev)); + goto err_unmap_ramdac; + } + + err = e3d_get_props(ep); + if (err) + goto err_release_pci0; + + line_length = (readl(ep->ramdac + RAMDAC_VID_CFG) >> 16) & 0xff; + line_length = 1 << line_length; + + switch (ep->depth) { + case 8: + info->fix.line_length = line_length; + break; + case 16: + info->fix.line_length = line_length * 2; + break; + case 24: + info->fix.line_length = line_length * 3; + break; + case 32: + info->fix.line_length = line_length * 4; + break; + } + ep->fb_size = info->fix.line_length * ep->height; + + ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size); + if (!ep->fb_base) + goto err_release_pci0; + + err = e3d_set_fbinfo(ep); + if (err) + goto err_unmap_fb; + + pci_set_drvdata(pdev, info); + + printk("e3d: Found device at %s\n", pci_name(pdev)); + + err = register_framebuffer(info); + if (err < 0) { + printk(KERN_ERR "e3d: Could not register framebuffer %s\n", + pci_name(pdev)); + goto err_unmap_fb; + } + + return 0; + +err_unmap_fb: + iounmap(ep->fb_base); + +err_release_pci0: + pci_release_region(pdev, 0); + +err_unmap_ramdac: + iounmap(ep->ramdac); + +err_release_pci1: + pci_release_region(pdev, 1); + +err_release_fb: + framebuffer_release(info); + +err_disable: + pci_disable_device(pdev); + +err_out: + return err; +} + +static void __devexit e3d_pci_unregister(struct pci_dev *pdev) +{ + struct fb_info *info = pci_get_drvdata(pdev); + struct e3d_info *ep = info->par; + + unregister_framebuffer(info); + + iounmap(ep->ramdac); + iounmap(ep->fb_base); + + pci_release_region(pdev, 0); + pci_release_region(pdev, 1); + + framebuffer_release(info); + + pci_disable_device(pdev); +} + +static struct pci_device_id e3d_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a0), }, + { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a2), }, + { .vendor = PCI_VENDOR_ID_3DLABS, + .device = PCI_ANY_ID, + .subvendor = PCI_VENDOR_ID_3DLABS, + .subdevice = 0x0108, + }, + { .vendor = PCI_VENDOR_ID_3DLABS, + .device = PCI_ANY_ID, + .subvendor = PCI_VENDOR_ID_3DLABS, + .subdevice = 0x0140, + }, + { .vendor = PCI_VENDOR_ID_3DLABS, + .device = PCI_ANY_ID, + .subvendor = PCI_VENDOR_ID_3DLABS, + .subdevice = 0x1024, + }, + { 0, } +}; + +static struct pci_driver e3d_driver = { + .name = "e3d", + .id_table = e3d_pci_table, + .probe = e3d_pci_register, + .remove = __devexit_p(e3d_pci_unregister), +}; + +static int __init e3d_init(void) +{ + if (fb_get_options("e3d", NULL)) + return -ENODEV; + + return pci_register_driver(&e3d_driver); +} + +static void __exit e3d_exit(void) +{ + pci_unregister_driver(&e3d_driver); +} + +module_init(e3d_init); +module_exit(e3d_exit); + +MODULE_DESCRIPTION("framebuffer driver for Sun XVR-500 graphics"); +MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/svgalib.c b/drivers/video/svgalib.c index 68b30d9..25df928 100644 --- a/drivers/video/svgalib.c +++ b/drivers/video/svgalib.c @@ -194,7 +194,7 @@ void svga_dump_var(struct fb_var_screeninfo *var, int node) void svga_settile(struct fb_info *info, struct fb_tilemap *map) { const u8 *font = map->data; - u8* fb = (u8 *) info->screen_base; + u8 __iomem *fb = (u8 __iomem *)info->screen_base; int i, c; if ((map->width != 8) || (map->height != 16) || @@ -207,7 +207,8 @@ void svga_settile(struct fb_info *info, struct fb_tilemap *map) fb += 2; for (c = 0; c < map->length; c++) { for (i = 0; i < map->height; i++) { - fb[i * 4] = font[i]; + fb_writeb(font[i], fb + i * 4); +// fb[i * 4] = font[i]; } fb += 128; font += map->height; @@ -221,8 +222,8 @@ void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area) /* colstride is halved in this function because u16 are used */ int colstride = 1 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK); int rowstride = colstride * (info->var.xres_virtual / 8); - u16 *fb = (u16 *) info->screen_base; - u16 *src, *dst; + u16 __iomem *fb = (u16 __iomem *) info->screen_base; + u16 __iomem *src, *dst; if ((area->sy > area->dy) || ((area->sy == area->dy) && (area->sx > area->dx))) { @@ -239,10 +240,11 @@ void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area) } for (dy = 0; dy < area->height; dy++) { - u16* src2 = src; - u16* dst2 = dst; + u16 __iomem *src2 = src; + u16 __iomem *dst2 = dst; for (dx = 0; dx < area->width; dx++) { - *dst2 = *src2; + fb_writew(fb_readw(src2), dst2); +// *dst2 = *src2; src2 += colstride; dst2 += colstride; } @@ -258,14 +260,14 @@ void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect) int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK); int rowstride = colstride * (info->var.xres_virtual / 8); int attr = (0x0F & rect->bg) << 4 | (0x0F & rect->fg); - u8 *fb = (u8 *) info->screen_base; + u8 __iomem *fb = (u8 __iomem *)info->screen_base; fb += rect->sx * colstride + rect->sy * rowstride; for (dy = 0; dy < rect->height; dy++) { - u8* fb2 = fb; + u8 __iomem *fb2 = fb; for (dx = 0; dx < rect->width; dx++) { - fb2[0] = rect->index; - fb2[1] = attr; + fb_writeb(rect->index, fb2); + fb_writeb(attr, fb2 + 1); fb2 += colstride; } fb += rowstride; @@ -279,15 +281,15 @@ void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit) int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK); int rowstride = colstride * (info->var.xres_virtual / 8); int attr = (0x0F & blit->bg) << 4 | (0x0F & blit->fg); - u8* fb = (u8 *) info->screen_base; + u8 __iomem *fb = (u8 __iomem *)info->screen_base; fb += blit->sx * colstride + blit->sy * rowstride; i=0; for (dy=0; dy < blit->height; dy ++) { - u8* fb2 = fb; + u8 __iomem *fb2 = fb; for (dx = 0; dx < blit->width; dx ++) { - fb2[0] = blit->indices[i]; - fb2[1] = attr; + fb_writeb(blit->indices[i], fb2); + fb_writeb(attr, fb2 + 1); fb2 += colstride; i ++; if (i == blit->length) return; @@ -340,6 +342,28 @@ void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) vga_wcrt(NULL, 0x0A, cs); /* set cursor start and enable it */ } +int svga_get_tilemax(struct fb_info *info) +{ + return 256; +} + +/* Get capabilities of accelerator based on the mode */ + +void svga_get_caps(struct fb_info *info, struct fb_blit_caps *caps, + struct fb_var_screeninfo *var) +{ + if (var->bits_per_pixel == 0) { + /* can only support 256 8x16 bitmap */ + caps->x = 1 << (8 - 1); + caps->y = 1 << (16 - 1); + caps->len = 256; + } else { + caps->x = (var->bits_per_pixel == 4) ? 1 << (8 - 1) : ~(u32)0; + caps->y = ~(u32)0; + caps->len = ~(u32)0; + } +} +EXPORT_SYMBOL(svga_get_caps); /* ------------------------------------------------------------------------- */ @@ -621,6 +645,7 @@ EXPORT_SYMBOL(svga_tilecopy); EXPORT_SYMBOL(svga_tilefill); EXPORT_SYMBOL(svga_tileblit); EXPORT_SYMBOL(svga_tilecursor); +EXPORT_SYMBOL(svga_get_tilemax); EXPORT_SYMBOL(svga_compute_pll); EXPORT_SYMBOL(svga_check_timings); diff --git a/drivers/video/syscopyarea.c b/drivers/video/syscopyarea.c new file mode 100644 index 0000000..37af10a --- /dev/null +++ b/drivers/video/syscopyarea.c @@ -0,0 +1,378 @@ +/* + * Generic Bit Block Transfer for frame buffers located in system RAM with + * packed pixels of any depth. + * + * Based almost entirely from cfbcopyarea.c (which is based almost entirely + * on Geert Uytterhoeven's copyarea routine) + * + * Copyright (C) 2007 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/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/fb.h> +#include <linux/slab.h> +#include <asm/types.h> +#include <asm/io.h> +#include "fb_draw.h" + + /* + * Generic bitwise copy algorithm + */ + +static void +bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, + int src_idx, int bits, unsigned n) +{ + unsigned long first, last; + int const shift = dst_idx-src_idx; + int left, right; + + first = FB_SHIFT_HIGH(~0UL, dst_idx); + last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); + + if (!shift) { + /* Same alignment for source and dest */ + if (dst_idx+n <= bits) { + /* Single word */ + if (last) + first &= last; + *dst = comp(*src, *dst, first); + } else { + /* Multiple destination words */ + /* Leading bits */ + if (first != ~0UL) { + *dst = comp(*src, *dst, first); + dst++; + src++; + n -= bits - dst_idx; + } + + /* Main chunk */ + n /= bits; + while (n >= 8) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + n -= 8; + } + while (n--) + *dst++ = *src++; + + /* Trailing bits */ + if (last) + *dst = comp(*src, *dst, last); + } + } else { + unsigned long d0, d1; + int m; + + /* Different alignment for source and dest */ + right = shift & (bits - 1); + left = -shift & (bits - 1); + + if (dst_idx+n <= bits) { + /* Single destination word */ + if (last) + first &= last; + if (shift > 0) { + /* Single source word */ + *dst = comp(*src >> right, *dst, first); + } else if (src_idx+n <= bits) { + /* Single source word */ + *dst = comp(*src << left, *dst, first); + } else { + /* 2 source words */ + d0 = *src++; + d1 = *src; + *dst = comp(d0 << left | d1 >> right, *dst, + first); + } + } else { + /* Multiple destination words */ + /** We must always remember the last value read, + because in case SRC and DST overlap bitwise (e.g. + when moving just one pixel in 1bpp), we always + collect one full long for DST and that might + overlap with the current long from SRC. We store + this value in 'd0'. */ + d0 = *src++; + /* Leading bits */ + if (shift > 0) { + /* Single source word */ + *dst = comp(d0 >> right, *dst, first); + dst++; + n -= bits - dst_idx; + } else { + /* 2 source words */ + d1 = *src++; + *dst = comp(d0 << left | *dst >> right, *dst, first); + d0 = d1; + dst++; + n -= bits - dst_idx; + } + + /* Main chunk */ + m = n % bits; + n /= bits; + while (n >= 4) { + d1 = *src++; + *dst++ = d0 << left | d1 >> right; + d0 = d1; + d1 = *src++; + *dst++ = d0 << left | d1 >> right; + d0 = d1; + d1 = *src++; + *dst++ = d0 << left | d1 >> right; + d0 = d1; + d1 = *src++; + *dst++ = d0 << left | d1 >> right; + d0 = d1; + n -= 4; + } + while (n--) { + d1 = *src++; + *dst++ = d0 << left | d1 >> right; + d0 = d1; + } + + /* Trailing bits */ + if (last) { + if (m <= right) { + /* Single source word */ + *dst = comp(d0 << left, *dst, last); + } else { + /* 2 source words */ + d1 = *src; + *dst = comp(d0 << left | d1 >> right, + *dst, last); + } + } + } + } +} + + /* + * Generic bitwise copy algorithm, operating backward + */ + +static void +bitcpy_rev(unsigned long *dst, int dst_idx, const unsigned long *src, + int src_idx, int bits, unsigned n) +{ + unsigned long first, last; + int shift; + + dst += (n-1)/bits; + src += (n-1)/bits; + if ((n-1) % bits) { + dst_idx += (n-1) % bits; + dst += dst_idx >> (ffs(bits) - 1); + dst_idx &= bits - 1; + src_idx += (n-1) % bits; + src += src_idx >> (ffs(bits) - 1); + src_idx &= bits - 1; + } + + shift = dst_idx-src_idx; + + first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx); + last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits))); + + if (!shift) { + /* Same alignment for source and dest */ + if ((unsigned long)dst_idx+1 >= n) { + /* Single word */ + if (last) + first &= last; + *dst = comp(*src, *dst, first); + } else { + /* Multiple destination words */ + + /* Leading bits */ + if (first != ~0UL) { + *dst = comp(*src, *dst, first); + dst--; + src--; + n -= dst_idx+1; + } + + /* Main chunk */ + n /= bits; + while (n >= 8) { + *dst-- = *src--; + *dst-- = *src--; + *dst-- = *src--; + *dst-- = *src--; + *dst-- = *src--; + *dst-- = *src--; + *dst-- = *src--; + *dst-- = *src--; + n -= 8; + } + while (n--) + *dst-- = *src--; + /* Trailing bits */ + if (last) + *dst = comp(*src, *dst, last); + } + } else { + /* Different alignment for source and dest */ + + int const left = -shift & (bits-1); + int const right = shift & (bits-1); + + if ((unsigned long)dst_idx+1 >= n) { + /* Single destination word */ + if (last) + first &= last; + if (shift < 0) { + /* Single source word */ + *dst = comp(*src << left, *dst, first); + } else if (1+(unsigned long)src_idx >= n) { + /* Single source word */ + *dst = comp(*src >> right, *dst, first); + } else { + /* 2 source words */ + *dst = comp(*src >> right | *(src-1) << left, + *dst, first); + } + } else { + /* Multiple destination words */ + /** We must always remember the last value read, + because in case SRC and DST overlap bitwise (e.g. + when moving just one pixel in 1bpp), we always + collect one full long for DST and that might + overlap with the current long from SRC. We store + this value in 'd0'. */ + unsigned long d0, d1; + int m; + + d0 = *src--; + /* Leading bits */ + if (shift < 0) { + /* Single source word */ + *dst = comp(d0 << left, *dst, first); + } else { + /* 2 source words */ + d1 = *src--; + *dst = comp(d0 >> right | d1 << left, *dst, + first); + d0 = d1; + } + dst--; + n -= dst_idx+1; + + /* Main chunk */ + m = n % bits; + n /= bits; + while (n >= 4) { + d1 = *src--; + *dst-- = d0 >> right | d1 << left; + d0 = d1; + d1 = *src--; + *dst-- = d0 >> right | d1 << left; + d0 = d1; + d1 = *src--; + *dst-- = d0 >> right | d1 << left; + d0 = d1; + d1 = *src--; + *dst-- = d0 >> right | d1 << left; + d0 = d1; + n -= 4; + } + while (n--) { + d1 = *src--; + *dst-- = d0 >> right | d1 << left; + d0 = d1; + } + + /* Trailing bits */ + if (last) { + if (m <= left) { + /* Single source word */ + *dst = comp(d0 >> right, *dst, last); + } else { + /* 2 source words */ + d1 = *src; + *dst = comp(d0 >> right | d1 << left, + *dst, last); + } + } + } + } +} + +void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area) +{ + u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; + u32 height = area->height, width = area->width; + unsigned long const bits_per_line = p->fix.line_length*8u; + unsigned long *dst = NULL, *src = NULL; + int bits = BITS_PER_LONG, bytes = bits >> 3; + int dst_idx = 0, src_idx = 0, rev_copy = 0; + + if (p->state != FBINFO_STATE_RUNNING) + 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)) { + dy += height; + sy += height; + rev_copy = 1; + } + + /* split the base of the framebuffer into a long-aligned address and + the index of the first bit */ + dst = src = (unsigned long *)((unsigned long)p->screen_base & + ~(bytes-1)); + dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1)); + /* add offset of source and target area */ + dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel; + src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel; + + if (p->fbops->fb_sync) + p->fbops->fb_sync(p); + + if (rev_copy) { + while (height--) { + dst_idx -= bits_per_line; + src_idx -= bits_per_line; + dst += dst_idx >> (ffs(bits) - 1); + dst_idx &= (bytes - 1); + src += src_idx >> (ffs(bits) - 1); + src_idx &= (bytes - 1); + bitcpy_rev(dst, dst_idx, src, src_idx, bits, + width*p->var.bits_per_pixel); + } + } else { + while (height--) { + dst += dst_idx >> (ffs(bits) - 1); + dst_idx &= (bytes - 1); + src += src_idx >> (ffs(bits) - 1); + src_idx &= (bytes - 1); + bitcpy(dst, dst_idx, src, src_idx, bits, + width*p->var.bits_per_pixel); + dst_idx += bits_per_line; + src_idx += bits_per_line; + } + } +} + +EXPORT_SYMBOL(sys_copyarea); + +MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); +MODULE_DESCRIPTION("Generic copyarea (sys-to-sys)"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/sysfillrect.c b/drivers/video/sysfillrect.c new file mode 100644 index 0000000..a261e9e --- /dev/null +++ b/drivers/video/sysfillrect.c @@ -0,0 +1,334 @@ +/* + * Generic fillrect for frame buffers in system RAM with packed pixels of + * any depth. + * + * Based almost entirely from cfbfillrect.c (which is based almost entirely + * on Geert Uytterhoeven's fillrect routine) + * + * Copyright (C) 2007 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/module.h> +#include <linux/string.h> +#include <linux/fb.h> +#include <asm/types.h> +#include "fb_draw.h" + + /* + * Aligned pattern fill using 32/64-bit memory accesses + */ + +static void +bitfill_aligned(unsigned long *dst, int dst_idx, unsigned long pat, + unsigned n, int bits) +{ + unsigned long first, last; + + if (!n) + return; + + first = FB_SHIFT_HIGH(~0UL, dst_idx); + last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); + + if (dst_idx+n <= bits) { + /* Single word */ + if (last) + first &= last; + *dst = comp(pat, *dst, first); + } else { + /* Multiple destination words */ + + /* Leading bits */ + if (first!= ~0UL) { + *dst = comp(pat, *dst, first); + dst++; + n -= bits - dst_idx; + } + + /* Main chunk */ + n /= bits; + while (n >= 8) { + *dst++ = pat; + *dst++ = pat; + *dst++ = pat; + *dst++ = pat; + *dst++ = pat; + *dst++ = pat; + *dst++ = pat; + *dst++ = pat; + n -= 8; + } + while (n--) + *dst++ = pat; + /* Trailing bits */ + if (last) + *dst = comp(pat, *dst, last); + } +} + + + /* + * Unaligned generic pattern fill using 32/64-bit memory accesses + * The pattern must have been expanded to a full 32/64-bit value + * Left/right are the appropriate shifts to convert to the pattern to be + * used for the next 32/64-bit word + */ + +static void +bitfill_unaligned(unsigned long *dst, int dst_idx, unsigned long pat, + int left, int right, unsigned n, int bits) +{ + unsigned long first, last; + + if (!n) + return; + + first = FB_SHIFT_HIGH(~0UL, dst_idx); + last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); + + if (dst_idx+n <= bits) { + /* Single word */ + if (last) + first &= last; + *dst = comp(pat, *dst, first); + } else { + /* Multiple destination words */ + /* Leading bits */ + if (first) { + *dst = comp(pat, *dst, first); + dst++; + pat = pat << left | pat >> right; + n -= bits - dst_idx; + } + + /* Main chunk */ + n /= bits; + while (n >= 4) { + *dst++ = pat; + pat = pat << left | pat >> right; + *dst++ = pat; + pat = pat << left | pat >> right; + *dst++ = pat; + pat = pat << left | pat >> right; + *dst++ = pat; + pat = pat << left | pat >> right; + n -= 4; + } + while (n--) { + *dst++ = pat; + pat = pat << left | pat >> right; + } + + /* Trailing bits */ + if (last) + *dst = comp(pat, *dst, first); + } +} + + /* + * Aligned pattern invert using 32/64-bit memory accesses + */ +static void +bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat, + unsigned n, int bits) +{ + unsigned long val = pat; + unsigned long first, last; + + if (!n) + return; + + first = FB_SHIFT_HIGH(~0UL, dst_idx); + last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); + + if (dst_idx+n <= bits) { + /* Single word */ + if (last) + first &= last; + *dst = comp(*dst ^ val, *dst, first); + } else { + /* Multiple destination words */ + /* Leading bits */ + if (first!=0UL) { + *dst = comp(*dst ^ val, *dst, first); + dst++; + n -= bits - dst_idx; + } + + /* Main chunk */ + n /= bits; + while (n >= 8) { + *dst++ ^= val; + *dst++ ^= val; + *dst++ ^= val; + *dst++ ^= val; + *dst++ ^= val; + *dst++ ^= val; + *dst++ ^= val; + *dst++ ^= val; + n -= 8; + } + while (n--) + *dst++ ^= val; + /* Trailing bits */ + if (last) + *dst = comp(*dst ^ val, *dst, last); + } +} + + + /* + * Unaligned generic pattern invert using 32/64-bit memory accesses + * The pattern must have been expanded to a full 32/64-bit value + * Left/right are the appropriate shifts to convert to the pattern to be + * used for the next 32/64-bit word + */ + +static void +bitfill_unaligned_rev(unsigned long *dst, int dst_idx, unsigned long pat, + int left, int right, unsigned n, int bits) +{ + unsigned long first, last; + + if (!n) + return; + + first = FB_SHIFT_HIGH(~0UL, dst_idx); + last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); + + if (dst_idx+n <= bits) { + /* Single word */ + if (last) + first &= last; + *dst = comp(*dst ^ pat, *dst, first); + } else { + /* Multiple destination words */ + + /* Leading bits */ + if (first != 0UL) { + *dst = comp(*dst ^ pat, *dst, first); + dst++; + pat = pat << left | pat >> right; + n -= bits - dst_idx; + } + + /* Main chunk */ + n /= bits; + while (n >= 4) { + *dst++ ^= pat; + pat = pat << left | pat >> right; + *dst++ ^= pat; + pat = pat << left | pat >> right; + *dst++ ^= pat; + pat = pat << left | pat >> right; + *dst++ ^= pat; + pat = pat << left | pat >> right; + n -= 4; + } + while (n--) { + *dst ^= pat; + pat = pat << left | pat >> right; + } + + /* Trailing bits */ + if (last) + *dst = comp(*dst ^ pat, *dst, last); + } +} + +void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) +{ + 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 *dst; + int dst_idx, left; + + if (p->state != FBINFO_STATE_RUNNING) + return; + + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR ) + fg = ((u32 *) (p->pseudo_palette))[rect->color]; + else + fg = rect->color; + + pat = pixel_to_pat( bpp, fg); + + dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1)); + dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; + dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; + /* FIXME For now we support 1-32 bpp only */ + left = bits % bpp; + if (p->fbops->fb_sync) + p->fbops->fb_sync(p); + if (!left) { + void (*fill_op32)(unsigned long *dst, int dst_idx, + unsigned long pat, unsigned n, int bits) = + NULL; + + switch (rect->rop) { + case ROP_XOR: + fill_op32 = bitfill_aligned_rev; + break; + case ROP_COPY: + fill_op32 = bitfill_aligned; + break; + default: + printk( KERN_ERR "cfb_fillrect(): unknown rop, " + "defaulting to ROP_COPY\n"); + fill_op32 = bitfill_aligned; + break; + } + while (height--) { + dst += dst_idx >> (ffs(bits) - 1); + dst_idx &= (bits - 1); + fill_op32(dst, dst_idx, pat, width*bpp, bits); + dst_idx += p->fix.line_length*8; + } + } else { + int right; + int r; + int rot = (left-dst_idx) % bpp; + void (*fill_op)(unsigned long *dst, int dst_idx, + unsigned long pat, int left, int right, + unsigned n, int bits) = NULL; + + /* rotate pattern to correct start position */ + pat = pat << rot | pat >> (bpp-rot); + + right = bpp-left; + switch (rect->rop) { + case ROP_XOR: + fill_op = bitfill_unaligned_rev; + break; + case ROP_COPY: + fill_op = bitfill_unaligned; + break; + default: + printk(KERN_ERR "cfb_fillrect(): unknown rop, " + "defaulting to ROP_COPY\n"); + fill_op = bitfill_unaligned; + break; + } + while (height--) { + dst += dst_idx >> (ffs(bits) - 1); + dst_idx &= (bits - 1); + fill_op(dst, dst_idx, pat, left, right, + width*bpp, bits); + r = (p->fix.line_length*8) % bpp; + pat = pat << (bpp-r) | pat >> r; + dst_idx += p->fix.line_length*8; + } + } +} + +EXPORT_SYMBOL(sys_fillrect); + +MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); +MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/sysimgblt.c b/drivers/video/sysimgblt.c new file mode 100644 index 0000000..bd7e7e9 --- /dev/null +++ b/drivers/video/sysimgblt.c @@ -0,0 +1,291 @@ +/* + * Generic 1-bit or 8-bit source to 1-32 bit destination expansion + * for frame buffer located in system RAM with packed pixels of any depth. + * + * Based almost entirely on cfbimgblt.c + * + * Copyright (C) April 2007 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/module.h> +#include <linux/string.h> +#include <linux/fb.h> +#include <asm/types.h> + +#define DEBUG + +#ifdef DEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__FUNCTION__,## args) +#else +#define DPRINTK(fmt, args...) +#endif + +static const u32 cfb_tab8[] = { +#if defined(__BIG_ENDIAN) + 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, + 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, + 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, + 0xffff0000,0xffff00ff,0xffffff00,0xffffffff +#elif defined(__LITTLE_ENDIAN) + 0x00000000,0xff000000,0x00ff0000,0xffff0000, + 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, + 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, + 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff +#else +#error FIXME: No endianness?? +#endif +}; + +static const u32 cfb_tab16[] = { +#if defined(__BIG_ENDIAN) + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff +#elif defined(__LITTLE_ENDIAN) + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff +#else +#error FIXME: No endianness?? +#endif +}; + +static const u32 cfb_tab32[] = { + 0x00000000, 0xffffffff +}; + +static void color_imageblit(const struct fb_image *image, struct fb_info *p, + void *dst1, u32 start_index, u32 pitch_index) +{ + /* Draw the penguin */ + u32 *dst, *dst2; + u32 color = 0, val, shift; + int i, n, bpp = p->var.bits_per_pixel; + u32 null_bits = 32 - bpp; + u32 *palette = (u32 *) p->pseudo_palette; + const u8 *src = image->data; + + dst2 = dst1; + for (i = image->height; i--; ) { + n = image->width; + dst = dst1; + shift = 0; + val = 0; + + if (start_index) { + u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0, + start_index)); + val = *dst & start_mask; + shift = start_index; + } + while (n--) { + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR ) + color = palette[*src]; + else + color = *src; + color <<= FB_LEFT_POS(bpp); + val |= FB_SHIFT_HIGH(color, shift); + if (shift >= null_bits) { + *dst++ = val; + + val = (shift == null_bits) ? 0 : + FB_SHIFT_LOW(color, 32 - shift); + } + shift += bpp; + shift &= (32 - 1); + src++; + } + if (shift) { + u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); + + *dst &= end_mask; + *dst |= val; + } + dst1 += p->fix.line_length; + if (pitch_index) { + dst2 += p->fix.line_length; + dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1)); + + start_index += pitch_index; + start_index &= 32 - 1; + } + } +} + +static void slow_imageblit(const struct fb_image *image, struct fb_info *p, + void *dst1, u32 fgcolor, u32 bgcolor, + u32 start_index, u32 pitch_index) +{ + u32 shift, color = 0, bpp = p->var.bits_per_pixel; + u32 *dst, *dst2; + u32 val, pitch = p->fix.line_length; + u32 null_bits = 32 - bpp; + u32 spitch = (image->width+7)/8; + const u8 *src = image->data, *s; + u32 i, j, l; + + dst2 = dst1; + fgcolor <<= FB_LEFT_POS(bpp); + bgcolor <<= FB_LEFT_POS(bpp); + + for (i = image->height; i--; ) { + shift = val = 0; + l = 8; + j = image->width; + dst = dst1; + s = src; + + /* write leading bits */ + if (start_index) { + u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index)); + val = *dst & start_mask; + shift = start_index; + } + + while (j--) { + l--; + color = (*s & (1 << l)) ? fgcolor : bgcolor; + val |= FB_SHIFT_HIGH(color, shift); + + /* Did the bitshift spill bits to the next long? */ + if (shift >= null_bits) { + *dst++ = val; + val = (shift == null_bits) ? 0 : + FB_SHIFT_LOW(color,32 - shift); + } + shift += bpp; + shift &= (32 - 1); + if (!l) { l = 8; s++; }; + } + + /* write trailing bits */ + if (shift) { + u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); + + *dst &= end_mask; + *dst |= val; + } + + dst1 += pitch; + src += spitch; + if (pitch_index) { + dst2 += pitch; + dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1)); + start_index += pitch_index; + start_index &= 32 - 1; + } + + } +} + +/* + * fast_imageblit - optimized monochrome color expansion + * + * Only if: bits_per_pixel == 8, 16, or 32 + * image->width is divisible by pixel/dword (ppw); + * fix->line_legth is divisible by 4; + * beginning and end of a scanline is dword aligned + */ +static void fast_imageblit(const struct fb_image *image, struct fb_info *p, + void *dst1, u32 fgcolor, u32 bgcolor) +{ + u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; + u32 ppw = 32/bpp, spitch = (image->width + 7)/8; + u32 bit_mask, end_mask, eorx, shift; + const char *s = image->data, *src; + u32 *dst; + const u32 *tab = NULL; + int i, j, k; + + switch (bpp) { + case 8: + tab = cfb_tab8; + break; + case 16: + tab = cfb_tab16; + break; + case 32: + default: + tab = cfb_tab32; + break; + } + + for (i = ppw-1; i--; ) { + fgx <<= bpp; + bgx <<= bpp; + fgx |= fgcolor; + bgx |= bgcolor; + } + + bit_mask = (1 << ppw) - 1; + eorx = fgx ^ bgx; + k = image->width/ppw; + + for (i = image->height; i--; ) { + dst = dst1; + shift = 8; + src = s; + + for (j = k; j--; ) { + shift -= ppw; + end_mask = tab[(*src >> shift) & bit_mask]; + *dst++ = (end_mask & eorx) ^ bgx; + if (!shift) { + shift = 8; + src++; + } + } + dst1 += p->fix.line_length; + s += spitch; + } +} + +void sys_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; + u32 dx = image->dx, dy = image->dy; + void *dst1; + + if (p->state != FBINFO_STATE_RUNNING) + return; + + bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); + start_index = bitstart & (32 - 1); + pitch_index = (p->fix.line_length & (bpl - 1)) * 8; + + bitstart /= 8; + bitstart &= ~(bpl - 1); + dst1 = (void __force *)p->screen_base + bitstart; + + if (p->fbops->fb_sync) + p->fbops->fb_sync(p); + + if (image->depth == 1) { + if (p->fix.visual == FB_VISUAL_TRUECOLOR || + p->fix.visual == FB_VISUAL_DIRECTCOLOR) { + fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; + bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; + } else { + fgcolor = image->fg_color; + bgcolor = image->bg_color; + } + + if (32 % bpp == 0 && !start_index && !pitch_index && + ((width & (32/bpp-1)) == 0) && + bpp >= 8 && bpp <= 32) + fast_imageblit(image, p, dst1, fgcolor, bgcolor); + else + slow_imageblit(image, p, dst1, fgcolor, bgcolor, + start_index, pitch_index); + } else + color_imageblit(image, p, dst1, start_index, pitch_index); +} + +EXPORT_SYMBOL(sys_imageblit); + +MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); +MODULE_DESCRIPTION("1-bit/8-bit to 1-32 bit color expansion (sys-to-sys)"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 7478d0e..f0fde6e 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -5,27 +5,45 @@ * Copyright (C) 1997 Geert Uytterhoeven * Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha * Copyright (C) 2002 Richard Henderson + * Copyright (C) 2006 Maciej W. Rozycki * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/slab.h> +#include <linux/bitrev.h> #include <linux/delay.h> -#include <linux/init.h> +#include <linux/device.h> +#include <linux/errno.h> #include <linux/fb.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/module.h> #include <linux/pci.h> #include <linux/selection.h> -#include <linux/bitrev.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/tc.h> + #include <asm/io.h> + #include <video/tgafb.h> +#ifdef CONFIG_PCI +#define TGA_BUS_PCI(dev) (dev->bus == &pci_bus_type) +#else +#define TGA_BUS_PCI(dev) 0 +#endif + +#ifdef CONFIG_TC +#define TGA_BUS_TC(dev) (dev->bus == &tc_bus_type) +#else +#define TGA_BUS_TC(dev) 0 +#endif + /* * Local functions. */ @@ -41,14 +59,19 @@ static void tgafb_init_fix(struct fb_info *); static void tgafb_imageblit(struct fb_info *, const struct fb_image *); static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *); static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *); +static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); -static int __devinit tgafb_pci_register(struct pci_dev *, - const struct pci_device_id *); -static void __devexit tgafb_pci_unregister(struct pci_dev *); +static int __devinit tgafb_register(struct device *dev); +static void __devexit tgafb_unregister(struct device *dev); -static const char *mode_option = "640x480@60"; +static const char *mode_option; +static const char *mode_option_pci = "640x480@60"; +static const char *mode_option_tc = "1280x1024@72"; +static struct pci_driver tgafb_pci_driver; +static struct tc_driver tgafb_tc_driver; + /* * Frame buffer operations */ @@ -59,15 +82,20 @@ static struct fb_ops tgafb_ops = { .fb_set_par = tgafb_set_par, .fb_setcolreg = tgafb_setcolreg, .fb_blank = tgafb_blank, + .fb_pan_display = tgafb_pan_display, .fb_fillrect = tgafb_fillrect, .fb_copyarea = tgafb_copyarea, .fb_imageblit = tgafb_imageblit, }; +#ifdef CONFIG_PCI /* * PCI registration operations */ +static int __devinit tgafb_pci_register(struct pci_dev *, + const struct pci_device_id *); +static void __devexit tgafb_pci_unregister(struct pci_dev *); static struct pci_device_id const tgafb_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) }, @@ -75,13 +103,68 @@ static struct pci_device_id const tgafb_pci_table[] = { }; MODULE_DEVICE_TABLE(pci, tgafb_pci_table); -static struct pci_driver tgafb_driver = { +static struct pci_driver tgafb_pci_driver = { .name = "tgafb", .id_table = tgafb_pci_table, .probe = tgafb_pci_register, .remove = __devexit_p(tgafb_pci_unregister), }; +static int __devinit +tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + return tgafb_register(&pdev->dev); +} + +static void __devexit +tgafb_pci_unregister(struct pci_dev *pdev) +{ + tgafb_unregister(&pdev->dev); +} +#endif /* CONFIG_PCI */ + +#ifdef CONFIG_TC +/* + * TC registration operations + */ +static int __devinit tgafb_tc_register(struct device *); +static int __devexit tgafb_tc_unregister(struct device *); + +static struct tc_device_id const tgafb_tc_table[] = { + { "DEC ", "PMAGD-AA" }, + { "DEC ", "PMAGD " }, + { } +}; +MODULE_DEVICE_TABLE(tc, tgafb_tc_table); + +static struct tc_driver tgafb_tc_driver = { + .id_table = tgafb_tc_table, + .driver = { + .name = "tgafb", + .bus = &tc_bus_type, + .probe = tgafb_tc_register, + .remove = __devexit_p(tgafb_tc_unregister), + }, +}; + +static int __devinit +tgafb_tc_register(struct device *dev) +{ + int status = tgafb_register(dev); + if (!status) + get_device(dev); + return status; +} + +static int __devexit +tgafb_tc_unregister(struct device *dev) +{ + put_device(dev); + tgafb_unregister(dev); + return 0; +} +#endif /* CONFIG_TC */ + /** * tgafb_check_var - Optional function. Validates a var passed in. @@ -132,10 +215,10 @@ static int tgafb_set_par(struct fb_info *info) { static unsigned int const deep_presets[4] = { - 0x00014000, - 0x0001440d, + 0x00004000, + 0x0000440d, 0xffffffff, - 0x0001441d + 0x0000441d }; static unsigned int const rasterop_presets[4] = { 0x00000003, @@ -157,6 +240,8 @@ tgafb_set_par(struct fb_info *info) }; struct tga_par *par = (struct tga_par *) info->par; + int tga_bus_pci = TGA_BUS_PCI(par->dev); + int tga_bus_tc = TGA_BUS_TC(par->dev); u32 htimings, vtimings, pll_freq; u8 tga_type; int i; @@ -221,7 +306,7 @@ tgafb_set_par(struct fb_info *info) TGA_WRITE_REG(par, vtimings, TGA_VERT_REG); /* Initalise RAMDAC. */ - if (tga_type == TGA_TYPE_8PLANE) { + if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) { /* Init BT485 RAMDAC registers. */ BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0), @@ -236,21 +321,7 @@ tgafb_set_par(struct fb_info *info) BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE); TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG); -#ifdef CONFIG_HW_CONSOLE - for (i = 0; i < 16; i++) { - int j = color_table[i]; - - TGA_WRITE_REG(par, default_red[j]|(BT485_DATA_PAL<<8), - TGA_RAMDAC_REG); - TGA_WRITE_REG(par, default_grn[j]|(BT485_DATA_PAL<<8), - TGA_RAMDAC_REG); - TGA_WRITE_REG(par, default_blu[j]|(BT485_DATA_PAL<<8), - TGA_RAMDAC_REG); - } - for (i = 0; i < 240 * 3; i += 4) { -#else for (i = 0; i < 256 * 3; i += 4) { -#endif TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8), TGA_RAMDAC_REG); TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8), @@ -261,6 +332,27 @@ tgafb_set_par(struct fb_info *info) TGA_RAMDAC_REG); } + } else if (tga_type == TGA_TYPE_8PLANE && tga_bus_tc) { + + /* Init BT459 RAMDAC registers. */ + BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_0, 0x40); + BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_1, 0x00); + BT459_WRITE(par, BT459_REG_ACC, BT459_CMD_REG_2, + (par->sync_on_green ? 0xc0 : 0x40)); + + BT459_WRITE(par, BT459_REG_ACC, BT459_CUR_CMD_REG, 0x00); + + /* Fill the palette. */ + BT459_LOAD_ADDR(par, 0x0000); + TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG); + + for (i = 0; i < 256 * 3; i += 4) { + TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG); + TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG); + TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG); + TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG); + } + } else { /* 24-plane or 24plusZ */ /* Init BT463 RAMDAC registers. */ @@ -431,6 +523,8 @@ tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { struct tga_par *par = (struct tga_par *) info->par; + int tga_bus_pci = TGA_BUS_PCI(par->dev); + int tga_bus_tc = TGA_BUS_TC(par->dev); if (regno > 255) return 1; @@ -438,12 +532,18 @@ tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, green >>= 8; blue >>= 8; - if (par->tga_type == TGA_TYPE_8PLANE) { + if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_pci) { BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE); TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG); TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); + } else if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_tc) { + BT459_LOAD_ADDR(par, regno); + TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG); + TGA_WRITE_REG(par, red, TGA_RAMDAC_REG); + TGA_WRITE_REG(par, green, TGA_RAMDAC_REG); + TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG); } else { if (regno < 16) { u32 value = (regno << 16) | (regno << 8) | regno; @@ -523,16 +623,8 @@ tgafb_blank(int blank, struct fb_info *info) * Acceleration. */ -/** - * tgafb_imageblit - REQUIRED function. Can use generic routines if - * non acclerated hardware and packed pixel based. - * Copies a image from system memory to the screen. - * - * @info: frame buffer structure that represents a single frame buffer - * @image: structure defining the image. - */ static void -tgafb_imageblit(struct fb_info *info, const struct fb_image *image) +tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image) { struct tga_par *par = (struct tga_par *) info->par; u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask; @@ -542,6 +634,17 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) void __iomem *regs_base; void __iomem *fb_base; + is8bpp = info->var.bits_per_pixel == 8; + + /* For copies that aren't pixel expansion, there's little we + can do better than the generic code. */ + /* ??? There is a DMA write mode; I wonder if that could be + made to pull the data from the image buffer... */ + if (image->depth > 1) { + cfb_imageblit(info, image); + return; + } + dx = image->dx; dy = image->dy; width = image->width; @@ -559,18 +662,8 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) if (dy + height > vyres) height = vyres - dy; - /* For copies that aren't pixel expansion, there's little we - can do better than the generic code. */ - /* ??? There is a DMA write mode; I wonder if that could be - made to pull the data from the image buffer... */ - if (image->depth > 1) { - cfb_imageblit(info, image); - return; - } - regs_base = par->tga_regs_base; fb_base = par->tga_fb_base; - is8bpp = info->var.bits_per_pixel == 8; /* Expand the color values to fill 32-bits. */ /* ??? Would be nice to notice colour changes elsewhere, so @@ -748,6 +841,85 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image) regs_base + TGA_MODE_REG); } +static void +tgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct tga_par *par = (struct tga_par *) info->par; + u32 color, dx, dy, width, height, vxres, vyres; + u32 *palette = ((u32 *)info->pseudo_palette); + unsigned long pos, line_length, i, j; + const unsigned char *data; + void *regs_base, *fb_base; + + dx = image->dx; + dy = image->dy; + width = image->width; + height = image->height; + vxres = info->var.xres_virtual; + vyres = info->var.yres_virtual; + line_length = info->fix.line_length; + + /* Crop the image to the screen. */ + if (dx > vxres || dy > vyres) + return; + if (dx + width > vxres) + width = vxres - dx; + if (dy + height > vyres) + height = vyres - dy; + + regs_base = par->tga_regs_base; + fb_base = par->tga_fb_base; + + pos = dy * line_length + (dx * 4); + data = image->data; + + /* Now copy the image, color_expanding via the palette. */ + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + color = palette[*data++]; + __raw_writel(color, fb_base + pos + j*4); + } + pos += line_length; + } +} + +/** + * tgafb_imageblit - REQUIRED function. Can use generic routines if + * non acclerated hardware and packed pixel based. + * Copies a image from system memory to the screen. + * + * @info: frame buffer structure that represents a single frame buffer + * @image: structure defining the image. + */ +static void +tgafb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + unsigned int is8bpp = info->var.bits_per_pixel == 8; + + /* If a mono image, regardless of FB depth, go do it. */ + if (image->depth == 1) { + tgafb_mono_imageblit(info, image); + return; + } + + /* For copies that aren't pixel expansion, there's little we + can do better than the generic code. */ + /* ??? There is a DMA write mode; I wonder if that could be + made to pull the data from the image buffer... */ + if (image->depth == info->var.bits_per_pixel) { + cfb_imageblit(info, image); + return; + } + + /* If 24-plane FB and the image is 8-plane with CLUT, we can do it. */ + if (!is8bpp && image->depth == 8) { + tgafb_clut_imageblit(info, image); + return; + } + + /* Silently return... */ +} + /** * tgafb_fillrect - REQUIRED function. Can use generic routines if * non acclerated hardware and packed pixel based. @@ -1309,18 +1481,29 @@ static void tgafb_init_fix(struct fb_info *info) { struct tga_par *par = (struct tga_par *)info->par; + int tga_bus_pci = TGA_BUS_PCI(par->dev); + int tga_bus_tc = TGA_BUS_TC(par->dev); u8 tga_type = par->tga_type; - const char *tga_type_name; + const char *tga_type_name = NULL; switch (tga_type) { case TGA_TYPE_8PLANE: - tga_type_name = "Digital ZLXp-E1"; + if (tga_bus_pci) + tga_type_name = "Digital ZLXp-E1"; + if (tga_bus_tc) + tga_type_name = "Digital ZLX-E1"; break; case TGA_TYPE_24PLANE: - tga_type_name = "Digital ZLXp-E2"; + if (tga_bus_pci) + tga_type_name = "Digital ZLXp-E2"; + if (tga_bus_tc) + tga_type_name = "Digital ZLX-E2"; break; case TGA_TYPE_24PLUSZ: - tga_type_name = "Digital ZLXp-E3"; + if (tga_bus_pci) + tga_type_name = "Digital ZLXp-E3"; + if (tga_bus_tc) + tga_type_name = "Digital ZLX-E3"; break; default: tga_type_name = "Unknown"; @@ -1346,11 +1529,37 @@ tgafb_init_fix(struct fb_info *info) info->fix.ywrapstep = 0; info->fix.accel = FB_ACCEL_DEC_TGA; + + /* + * These are needed by fb_set_logo_truepalette(), so we + * set them here for 24-plane cards. + */ + if (tga_type != TGA_TYPE_8PLANE) { + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; + info->var.red.offset = 16; + info->var.green.offset = 8; + info->var.blue.offset = 0; + } } -static __devinit int -tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) +static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +{ + /* We just use this to catch switches out of graphics mode. */ + tgafb_set_par(info); /* A bit of overkill for BASE_ADDR reset. */ + return 0; +} + +static int __devinit +tgafb_register(struct device *dev) { + static const struct fb_videomode modedb_tc = { + /* 1280x1024 @ 72 Hz, 76.8 kHz hsync */ + "1280x1024@72", 0, 1280, 1024, 7645, 224, 28, 33, 3, 160, 3, + FB_SYNC_ON_GREEN, FB_VMODE_NONINTERLACED + }; + static unsigned int const fb_offset_presets[4] = { TGA_8PLANE_FB_OFFSET, TGA_24PLANE_FB_OFFSET, @@ -1358,40 +1567,51 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) TGA_24PLUSZ_FB_OFFSET }; + const struct fb_videomode *modedb_tga = NULL; + resource_size_t bar0_start = 0, bar0_len = 0; + const char *mode_option_tga = NULL; + int tga_bus_pci = TGA_BUS_PCI(dev); + int tga_bus_tc = TGA_BUS_TC(dev); + unsigned int modedbsize_tga = 0; void __iomem *mem_base; - unsigned long bar0_start, bar0_len; struct fb_info *info; struct tga_par *par; u8 tga_type; - int ret; + int ret = 0; /* Enable device in PCI config. */ - if (pci_enable_device(pdev)) { + if (tga_bus_pci && pci_enable_device(to_pci_dev(dev))) { printk(KERN_ERR "tgafb: Cannot enable PCI device\n"); return -ENODEV; } /* Allocate the fb and par structures. */ - info = framebuffer_alloc(sizeof(struct tga_par), &pdev->dev); + info = framebuffer_alloc(sizeof(struct tga_par), dev); if (!info) { printk(KERN_ERR "tgafb: Cannot allocate memory\n"); return -ENOMEM; } par = info->par; - pci_set_drvdata(pdev, info); + dev_set_drvdata(dev, info); /* Request the mem regions. */ - bar0_start = pci_resource_start(pdev, 0); - bar0_len = pci_resource_len(pdev, 0); ret = -ENODEV; + if (tga_bus_pci) { + bar0_start = pci_resource_start(to_pci_dev(dev), 0); + bar0_len = pci_resource_len(to_pci_dev(dev), 0); + } + if (tga_bus_tc) { + bar0_start = to_tc_dev(dev)->resource.start; + bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1; + } if (!request_mem_region (bar0_start, bar0_len, "tgafb")) { printk(KERN_ERR "tgafb: cannot reserve FB region\n"); goto err0; } /* Map the framebuffer. */ - mem_base = ioremap(bar0_start, bar0_len); + mem_base = ioremap_nocache(bar0_start, bar0_len); if (!mem_base) { printk(KERN_ERR "tgafb: Cannot map MMIO\n"); goto err1; @@ -1399,12 +1619,16 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) /* Grab info about the card. */ tga_type = (readl(mem_base) >> 12) & 0x0f; - par->pdev = pdev; + par->dev = dev; par->tga_mem_base = mem_base; par->tga_fb_base = mem_base + fb_offset_presets[tga_type]; par->tga_regs_base = mem_base + TGA_REGS_OFFSET; par->tga_type = tga_type; - pci_read_config_byte(pdev, PCI_REVISION_ID, &par->tga_chip_rev); + if (tga_bus_pci) + pci_read_config_byte(to_pci_dev(dev), PCI_REVISION_ID, + &par->tga_chip_rev); + if (tga_bus_tc) + par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff; /* Setup framebuffer. */ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | @@ -1414,8 +1638,17 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) info->pseudo_palette = (void *)(par + 1); /* This should give a reasonable default video mode. */ - - ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, + if (tga_bus_pci) { + mode_option_tga = mode_option_pci; + } + if (tga_bus_tc) { + mode_option_tga = mode_option_tc; + modedb_tga = &modedb_tc; + modedbsize_tga = 1; + } + ret = fb_find_mode(&info->var, info, + mode_option ? mode_option : mode_option_tga, + modedb_tga, modedbsize_tga, NULL, tga_type == TGA_TYPE_8PLANE ? 8 : 32); if (ret == 0 || ret == 4) { printk(KERN_ERR "tgafb: Could not find valid video mode\n"); @@ -1438,13 +1671,19 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) goto err1; } - printk(KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n", - par->tga_chip_rev); - printk(KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n", - pdev->bus->number, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn)); - printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n", - info->node, info->fix.id, bar0_start); + if (tga_bus_pci) { + pr_info("tgafb: DC21030 [TGA] detected, rev=0x%02x\n", + par->tga_chip_rev); + pr_info("tgafb: at PCI bus %d, device %d, function %d\n", + to_pci_dev(dev)->bus->number, + PCI_SLOT(to_pci_dev(dev)->devfn), + PCI_FUNC(to_pci_dev(dev)->devfn)); + } + if (tga_bus_tc) + pr_info("tgafb: SFB+ detected, rev=0x%02x\n", + par->tga_chip_rev); + pr_info("fb%d: %s frame buffer device at 0x%lx\n", + info->node, info->fix.id, (long)bar0_start); return 0; @@ -1458,25 +1697,39 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) } static void __devexit -tgafb_pci_unregister(struct pci_dev *pdev) +tgafb_unregister(struct device *dev) { - struct fb_info *info = pci_get_drvdata(pdev); - struct tga_par *par = info->par; + resource_size_t bar0_start = 0, bar0_len = 0; + int tga_bus_pci = TGA_BUS_PCI(dev); + int tga_bus_tc = TGA_BUS_TC(dev); + struct fb_info *info = NULL; + struct tga_par *par; + info = dev_get_drvdata(dev); if (!info) return; + + par = info->par; unregister_framebuffer(info); fb_dealloc_cmap(&info->cmap); iounmap(par->tga_mem_base); - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + if (tga_bus_pci) { + bar0_start = pci_resource_start(to_pci_dev(dev), 0); + bar0_len = pci_resource_len(to_pci_dev(dev), 0); + } + if (tga_bus_tc) { + bar0_start = to_tc_dev(dev)->resource.start; + bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1; + } + release_mem_region(bar0_start, bar0_len); framebuffer_release(info); } static void __devexit tgafb_exit(void) { - pci_unregister_driver(&tgafb_driver); + tc_unregister_driver(&tgafb_tc_driver); + pci_unregister_driver(&tgafb_pci_driver); } #ifndef MODULE @@ -1505,6 +1758,7 @@ tgafb_setup(char *arg) static int __devinit tgafb_init(void) { + int status; #ifndef MODULE char *option = NULL; @@ -1512,7 +1766,10 @@ tgafb_init(void) return -ENODEV; tgafb_setup(option); #endif - return pci_register_driver(&tgafb_driver); + status = pci_register_driver(&tgafb_pci_driver); + if (!status) + status = tc_register_driver(&tgafb_tc_driver); + return status; } /* @@ -1522,5 +1779,5 @@ tgafb_init(void) module_init(tgafb_init); module_exit(tgafb_exit); -MODULE_DESCRIPTION("framebuffer driver for TGA chipset"); +MODULE_DESCRIPTION("Framebuffer driver for TGA/SFB+ chipset"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 06fc19a..ad66f07 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -51,7 +51,6 @@ #include <linux/fb.h> #include <linux/selection.h> #include <linux/init.h> -#include <linux/pci.h> #include <linux/nvram.h> #include <linux/adb.h> #include <linux/cuda.h> diff --git a/drivers/video/vermilion/Makefile b/drivers/video/vermilion/Makefile new file mode 100644 index 0000000..cc21a65 --- /dev/null +++ b/drivers/video/vermilion/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_FB_LE80578) += vmlfb.o +obj-$(CONFIG_FB_CARILLO_RANCH) += crvml.o + +vmlfb-objs := vermilion.o +crvml-objs := cr_pll.o diff --git a/drivers/video/vermilion/cr_pll.c b/drivers/video/vermilion/cr_pll.c new file mode 100644 index 0000000..ebc6e6e --- /dev/null +++ b/drivers/video/vermilion/cr_pll.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * This file is part of the Carillo Ranch video subsystem driver. + * The Carillo Ranch video subsystem driver is free software; + * you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The Carillo Ranch video subsystem driver is distributed + * in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this driver; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> + * Alan Hourihane <alanh-at-tungstengraphics-dot-com> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include "vermilion.h" + +/* The PLL Clock register sits on Host bridge */ +#define CRVML_DEVICE_MCH 0x5001 +#define CRVML_REG_MCHBAR 0x44 +#define CRVML_REG_MCHEN 0x54 +#define CRVML_MCHEN_BIT (1 << 28) +#define CRVML_MCHMAP_SIZE 4096 +#define CRVML_REG_CLOCK 0xc3c +#define CRVML_CLOCK_SHIFT 8 +#define CRVML_CLOCK_MASK 0x00000f00 + +static struct pci_dev *mch_dev; +static u32 mch_bar; +static void __iomem *mch_regs_base; +static u32 saved_clock; + +static const unsigned crvml_clocks[] = { + 6750, + 13500, + 27000, + 29700, + 37125, + 54000, + 59400, + 74250, + 120000 + /* + * There are more clocks, but they are disabled on the CR board. + */ +}; + +static const u32 crvml_clock_bits[] = { + 0x0a, + 0x09, + 0x08, + 0x07, + 0x06, + 0x05, + 0x04, + 0x03, + 0x0b +}; + +static const unsigned crvml_num_clocks = ARRAY_SIZE(crvml_clocks); + +static int crvml_sys_restore(struct vml_sys *sys) +{ + void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK; + + iowrite32(saved_clock, clock_reg); + ioread32(clock_reg); + + return 0; +} + +static int crvml_sys_save(struct vml_sys *sys) +{ + void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK; + + saved_clock = ioread32(clock_reg); + + return 0; +} + +static int crvml_nearest_index(const struct vml_sys *sys, int clock) +{ + int i; + int cur_index = 0; + int cur_diff; + int diff; + + cur_diff = clock - crvml_clocks[0]; + cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff; + for (i = 1; i < crvml_num_clocks; ++i) { + diff = clock - crvml_clocks[i]; + diff = (diff < 0) ? -diff : diff; + if (diff < cur_diff) { + cur_index = i; + cur_diff = diff; + } + } + return cur_index; +} + +static int crvml_nearest_clock(const struct vml_sys *sys, int clock) +{ + return crvml_clocks[crvml_nearest_index(sys, clock)]; +} + +static int crvml_set_clock(struct vml_sys *sys, int clock) +{ + void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK; + int index; + u32 clock_val; + + index = crvml_nearest_index(sys, clock); + + if (crvml_clocks[index] != clock) + return -EINVAL; + + clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK; + clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT; + iowrite32(clock_val, clock_reg); + ioread32(clock_reg); + + return 0; +} + +static struct vml_sys cr_pll_ops = { + .name = "Carillo Ranch", + .save = crvml_sys_save, + .restore = crvml_sys_restore, + .set_clock = crvml_set_clock, + .nearest_clock = crvml_nearest_clock, +}; + +static int __init cr_pll_init(void) +{ + int err; + u32 dev_en; + + mch_dev = pci_get_device(PCI_VENDOR_ID_INTEL, + CRVML_DEVICE_MCH, NULL); + if (!mch_dev) { + printk(KERN_ERR + "Could not find Carillo Ranch MCH device.\n"); + return -ENODEV; + } + + pci_read_config_dword(mch_dev, CRVML_REG_MCHEN, &dev_en); + if (!(dev_en & CRVML_MCHEN_BIT)) { + printk(KERN_ERR + "Carillo Ranch MCH device was not enabled.\n"); + pci_dev_put(mch_dev); + return -ENODEV; + } + + pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR, + &mch_bar); + mch_regs_base = + ioremap_nocache(mch_bar, CRVML_MCHMAP_SIZE); + if (!mch_regs_base) { + printk(KERN_ERR + "Carillo Ranch MCH device was not enabled.\n"); + pci_dev_put(mch_dev); + return -ENODEV; + } + + err = vmlfb_register_subsys(&cr_pll_ops); + if (err) { + printk(KERN_ERR + "Carillo Ranch failed to initialize vml_sys.\n"); + pci_dev_put(mch_dev); + return err; + } + + return 0; +} + +static void __exit cr_pll_exit(void) +{ + vmlfb_unregister_subsys(&cr_pll_ops); + + iounmap(mch_regs_base); + pci_dev_put(mch_dev); +} + +module_init(cr_pll_init); +module_exit(cr_pll_exit); + +MODULE_AUTHOR("Tungsten Graphics Inc."); +MODULE_DESCRIPTION("Carillo Ranch PLL Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c new file mode 100644 index 0000000..de531c9 --- /dev/null +++ b/drivers/video/vermilion/vermilion.c @@ -0,0 +1,1195 @@ +/* + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * This file is part of the Vermilion Range fb driver. + * The Vermilion Range fb driver is free software; + * you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The Vermilion Range fb driver is distributed + * in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this driver; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> + * Michel Dänzer <michel-at-tungstengraphics-dot-com> + * Alan Hourihane <alanh-at-tungstengraphics-dot-com> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include <linux/pci.h> +#include <asm/cacheflush.h> +#include <asm/tlbflush.h> +#include <linux/mmzone.h> +#include <asm/uaccess.h> + +/* #define VERMILION_DEBUG */ + +#include "vermilion.h" + +#define MODULE_NAME "vmlfb" + +#define VML_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) + +static struct mutex vml_mutex; +static struct list_head global_no_mode; +static struct list_head global_has_mode; +static struct fb_ops vmlfb_ops; +static struct vml_sys *subsys = NULL; +static char *vml_default_mode = "1024x768@60"; +static struct fb_videomode defaultmode = { + NULL, 60, 1024, 768, 12896, 144, 24, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED +}; + +static u32 vml_mem_requested = (10 * 1024 * 1024); +static u32 vml_mem_contig = (4 * 1024 * 1024); +static u32 vml_mem_min = (4 * 1024 * 1024); + +static u32 vml_clocks[] = { + 6750, + 13500, + 27000, + 29700, + 37125, + 54000, + 59400, + 74250, + 120000, + 148500 +}; + +static u32 vml_num_clocks = ARRAY_SIZE(vml_clocks); + +/* + * Allocate a contiguous vram area and make its linear kernel map + * uncached. + */ + +static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order, + unsigned min_order) +{ + gfp_t flags; + unsigned long i; + pgprot_t wc_pageprot; + + wc_pageprot = PAGE_KERNEL_NOCACHE; + max_order++; + do { + /* + * Really try hard to get the needed memory. + * We need memory below the first 32MB, so we + * add the __GFP_DMA flag that guarantees that we are + * below the first 16MB. + */ + + flags = __GFP_DMA | __GFP_HIGH; + va->logical = + __get_free_pages(flags, --max_order); + } while (va->logical == 0 && max_order > min_order); + + if (!va->logical) + return -ENOMEM; + + va->phys = virt_to_phys((void *)va->logical); + va->size = PAGE_SIZE << max_order; + va->order = max_order; + + /* + * It seems like __get_free_pages only ups the usage count + * of the first page. This doesn't work with nopage mapping, so + * up the usage count once more. + */ + + memset((void *)va->logical, 0x00, va->size); + for (i = va->logical; i < va->logical + va->size; i += PAGE_SIZE) { + get_page(virt_to_page(i)); + } + + /* + * Change caching policy of the linear kernel map to avoid + * mapping type conflicts with user-space mappings. + * The first global_flush_tlb() is really only there to do a global + * wbinvd(). + */ + + global_flush_tlb(); + change_page_attr(virt_to_page(va->logical), va->size >> PAGE_SHIFT, + wc_pageprot); + global_flush_tlb(); + + printk(KERN_DEBUG MODULE_NAME + ": Allocated %ld bytes vram area at 0x%08lx\n", + va->size, va->phys); + + return 0; +} + +/* + * Free a contiguous vram area and reset its linear kernel map + * mapping type. + */ + +static void vmlfb_free_vram_area(struct vram_area *va) +{ + unsigned long j; + + if (va->logical) { + + /* + * Reset the linear kernel map caching policy. + */ + + change_page_attr(virt_to_page(va->logical), + va->size >> PAGE_SHIFT, PAGE_KERNEL); + global_flush_tlb(); + + /* + * Decrease the usage count on the pages we've used + * to compensate for upping when allocating. + */ + + for (j = va->logical; j < va->logical + va->size; + j += PAGE_SIZE) { + (void)put_page_testzero(virt_to_page(j)); + } + + printk(KERN_DEBUG MODULE_NAME + ": Freeing %ld bytes vram area at 0x%08lx\n", + va->size, va->phys); + free_pages(va->logical, va->order); + + va->logical = 0; + } +} + +/* + * Free allocated vram. + */ + +static void vmlfb_free_vram(struct vml_info *vinfo) +{ + int i; + + for (i = 0; i < vinfo->num_areas; ++i) { + vmlfb_free_vram_area(&vinfo->vram[i]); + } + vinfo->num_areas = 0; +} + +/* + * Allocate vram. Currently we try to allocate contiguous areas from the + * __GFP_DMA zone and puzzle them together. A better approach would be to + * allocate one contiguous area for scanout and use one-page allocations for + * offscreen areas. This requires user-space and GPU virtual mappings. + */ + +static int vmlfb_alloc_vram(struct vml_info *vinfo, + size_t requested, + size_t min_total, size_t min_contig) +{ + int i, j; + int order; + int contiguous; + int err; + struct vram_area *va; + struct vram_area *va2; + + vinfo->num_areas = 0; + for (i = 0; i < VML_VRAM_AREAS; ++i) { + va = &vinfo->vram[i]; + order = 0; + + while (requested > (PAGE_SIZE << order) && order < MAX_ORDER) + order++; + + err = vmlfb_alloc_vram_area(va, order, 0); + + if (err) + break; + + if (i == 0) { + vinfo->vram_start = va->phys; + vinfo->vram_logical = (void __iomem *) va->logical; + vinfo->vram_contig_size = va->size; + vinfo->num_areas = 1; + } else { + contiguous = 0; + + for (j = 0; j < i; ++j) { + va2 = &vinfo->vram[j]; + if (va->phys + va->size == va2->phys || + va2->phys + va2->size == va->phys) { + contiguous = 1; + break; + } + } + + if (contiguous) { + vinfo->num_areas++; + if (va->phys < vinfo->vram_start) { + vinfo->vram_start = va->phys; + vinfo->vram_logical = + (void __iomem *)va->logical; + } + vinfo->vram_contig_size += va->size; + } else { + vmlfb_free_vram_area(va); + break; + } + } + + if (requested < va->size) + break; + else + requested -= va->size; + } + + if (vinfo->vram_contig_size > min_total && + vinfo->vram_contig_size > min_contig) { + + printk(KERN_DEBUG MODULE_NAME + ": Contiguous vram: %ld bytes at physical 0x%08lx.\n", + (unsigned long)vinfo->vram_contig_size, + (unsigned long)vinfo->vram_start); + + return 0; + } + + printk(KERN_ERR MODULE_NAME + ": Could not allocate requested minimal amount of vram.\n"); + + vmlfb_free_vram(vinfo); + + return -ENOMEM; +} + +/* + * Find the GPU to use with our display controller. + */ + +static int vmlfb_get_gpu(struct vml_par *par) +{ + mutex_lock(&vml_mutex); + + par->gpu = pci_get_device(PCI_VENDOR_ID_INTEL, VML_DEVICE_GPU, NULL); + + if (!par->gpu) { + mutex_unlock(&vml_mutex); + return -ENODEV; + } + + mutex_unlock(&vml_mutex); + + if (pci_enable_device(par->gpu) < 0) + return -ENODEV; + + return 0; +} + +/* + * Find a contiguous vram area that contains a given offset from vram start. + */ +static int vmlfb_vram_offset(struct vml_info *vinfo, unsigned long offset) +{ + unsigned long aoffset; + unsigned i; + + for (i = 0; i < vinfo->num_areas; ++i) { + aoffset = offset - (vinfo->vram[i].phys - vinfo->vram_start); + + if (aoffset < vinfo->vram[i].size) { + return 0; + } + } + + return -EINVAL; +} + +/* + * Remap the MMIO register spaces of the VDC and the GPU. + */ + +static int vmlfb_enable_mmio(struct vml_par *par) +{ + int err; + + par->vdc_mem_base = pci_resource_start(par->vdc, 0); + par->vdc_mem_size = pci_resource_len(par->vdc, 0); + if (!request_mem_region(par->vdc_mem_base, par->vdc_mem_size, "vmlfb")) { + printk(KERN_ERR MODULE_NAME + ": Could not claim display controller MMIO.\n"); + return -EBUSY; + } + par->vdc_mem = ioremap_nocache(par->vdc_mem_base, par->vdc_mem_size); + if (par->vdc_mem == NULL) { + printk(KERN_ERR MODULE_NAME + ": Could not map display controller MMIO.\n"); + err = -ENOMEM; + goto out_err_0; + } + + par->gpu_mem_base = pci_resource_start(par->gpu, 0); + par->gpu_mem_size = pci_resource_len(par->gpu, 0); + if (!request_mem_region(par->gpu_mem_base, par->gpu_mem_size, "vmlfb")) { + printk(KERN_ERR MODULE_NAME ": Could not claim GPU MMIO.\n"); + err = -EBUSY; + goto out_err_1; + } + par->gpu_mem = ioremap_nocache(par->gpu_mem_base, par->gpu_mem_size); + if (par->gpu_mem == NULL) { + printk(KERN_ERR MODULE_NAME ": Could not map GPU MMIO.\n"); + err = -ENOMEM; + goto out_err_2; + } + + return 0; + +out_err_2: + release_mem_region(par->gpu_mem_base, par->gpu_mem_size); +out_err_1: + iounmap(par->vdc_mem); +out_err_0: + release_mem_region(par->vdc_mem_base, par->vdc_mem_size); + return err; +} + +/* + * Unmap the VDC and GPU register spaces. + */ + +static void vmlfb_disable_mmio(struct vml_par *par) +{ + iounmap(par->gpu_mem); + release_mem_region(par->gpu_mem_base, par->gpu_mem_size); + iounmap(par->vdc_mem); + release_mem_region(par->vdc_mem_base, par->vdc_mem_size); +} + +/* + * Release and uninit the VDC and GPU. + */ + +static void vmlfb_release_devices(struct vml_par *par) +{ + if (atomic_dec_and_test(&par->refcount)) { + pci_set_drvdata(par->vdc, NULL); + pci_disable_device(par->gpu); + pci_disable_device(par->vdc); + } +} + +/* + * Free up allocated resources for a device. + */ + +static void __devexit vml_pci_remove(struct pci_dev *dev) +{ + struct fb_info *info; + struct vml_info *vinfo; + struct vml_par *par; + + info = pci_get_drvdata(dev); + if (info) { + vinfo = container_of(info, struct vml_info, info); + par = vinfo->par; + mutex_lock(&vml_mutex); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + vmlfb_free_vram(vinfo); + vmlfb_disable_mmio(par); + vmlfb_release_devices(par); + kfree(vinfo); + kfree(par); + mutex_unlock(&vml_mutex); + } +} + +static void vmlfb_set_pref_pixel_format(struct fb_var_screeninfo *var) +{ + switch (var->bits_per_pixel) { + case 16: + var->blue.offset = 0; + var->blue.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->red.offset = 10; + var->red.length = 5; + var->transp.offset = 15; + var->transp.length = 1; + break; + case 32: + var->blue.offset = 0; + var->blue.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->red.offset = 16; + var->red.length = 8; + var->transp.offset = 24; + var->transp.length = 0; + break; + default: + break; + } + + var->blue.msb_right = var->green.msb_right = + var->red.msb_right = var->transp.msb_right = 0; +} + +/* + * Device initialization. + * We initialize one vml_par struct per device and one vml_info + * struct per pipe. Currently we have only one pipe. + */ + +static int __devinit vml_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct vml_info *vinfo; + struct fb_info *info; + struct vml_par *par; + int err = 0; + + par = kzalloc(sizeof(*par), GFP_KERNEL); + if (par == NULL) + return -ENOMEM; + + vinfo = kzalloc(sizeof(*vinfo), GFP_KERNEL); + if (vinfo == NULL) { + err = -ENOMEM; + goto out_err_0; + } + + vinfo->par = par; + par->vdc = dev; + atomic_set(&par->refcount, 1); + + switch (id->device) { + case VML_DEVICE_VDC: + if ((err = vmlfb_get_gpu(par))) + goto out_err_1; + pci_set_drvdata(dev, &vinfo->info); + break; + default: + err = -ENODEV; + goto out_err_1; + break; + } + + info = &vinfo->info; + info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK; + + err = vmlfb_enable_mmio(par); + if (err) + goto out_err_2; + + err = vmlfb_alloc_vram(vinfo, vml_mem_requested, + vml_mem_contig, vml_mem_min); + if (err) + goto out_err_3; + + strcpy(info->fix.id, "Vermilion Range"); + info->fix.mmio_start = 0; + info->fix.mmio_len = 0; + info->fix.smem_start = vinfo->vram_start; + info->fix.smem_len = vinfo->vram_contig_size; + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.ypanstep = 1; + info->fix.xpanstep = 1; + info->fix.ywrapstep = 0; + info->fix.accel = FB_ACCEL_NONE; + info->screen_base = vinfo->vram_logical; + info->pseudo_palette = vinfo->pseudo_palette; + info->par = par; + info->fbops = &vmlfb_ops; + info->device = &dev->dev; + + INIT_LIST_HEAD(&vinfo->head); + vinfo->pipe_disabled = 1; + vinfo->cur_blank_mode = FB_BLANK_UNBLANK; + + info->var.grayscale = 0; + info->var.bits_per_pixel = 16; + vmlfb_set_pref_pixel_format(&info->var); + + if (!fb_find_mode + (&info->var, info, vml_default_mode, NULL, 0, &defaultmode, 16)) { + printk(KERN_ERR MODULE_NAME ": Could not find initial mode\n"); + } + + if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) { + err = -ENOMEM; + goto out_err_4; + } + + err = register_framebuffer(info); + if (err) { + printk(KERN_ERR MODULE_NAME ": Register framebuffer error.\n"); + goto out_err_5; + } + + printk("Initialized vmlfb\n"); + + return 0; + +out_err_5: + fb_dealloc_cmap(&info->cmap); +out_err_4: + vmlfb_free_vram(vinfo); +out_err_3: + vmlfb_disable_mmio(par); +out_err_2: + vmlfb_release_devices(par); +out_err_1: + kfree(vinfo); +out_err_0: + kfree(par); + return err; +} + +static int vmlfb_open(struct fb_info *info, int user) +{ + /* + * Save registers here? + */ + return 0; +} + +static int vmlfb_release(struct fb_info *info, int user) +{ + /* + * Restore registers here. + */ + + return 0; +} + +static int vml_nearest_clock(int clock) +{ + + int i; + int cur_index; + int cur_diff; + int diff; + + cur_index = 0; + cur_diff = clock - vml_clocks[0]; + cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff; + for (i = 1; i < vml_num_clocks; ++i) { + diff = clock - vml_clocks[i]; + diff = (diff < 0) ? -diff : diff; + if (diff < cur_diff) { + cur_index = i; + cur_diff = diff; + } + } + return vml_clocks[cur_index]; +} + +static int vmlfb_check_var_locked(struct fb_var_screeninfo *var, + struct vml_info *vinfo) +{ + u32 pitch; + u64 mem; + int nearest_clock; + int clock; + int clock_diff; + struct fb_var_screeninfo v; + + v = *var; + clock = PICOS2KHZ(var->pixclock); + + if (subsys && subsys->nearest_clock) { + nearest_clock = subsys->nearest_clock(subsys, clock); + } else { + nearest_clock = vml_nearest_clock(clock); + } + + /* + * Accept a 20% diff. + */ + + clock_diff = nearest_clock - clock; + clock_diff = (clock_diff < 0) ? -clock_diff : clock_diff; + if (clock_diff > clock / 5) { +#if 0 + printk(KERN_DEBUG MODULE_NAME ": Diff failure. %d %d\n",clock_diff,clock); +#endif + return -EINVAL; + } + + v.pixclock = KHZ2PICOS(nearest_clock); + + if (var->xres > VML_MAX_XRES || var->yres > VML_MAX_YRES) { + printk(KERN_DEBUG MODULE_NAME ": Resolution failure.\n"); + return -EINVAL; + } + if (var->xres_virtual > VML_MAX_XRES_VIRTUAL) { + printk(KERN_DEBUG MODULE_NAME + ": Virtual resolution failure.\n"); + return -EINVAL; + } + switch (v.bits_per_pixel) { + case 0 ... 16: + v.bits_per_pixel = 16; + break; + case 17 ... 32: + v.bits_per_pixel = 32; + break; + default: + printk(KERN_DEBUG MODULE_NAME ": Invalid bpp: %d.\n", + var->bits_per_pixel); + return -EINVAL; + } + + pitch = __ALIGN_MASK((var->xres * var->bits_per_pixel) >> 3, 0x3F); + mem = pitch * var->yres_virtual; + if (mem > vinfo->vram_contig_size) { + return -ENOMEM; + } + + switch (v.bits_per_pixel) { + case 16: + if (var->blue.offset != 0 || + var->blue.length != 5 || + var->green.offset != 5 || + var->green.length != 5 || + var->red.offset != 10 || + var->red.length != 5 || + var->transp.offset != 15 || var->transp.length != 1) { + vmlfb_set_pref_pixel_format(&v); + } + break; + case 32: + if (var->blue.offset != 0 || + var->blue.length != 8 || + var->green.offset != 8 || + var->green.length != 8 || + var->red.offset != 16 || + var->red.length != 8 || + (var->transp.length != 0 && var->transp.length != 8) || + (var->transp.length == 8 && var->transp.offset != 24)) { + vmlfb_set_pref_pixel_format(&v); + } + break; + default: + return -EINVAL; + } + + *var = v; + + return 0; +} + +static int vmlfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct vml_info *vinfo = container_of(info, struct vml_info, info); + int ret; + + mutex_lock(&vml_mutex); + ret = vmlfb_check_var_locked(var, vinfo); + mutex_unlock(&vml_mutex); + + return ret; +} + +static void vml_wait_vblank(struct vml_info *vinfo) +{ + /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */ + mdelay(20); +} + +static void vmlfb_disable_pipe(struct vml_info *vinfo) +{ + struct vml_par *par = vinfo->par; + + /* Disable the MDVO pad */ + VML_WRITE32(par, VML_RCOMPSTAT, 0); + while (!(VML_READ32(par, VML_RCOMPSTAT) & VML_MDVO_VDC_I_RCOMP)) ; + + /* Disable display planes */ + VML_WRITE32(par, VML_DSPCCNTR, + VML_READ32(par, VML_DSPCCNTR) & ~VML_GFX_ENABLE); + (void)VML_READ32(par, VML_DSPCCNTR); + /* Wait for vblank for the disable to take effect */ + vml_wait_vblank(vinfo); + + /* Next, disable display pipes */ + VML_WRITE32(par, VML_PIPEACONF, 0); + (void)VML_READ32(par, VML_PIPEACONF); + + vinfo->pipe_disabled = 1; +} + +#ifdef VERMILION_DEBUG +static void vml_dump_regs(struct vml_info *vinfo) +{ + struct vml_par *par = vinfo->par; + + printk(KERN_DEBUG MODULE_NAME ": Modesetting register dump:\n"); + printk(KERN_DEBUG MODULE_NAME ": \tHTOTAL_A : 0x%08x\n", + (unsigned)VML_READ32(par, VML_HTOTAL_A)); + printk(KERN_DEBUG MODULE_NAME ": \tHBLANK_A : 0x%08x\n", + (unsigned)VML_READ32(par, VML_HBLANK_A)); + printk(KERN_DEBUG MODULE_NAME ": \tHSYNC_A : 0x%08x\n", + (unsigned)VML_READ32(par, VML_HSYNC_A)); + printk(KERN_DEBUG MODULE_NAME ": \tVTOTAL_A : 0x%08x\n", + (unsigned)VML_READ32(par, VML_VTOTAL_A)); + printk(KERN_DEBUG MODULE_NAME ": \tVBLANK_A : 0x%08x\n", + (unsigned)VML_READ32(par, VML_VBLANK_A)); + printk(KERN_DEBUG MODULE_NAME ": \tVSYNC_A : 0x%08x\n", + (unsigned)VML_READ32(par, VML_VSYNC_A)); + printk(KERN_DEBUG MODULE_NAME ": \tDSPCSTRIDE : 0x%08x\n", + (unsigned)VML_READ32(par, VML_DSPCSTRIDE)); + printk(KERN_DEBUG MODULE_NAME ": \tDSPCSIZE : 0x%08x\n", + (unsigned)VML_READ32(par, VML_DSPCSIZE)); + printk(KERN_DEBUG MODULE_NAME ": \tDSPCPOS : 0x%08x\n", + (unsigned)VML_READ32(par, VML_DSPCPOS)); + printk(KERN_DEBUG MODULE_NAME ": \tDSPARB : 0x%08x\n", + (unsigned)VML_READ32(par, VML_DSPARB)); + printk(KERN_DEBUG MODULE_NAME ": \tDSPCADDR : 0x%08x\n", + (unsigned)VML_READ32(par, VML_DSPCADDR)); + printk(KERN_DEBUG MODULE_NAME ": \tBCLRPAT_A : 0x%08x\n", + (unsigned)VML_READ32(par, VML_BCLRPAT_A)); + printk(KERN_DEBUG MODULE_NAME ": \tCANVSCLR_A : 0x%08x\n", + (unsigned)VML_READ32(par, VML_CANVSCLR_A)); + printk(KERN_DEBUG MODULE_NAME ": \tPIPEASRC : 0x%08x\n", + (unsigned)VML_READ32(par, VML_PIPEASRC)); + printk(KERN_DEBUG MODULE_NAME ": \tPIPEACONF : 0x%08x\n", + (unsigned)VML_READ32(par, VML_PIPEACONF)); + printk(KERN_DEBUG MODULE_NAME ": \tDSPCCNTR : 0x%08x\n", + (unsigned)VML_READ32(par, VML_DSPCCNTR)); + printk(KERN_DEBUG MODULE_NAME ": \tRCOMPSTAT : 0x%08x\n", + (unsigned)VML_READ32(par, VML_RCOMPSTAT)); + printk(KERN_DEBUG MODULE_NAME ": End of modesetting register dump.\n"); +} +#endif + +static int vmlfb_set_par_locked(struct vml_info *vinfo) +{ + struct vml_par *par = vinfo->par; + struct fb_info *info = &vinfo->info; + struct fb_var_screeninfo *var = &info->var; + u32 htotal, hactive, hblank_start, hblank_end, hsync_start, hsync_end; + u32 vtotal, vactive, vblank_start, vblank_end, vsync_start, vsync_end; + u32 dspcntr; + int clock; + + vinfo->bytes_per_pixel = var->bits_per_pixel >> 3; + vinfo->stride = + __ALIGN_MASK(var->xres_virtual * vinfo->bytes_per_pixel, 0x3F); + info->fix.line_length = vinfo->stride; + + if (!subsys) + return 0; + + htotal = + var->xres + var->right_margin + var->hsync_len + var->left_margin; + hactive = var->xres; + hblank_start = var->xres; + hblank_end = htotal; + hsync_start = hactive + var->right_margin; + hsync_end = hsync_start + var->hsync_len; + + vtotal = + var->yres + var->lower_margin + var->vsync_len + var->upper_margin; + vactive = var->yres; + vblank_start = var->yres; + vblank_end = vtotal; + vsync_start = vactive + var->lower_margin; + vsync_end = vsync_start + var->vsync_len; + + dspcntr = VML_GFX_ENABLE | VML_GFX_GAMMABYPASS; + clock = PICOS2KHZ(var->pixclock); + + if (subsys->nearest_clock) { + clock = subsys->nearest_clock(subsys, clock); + } else { + clock = vml_nearest_clock(clock); + } + printk(KERN_DEBUG MODULE_NAME + ": Set mode Hfreq : %d kHz, Vfreq : %d Hz.\n", clock / htotal, + ((clock / htotal) * 1000) / vtotal); + + switch (var->bits_per_pixel) { + case 16: + dspcntr |= VML_GFX_ARGB1555; + break; + case 32: + if (var->transp.length == 8) + dspcntr |= VML_GFX_ARGB8888 | VML_GFX_ALPHAMULT; + else + dspcntr |= VML_GFX_RGB0888; + break; + default: + return -EINVAL; + } + + vmlfb_disable_pipe(vinfo); + mb(); + + if (subsys->set_clock) + subsys->set_clock(subsys, clock); + else + return -EINVAL; + + VML_WRITE32(par, VML_HTOTAL_A, ((htotal - 1) << 16) | (hactive - 1)); + VML_WRITE32(par, VML_HBLANK_A, + ((hblank_end - 1) << 16) | (hblank_start - 1)); + VML_WRITE32(par, VML_HSYNC_A, + ((hsync_end - 1) << 16) | (hsync_start - 1)); + VML_WRITE32(par, VML_VTOTAL_A, ((vtotal - 1) << 16) | (vactive - 1)); + VML_WRITE32(par, VML_VBLANK_A, + ((vblank_end - 1) << 16) | (vblank_start - 1)); + VML_WRITE32(par, VML_VSYNC_A, + ((vsync_end - 1) << 16) | (vsync_start - 1)); + VML_WRITE32(par, VML_DSPCSTRIDE, vinfo->stride); + VML_WRITE32(par, VML_DSPCSIZE, + ((var->yres - 1) << 16) | (var->xres - 1)); + VML_WRITE32(par, VML_DSPCPOS, 0x00000000); + VML_WRITE32(par, VML_DSPARB, VML_FIFO_DEFAULT); + VML_WRITE32(par, VML_BCLRPAT_A, 0x00000000); + VML_WRITE32(par, VML_CANVSCLR_A, 0x00000000); + VML_WRITE32(par, VML_PIPEASRC, + ((var->xres - 1) << 16) | (var->yres - 1)); + + wmb(); + VML_WRITE32(par, VML_PIPEACONF, VML_PIPE_ENABLE); + wmb(); + VML_WRITE32(par, VML_DSPCCNTR, dspcntr); + wmb(); + VML_WRITE32(par, VML_DSPCADDR, (u32) vinfo->vram_start + + var->yoffset * vinfo->stride + + var->xoffset * vinfo->bytes_per_pixel); + + VML_WRITE32(par, VML_RCOMPSTAT, VML_MDVO_PAD_ENABLE); + + while (!(VML_READ32(par, VML_RCOMPSTAT) & + (VML_MDVO_VDC_I_RCOMP | VML_MDVO_PAD_ENABLE))) ; + + vinfo->pipe_disabled = 0; +#ifdef VERMILION_DEBUG + vml_dump_regs(vinfo); +#endif + + return 0; +} + +static int vmlfb_set_par(struct fb_info *info) +{ + struct vml_info *vinfo = container_of(info, struct vml_info, info); + int ret; + + mutex_lock(&vml_mutex); + list_del(&vinfo->head); + list_add(&vinfo->head, (subsys) ? &global_has_mode : &global_no_mode); + ret = vmlfb_set_par_locked(vinfo); + + mutex_unlock(&vml_mutex); + return ret; +} + +static int vmlfb_blank_locked(struct vml_info *vinfo) +{ + struct vml_par *par = vinfo->par; + u32 cur = VML_READ32(par, VML_PIPEACONF); + + switch (vinfo->cur_blank_mode) { + case FB_BLANK_UNBLANK: + if (vinfo->pipe_disabled) { + vmlfb_set_par_locked(vinfo); + } + VML_WRITE32(par, VML_PIPEACONF, cur & ~VML_PIPE_FORCE_BORDER); + (void)VML_READ32(par, VML_PIPEACONF); + break; + case FB_BLANK_NORMAL: + if (vinfo->pipe_disabled) { + vmlfb_set_par_locked(vinfo); + } + VML_WRITE32(par, VML_PIPEACONF, cur | VML_PIPE_FORCE_BORDER); + (void)VML_READ32(par, VML_PIPEACONF); + break; + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + if (!vinfo->pipe_disabled) { + vmlfb_disable_pipe(vinfo); + } + break; + case FB_BLANK_POWERDOWN: + if (!vinfo->pipe_disabled) { + vmlfb_disable_pipe(vinfo); + } + break; + default: + return -EINVAL; + } + + return 0; +} + +static int vmlfb_blank(int blank_mode, struct fb_info *info) +{ + struct vml_info *vinfo = container_of(info, struct vml_info, info); + int ret; + + mutex_lock(&vml_mutex); + vinfo->cur_blank_mode = blank_mode; + ret = vmlfb_blank_locked(vinfo); + mutex_unlock(&vml_mutex); + return ret; +} + +static int vmlfb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct vml_info *vinfo = container_of(info, struct vml_info, info); + struct vml_par *par = vinfo->par; + + mutex_lock(&vml_mutex); + VML_WRITE32(par, VML_DSPCADDR, (u32) vinfo->vram_start + + var->yoffset * vinfo->stride + + var->xoffset * vinfo->bytes_per_pixel); + (void)VML_READ32(par, VML_DSPCADDR); + mutex_unlock(&vml_mutex); + + return 0; +} + +static int vmlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + u32 v; + + if (regno >= 16) + return -EINVAL; + + if (info->var.grayscale) { + red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; + } + + if (info->fix.visual != FB_VISUAL_TRUECOLOR) + return -EINVAL; + + red = VML_TOHW(red, info->var.red.length); + blue = VML_TOHW(blue, info->var.blue.length); + green = VML_TOHW(green, info->var.green.length); + transp = VML_TOHW(transp, info->var.transp.length); + + v = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + + switch (info->var.bits_per_pixel) { + case 16: + ((u32 *) info->pseudo_palette)[regno] = v; + break; + case 24: + case 32: + ((u32 *) info->pseudo_palette)[regno] = v; + break; + } + return 0; +} + +static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + struct vml_info *vinfo = container_of(info, struct vml_info, info); + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + int ret; + + if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) + return -EINVAL; + if (offset + size > vinfo->vram_contig_size) + return -EINVAL; + ret = vmlfb_vram_offset(vinfo, offset); + if (ret) + return -EINVAL; + offset += vinfo->vram_start; + pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; + pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; + vma->vm_flags |= VM_RESERVED | VM_IO; + if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, + size, vma->vm_page_prot)) + return -EAGAIN; + return 0; +} + +static int vmlfb_sync(struct fb_info *info) +{ + return 0; +} + +static int vmlfb_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + return -EINVAL; /* just to force soft_cursor() call */ +} + +static struct fb_ops vmlfb_ops = { + .owner = THIS_MODULE, + .fb_open = vmlfb_open, + .fb_release = vmlfb_release, + .fb_check_var = vmlfb_check_var, + .fb_set_par = vmlfb_set_par, + .fb_blank = vmlfb_blank, + .fb_pan_display = vmlfb_pan_display, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_cursor = vmlfb_cursor, + .fb_sync = vmlfb_sync, + .fb_mmap = vmlfb_mmap, + .fb_setcolreg = vmlfb_setcolreg +}; + +static struct pci_device_id vml_ids[] = { + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, VML_DEVICE_VDC)}, + {0} +}; + +static struct pci_driver vmlfb_pci_driver = { + .name = "vmlfb", + .id_table = vml_ids, + .probe = vml_pci_probe, + .remove = __devexit_p(vml_pci_remove) +}; + +static void __exit vmlfb_cleanup(void) +{ + pci_unregister_driver(&vmlfb_pci_driver); +} + +static int __init vmlfb_init(void) +{ + +#ifndef MODULE + char *option = NULL; + + if (fb_get_options(MODULE_NAME, &option)) + return -ENODEV; +#endif + + printk(KERN_DEBUG MODULE_NAME ": initializing\n"); + mutex_init(&vml_mutex); + INIT_LIST_HEAD(&global_no_mode); + INIT_LIST_HEAD(&global_has_mode); + + return pci_register_driver(&vmlfb_pci_driver); +} + +int vmlfb_register_subsys(struct vml_sys *sys) +{ + struct vml_info *entry; + struct list_head *list; + u32 save_activate; + + mutex_lock(&vml_mutex); + if (subsys != NULL) { + subsys->restore(subsys); + } + subsys = sys; + subsys->save(subsys); + + /* + * We need to restart list traversal for each item, since we + * release the list mutex in the loop. + */ + + list = global_no_mode.next; + while (list != &global_no_mode) { + list_del_init(list); + entry = list_entry(list, struct vml_info, head); + + /* + * First, try the current mode which might not be + * completely validated with respect to the pixel clock. + */ + + if (!vmlfb_check_var_locked(&entry->info.var, entry)) { + vmlfb_set_par_locked(entry); + list_add_tail(list, &global_has_mode); + } else { + + /* + * Didn't work. Try to find another mode, + * that matches this subsys. + */ + + mutex_unlock(&vml_mutex); + save_activate = entry->info.var.activate; + entry->info.var.bits_per_pixel = 16; + vmlfb_set_pref_pixel_format(&entry->info.var); + if (fb_find_mode(&entry->info.var, + &entry->info, + vml_default_mode, NULL, 0, NULL, 16)) { + entry->info.var.activate |= + FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; + fb_set_var(&entry->info, &entry->info.var); + } else { + printk(KERN_ERR MODULE_NAME + ": Sorry. no mode found for this subsys.\n"); + } + entry->info.var.activate = save_activate; + mutex_lock(&vml_mutex); + } + vmlfb_blank_locked(entry); + list = global_no_mode.next; + } + mutex_unlock(&vml_mutex); + + printk(KERN_DEBUG MODULE_NAME ": Registered %s subsystem.\n", + subsys->name ? subsys->name : "unknown"); + return 0; +} + +EXPORT_SYMBOL_GPL(vmlfb_register_subsys); + +void vmlfb_unregister_subsys(struct vml_sys *sys) +{ + struct vml_info *entry, *next; + + mutex_lock(&vml_mutex); + if (subsys != sys) { + mutex_unlock(&vml_mutex); + return; + } + subsys->restore(subsys); + subsys = NULL; + list_for_each_entry_safe(entry, next, &global_has_mode, head) { + printk(KERN_DEBUG MODULE_NAME ": subsys disable pipe\n"); + vmlfb_disable_pipe(entry); + list_del(&entry->head); + list_add_tail(&entry->head, &global_no_mode); + } + mutex_unlock(&vml_mutex); +} + +EXPORT_SYMBOL_GPL(vmlfb_unregister_subsys); + +module_init(vmlfb_init); +module_exit(vmlfb_cleanup); + +MODULE_AUTHOR("Tungsten Graphics"); +MODULE_DESCRIPTION("Initialization of the Vermilion display devices"); +MODULE_VERSION("1.0.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h new file mode 100644 index 0000000..1fc6695 --- /dev/null +++ b/drivers/video/vermilion/vermilion.h @@ -0,0 +1,260 @@ +/* + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * This file is part of the Vermilion Range fb driver. + * The Vermilion Range fb driver is free software; + * you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The Vermilion Range fb driver is distributed + * in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this driver; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> + */ + +#ifndef _VERMILION_H_ +#define _VERMILION_H_ + +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/pci.h> +#include <asm/atomic.h> +#include <linux/mutex.h> + +#define VML_DEVICE_GPU 0x5002 +#define VML_DEVICE_VDC 0x5009 + +#define VML_VRAM_AREAS 3 +#define VML_MAX_XRES 1024 +#define VML_MAX_YRES 768 +#define VML_MAX_XRES_VIRTUAL 1040 + +/* + * Display controller registers: + */ + +/* Display controller 10-bit color representation */ + +#define VML_R_MASK 0x3FF00000 +#define VML_R_SHIFT 20 +#define VML_G_MASK 0x000FFC00 +#define VML_G_SHIFT 10 +#define VML_B_MASK 0x000003FF +#define VML_B_SHIFT 0 + +/* Graphics plane control */ +#define VML_DSPCCNTR 0x00072180 +#define VML_GFX_ENABLE 0x80000000 +#define VML_GFX_GAMMABYPASS 0x40000000 +#define VML_GFX_ARGB1555 0x0C000000 +#define VML_GFX_RGB0888 0x18000000 +#define VML_GFX_ARGB8888 0x1C000000 +#define VML_GFX_ALPHACONST 0x02000000 +#define VML_GFX_ALPHAMULT 0x01000000 +#define VML_GFX_CONST_ALPHA 0x000000FF + +/* Graphics plane start address. Pixel aligned. */ +#define VML_DSPCADDR 0x00072184 + +/* Graphics plane stride register. */ +#define VML_DSPCSTRIDE 0x00072188 + +/* Graphics plane position register. */ +#define VML_DSPCPOS 0x0007218C +#define VML_POS_YMASK 0x0FFF0000 +#define VML_POS_YSHIFT 16 +#define VML_POS_XMASK 0x00000FFF +#define VML_POS_XSHIFT 0 + +/* Graphics plane height and width */ +#define VML_DSPCSIZE 0x00072190 +#define VML_SIZE_HMASK 0x0FFF0000 +#define VML_SIZE_HSHIFT 16 +#define VML_SISE_WMASK 0x00000FFF +#define VML_SIZE_WSHIFT 0 + +/* Graphics plane gamma correction lookup table registers (129 * 32 bits) */ +#define VML_DSPCGAMLUT 0x00072200 + +/* Pixel video output configuration register */ +#define VML_PVOCONFIG 0x00061140 +#define VML_CONFIG_BASE 0x80000000 +#define VML_CONFIG_PIXEL_SWAP 0x04000000 +#define VML_CONFIG_DE_INV 0x01000000 +#define VML_CONFIG_HREF_INV 0x00400000 +#define VML_CONFIG_VREF_INV 0x00100000 +#define VML_CONFIG_CLK_INV 0x00040000 +#define VML_CONFIG_CLK_DIV2 0x00010000 +#define VML_CONFIG_ESTRB_INV 0x00008000 + +/* Pipe A Horizontal total register */ +#define VML_HTOTAL_A 0x00060000 +#define VML_HTOTAL_MASK 0x1FFF0000 +#define VML_HTOTAL_SHIFT 16 +#define VML_HTOTAL_VAL 8192 +#define VML_HACTIVE_MASK 0x000007FF +#define VML_HACTIVE_SHIFT 0 +#define VML_HACTIVE_VAL 4096 + +/* Pipe A Horizontal Blank register */ +#define VML_HBLANK_A 0x00060004 +#define VML_HBLANK_END_MASK 0x1FFF0000 +#define VML_HBLANK_END_SHIFT 16 +#define VML_HBLANK_END_VAL 8192 +#define VML_HBLANK_START_MASK 0x00001FFF +#define VML_HBLANK_START_SHIFT 0 +#define VML_HBLANK_START_VAL 8192 + +/* Pipe A Horizontal Sync register */ +#define VML_HSYNC_A 0x00060008 +#define VML_HSYNC_END_MASK 0x1FFF0000 +#define VML_HSYNC_END_SHIFT 16 +#define VML_HSYNC_END_VAL 8192 +#define VML_HSYNC_START_MASK 0x00001FFF +#define VML_HSYNC_START_SHIFT 0 +#define VML_HSYNC_START_VAL 8192 + +/* Pipe A Vertical total register */ +#define VML_VTOTAL_A 0x0006000C +#define VML_VTOTAL_MASK 0x1FFF0000 +#define VML_VTOTAL_SHIFT 16 +#define VML_VTOTAL_VAL 8192 +#define VML_VACTIVE_MASK 0x000007FF +#define VML_VACTIVE_SHIFT 0 +#define VML_VACTIVE_VAL 4096 + +/* Pipe A Vertical Blank register */ +#define VML_VBLANK_A 0x00060010 +#define VML_VBLANK_END_MASK 0x1FFF0000 +#define VML_VBLANK_END_SHIFT 16 +#define VML_VBLANK_END_VAL 8192 +#define VML_VBLANK_START_MASK 0x00001FFF +#define VML_VBLANK_START_SHIFT 0 +#define VML_VBLANK_START_VAL 8192 + +/* Pipe A Vertical Sync register */ +#define VML_VSYNC_A 0x00060014 +#define VML_VSYNC_END_MASK 0x1FFF0000 +#define VML_VSYNC_END_SHIFT 16 +#define VML_VSYNC_END_VAL 8192 +#define VML_VSYNC_START_MASK 0x00001FFF +#define VML_VSYNC_START_SHIFT 0 +#define VML_VSYNC_START_VAL 8192 + +/* Pipe A Source Image size (minus one - equal to active size) + * Programmable while pipe is enabled. + */ +#define VML_PIPEASRC 0x0006001C +#define VML_PIPEASRC_HMASK 0x0FFF0000 +#define VML_PIPEASRC_HSHIFT 16 +#define VML_PIPEASRC_VMASK 0x00000FFF +#define VML_PIPEASRC_VSHIFT 0 + +/* Pipe A Border Color Pattern register (10 bit color) */ +#define VML_BCLRPAT_A 0x00060020 + +/* Pipe A Canvas Color register (10 bit color) */ +#define VML_CANVSCLR_A 0x00060024 + +/* Pipe A Configuration register */ +#define VML_PIPEACONF 0x00070008 +#define VML_PIPE_BASE 0x00000000 +#define VML_PIPE_ENABLE 0x80000000 +#define VML_PIPE_FORCE_BORDER 0x02000000 +#define VML_PIPE_PLANES_OFF 0x00080000 +#define VML_PIPE_ARGB_OUTPUT_MODE 0x00040000 + +/* Pipe A FIFO setting */ +#define VML_DSPARB 0x00070030 +#define VML_FIFO_DEFAULT 0x00001D9C + +/* MDVO rcomp status & pads control register */ +#define VML_RCOMPSTAT 0x00070048 +#define VML_MDVO_VDC_I_RCOMP 0x80000000 +#define VML_MDVO_POWERSAVE_OFF 0x00000008 +#define VML_MDVO_PAD_ENABLE 0x00000004 +#define VML_MDVO_PULLDOWN_ENABLE 0x00000001 + +struct vml_par { + struct pci_dev *vdc; + u64 vdc_mem_base; + u64 vdc_mem_size; + char __iomem *vdc_mem; + + struct pci_dev *gpu; + u64 gpu_mem_base; + u64 gpu_mem_size; + char __iomem *gpu_mem; + + atomic_t refcount; +}; + +struct vram_area { + unsigned long logical; + unsigned long phys; + unsigned long size; + unsigned order; +}; + +struct vml_info { + struct fb_info info; + struct vml_par *par; + struct list_head head; + struct vram_area vram[VML_VRAM_AREAS]; + u64 vram_start; + u64 vram_contig_size; + u32 num_areas; + void __iomem *vram_logical; + u32 pseudo_palette[16]; + u32 stride; + u32 bytes_per_pixel; + atomic_t vmas; + int cur_blank_mode; + int pipe_disabled; +}; + +/* + * Subsystem + */ + +struct vml_sys { + char *name; + + /* + * Save / Restore; + */ + + int (*save) (struct vml_sys * sys); + int (*restore) (struct vml_sys * sys); + + /* + * PLL programming; + */ + + int (*set_clock) (struct vml_sys * sys, int clock); + int (*nearest_clock) (const struct vml_sys * sys, int clock); +}; + +extern int vmlfb_register_subsys(struct vml_sys *sys); +extern void vmlfb_unregister_subsys(struct vml_sys *sys); + +#define VML_READ32(_par, _offset) \ + (ioread32((_par)->vdc_mem + (_offset))) +#define VML_WRITE32(_par, _offset, _value) \ + iowrite32(_value, (_par)->vdc_mem + (_offset)) + +#endif diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index a9b99b0..64ee78c 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -84,13 +84,15 @@ static int vfb_mmap(struct fb_info *info, struct vm_area_struct *vma); static struct fb_ops vfb_ops = { + .fb_read = fb_sys_read, + .fb_write = fb_sys_write, .fb_check_var = vfb_check_var, .fb_set_par = vfb_set_par, .fb_setcolreg = vfb_setcolreg, .fb_pan_display = vfb_pan_display, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, .fb_mmap = vfb_mmap, }; diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index ec4c7dc..2a14d28 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1378,6 +1378,8 @@ static int __init vga16fb_probe(struct platform_device *dev) info->fbops = &vga16fb_ops; info->var = vga16fb_defined; info->fix = vga16fb_fix; + /* supports rectangles with widths of multiples of 8 */ + info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31; info->flags = FBINFO_FLAG_DEFAULT | FBINFO_HWACCEL_YPAN; diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c index d94efaf..b91c466 100644 --- a/drivers/video/vgastate.c +++ b/drivers/video/vgastate.c @@ -50,23 +50,28 @@ static void save_vga_text(struct vgastate *state, void __iomem *fbbase) struct regstate *saved = (struct regstate *) state->vidstate; int i; u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4; + unsigned short iobase; /* if in graphics mode, no need to save */ + misc = vga_r(state->vgabase, VGA_MIS_R); + iobase = (misc & 1) ? 0x3d0 : 0x3b0; + + vga_r(state->vgabase, iobase + 0xa); + vga_w(state->vgabase, VGA_ATT_W, 0x00); attr10 = vga_rattr(state->vgabase, 0x10); + vga_r(state->vgabase, iobase + 0xa); + vga_w(state->vgabase, VGA_ATT_W, 0x20); + if (attr10 & 1) return; - + /* save regs */ - misc = vga_r(state->vgabase, VGA_MIS_R); gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ); gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE); gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC); seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE); seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE); - /* force graphics mode */ - vga_w(state->vgabase, VGA_MIS_W, misc | 1); - /* blank screen */ seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE); vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); @@ -115,15 +120,12 @@ static void save_vga_text(struct vgastate *state, void __iomem *fbbase) } /* restore regs */ - vga_wattr(state->vgabase, 0x10, attr10); - vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4); vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5); vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6); - vga_w(state->vgabase, VGA_MIS_W, misc); /* unblank screen */ vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); @@ -137,11 +139,10 @@ static void restore_vga_text(struct vgastate *state, void __iomem *fbbase) { struct regstate *saved = (struct regstate *) state->vidstate; int i; - u8 misc, gr1, gr3, gr4, gr5, gr6, gr8; + u8 gr1, gr3, gr4, gr5, gr6, gr8; u8 seq1, seq2, seq4; /* save regs */ - misc = vga_r(state->vgabase, VGA_MIS_R); gr1 = vga_rgfx(state->vgabase, VGA_GFX_SR_ENABLE); gr3 = vga_rgfx(state->vgabase, VGA_GFX_DATA_ROTATE); gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ); @@ -151,9 +152,6 @@ static void restore_vga_text(struct vgastate *state, void __iomem *fbbase) seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE); seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE); - /* force graphics mode */ - vga_w(state->vgabase, VGA_MIS_W, misc | 1); - /* blank screen */ seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE); vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); @@ -213,8 +211,6 @@ static void restore_vga_text(struct vgastate *state, void __iomem *fbbase) vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); /* restore regs */ - vga_w(state->vgabase, VGA_MIS_W, misc); - vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, gr1); vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, gr3); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4); diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c new file mode 100644 index 0000000..5e9755e --- /dev/null +++ b/drivers/video/vt8623fb.c @@ -0,0 +1,927 @@ +/* + * linux/drivers/video/vt8623fb.c - fbdev driver for + * integrated graphic core in VIA VT8623 [CLE266] chipset + * + * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Code is based on s3fb, some parts are from David Boucher's viafb + * (http://davesdomain.org.uk/viafb/) + */ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/svga.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */ +#include <video/vga.h> + +#ifdef CONFIG_MTRR +#include <asm/mtrr.h> +#endif + +struct vt8623fb_info { + char __iomem *mmio_base; + int mtrr_reg; + struct vgastate state; + struct mutex open_lock; + unsigned int ref_count; + u32 pseudo_palette[16]; +}; + + + +/* ------------------------------------------------------------------------- */ + +static const struct svga_fb_format vt8623fb_formats[] = { + { 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, + FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP8, FB_VISUAL_PSEUDOCOLOR, 16, 16}, + { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 16, 16}, + { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 1, + FB_TYPE_INTERLEAVED_PLANES, 1, FB_VISUAL_PSEUDOCOLOR, 16, 16}, + { 8, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 8}, +/* {16, {10, 5, 0}, {5, 5, 0}, {0, 5, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 4, 4}, */ + {16, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 4, 4}, + {32, {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, + FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 2, 2}, + SVGA_FORMAT_END +}; + +static const struct svga_pll vt8623_pll = {2, 127, 2, 7, 0, 3, + 60000, 300000, 14318}; + +/* CRT timing register sets */ + +struct vga_regset vt8623_h_total_regs[] = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END}; +struct vga_regset vt8623_h_display_regs[] = {{0x01, 0, 7}, VGA_REGSET_END}; +struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END}; +struct vga_regset vt8623_h_blank_end_regs[] = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END}; +struct vga_regset vt8623_h_sync_start_regs[] = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END}; +struct vga_regset vt8623_h_sync_end_regs[] = {{0x05, 0, 4}, VGA_REGSET_END}; + +struct vga_regset vt8623_v_total_regs[] = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END}; +struct vga_regset vt8623_v_display_regs[] = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END}; +struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END}; +struct vga_regset vt8623_v_blank_end_regs[] = {{0x16, 0, 7}, VGA_REGSET_END}; +struct vga_regset vt8623_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END}; +struct vga_regset vt8623_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END}; + +struct vga_regset vt8623_offset_regs[] = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END}; +struct vga_regset vt8623_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END}; +struct vga_regset vt8623_fetch_count_regs[] = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END}; +struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END}; + +struct svga_timing_regs vt8623_timing_regs = { + vt8623_h_total_regs, vt8623_h_display_regs, vt8623_h_blank_start_regs, + vt8623_h_blank_end_regs, vt8623_h_sync_start_regs, vt8623_h_sync_end_regs, + vt8623_v_total_regs, vt8623_v_display_regs, vt8623_v_blank_start_regs, + vt8623_v_blank_end_regs, vt8623_v_sync_start_regs, vt8623_v_sync_end_regs, +}; + + +/* ------------------------------------------------------------------------- */ + + +/* Module parameters */ + +static char *mode = "640x480-8@60"; + +#ifdef CONFIG_MTRR +static int mtrr = 1; +#endif + +MODULE_AUTHOR("(c) 2006 Ondrej Zajicek <santiago@crfreenet.org>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("fbdev driver for integrated graphics core in VIA VT8623 [CLE266]"); + +module_param(mode, charp, 0644); +MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc)"); + +#ifdef CONFIG_MTRR +module_param(mtrr, int, 0444); +MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)"); +#endif + + +/* ------------------------------------------------------------------------- */ + + +static struct fb_tile_ops vt8623fb_tile_ops = { + .fb_settile = svga_settile, + .fb_tilecopy = svga_tilecopy, + .fb_tilefill = svga_tilefill, + .fb_tileblit = svga_tileblit, + .fb_tilecursor = svga_tilecursor, + .fb_get_tilemax = svga_get_tilemax, +}; + + +/* ------------------------------------------------------------------------- */ + + +/* image data is MSB-first, fb structure is MSB-first too */ +static inline u32 expand_color(u32 c) +{ + return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF; +} + +/* vt8623fb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */ +static void vt8623fb_iplan_imageblit(struct fb_info *info, const struct fb_image *image) +{ + u32 fg = expand_color(image->fg_color); + u32 bg = expand_color(image->bg_color); + const u8 *src1, *src; + u8 __iomem *dst1; + u32 __iomem *dst; + u32 val; + int x, y; + + src1 = image->data; + dst1 = info->screen_base + (image->dy * info->fix.line_length) + + ((image->dx / 8) * 4); + + for (y = 0; y < image->height; y++) { + src = src1; + dst = (u32 __iomem *) dst1; + for (x = 0; x < image->width; x += 8) { + val = *(src++) * 0x01010101; + val = (val & fg) | (~val & bg); + fb_writel(val, dst++); + } + src1 += image->width / 8; + dst1 += info->fix.line_length; + } +} + +/* vt8623fb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */ +static void vt8623fb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + u32 fg = expand_color(rect->color); + u8 __iomem *dst1; + u32 __iomem *dst; + int x, y; + + dst1 = info->screen_base + (rect->dy * info->fix.line_length) + + ((rect->dx / 8) * 4); + + for (y = 0; y < rect->height; y++) { + dst = (u32 __iomem *) dst1; + for (x = 0; x < rect->width; x += 8) { + fb_writel(fg, dst++); + } + dst1 += info->fix.line_length; + } +} + + +/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */ +static inline u32 expand_pixel(u32 c) +{ + return (((c & 1) << 24) | ((c & 2) << 27) | ((c & 4) << 14) | ((c & 8) << 17) | + ((c & 16) << 4) | ((c & 32) << 7) | ((c & 64) >> 6) | ((c & 128) >> 3)) * 0xF; +} + +/* vt8623fb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */ +static void vt8623fb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image) +{ + u32 fg = image->fg_color * 0x11111111; + u32 bg = image->bg_color * 0x11111111; + const u8 *src1, *src; + u8 __iomem *dst1; + u32 __iomem *dst; + u32 val; + int x, y; + + src1 = image->data; + dst1 = info->screen_base + (image->dy * info->fix.line_length) + + ((image->dx / 8) * 4); + + for (y = 0; y < image->height; y++) { + src = src1; + dst = (u32 __iomem *) dst1; + for (x = 0; x < image->width; x += 8) { + val = expand_pixel(*(src++)); + val = (val & fg) | (~val & bg); + fb_writel(val, dst++); + } + src1 += image->width / 8; + dst1 += info->fix.line_length; + } +} + +static void vt8623fb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + if ((info->var.bits_per_pixel == 4) && (image->depth == 1) + && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) { + if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES) + vt8623fb_iplan_imageblit(info, image); + else + vt8623fb_cfb4_imageblit(info, image); + } else + cfb_imageblit(info, image); +} + +static void vt8623fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + if ((info->var.bits_per_pixel == 4) + && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0) + && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)) + vt8623fb_iplan_fillrect(info, rect); + else + cfb_fillrect(info, rect); +} + + +/* ------------------------------------------------------------------------- */ + + +static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock) +{ + u16 m, n, r; + u8 regval; + int rv; + + rv = svga_compute_pll(&vt8623_pll, 1000000000 / pixclock, &m, &n, &r, info->node); + if (rv < 0) { + printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); + return; + } + + /* Set VGA misc register */ + regval = vga_r(NULL, VGA_MIS_R); + vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); + + /* Set clock registers */ + vga_wseq(NULL, 0x46, (n | (r << 6))); + vga_wseq(NULL, 0x47, m); + + udelay(1000); + + /* PLL reset */ + svga_wseq_mask(0x40, 0x02, 0x02); + svga_wseq_mask(0x40, 0x00, 0x02); +} + + +static int vt8623fb_open(struct fb_info *info, int user) +{ + struct vt8623fb_info *par = info->par; + + mutex_lock(&(par->open_lock)); + if (par->ref_count == 0) { + memset(&(par->state), 0, sizeof(struct vgastate)); + par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; + par->state.num_crtc = 0xA2; + par->state.num_seq = 0x50; + save_vga(&(par->state)); + } + + par->ref_count++; + mutex_unlock(&(par->open_lock)); + + return 0; +} + +static int vt8623fb_release(struct fb_info *info, int user) +{ + struct vt8623fb_info *par = info->par; + + mutex_lock(&(par->open_lock)); + if (par->ref_count == 0) { + mutex_unlock(&(par->open_lock)); + return -EINVAL; + } + + if (par->ref_count == 1) + restore_vga(&(par->state)); + + par->ref_count--; + mutex_unlock(&(par->open_lock)); + + return 0; +} + +static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + int rv, mem, step; + + /* Find appropriate format */ + rv = svga_match_format (vt8623fb_formats, var, NULL); + if (rv < 0) + { + printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node); + return rv; + } + + /* Do not allow to have real resoulution larger than virtual */ + if (var->xres > var->xres_virtual) + var->xres_virtual = var->xres; + + if (var->yres > var->yres_virtual) + var->yres_virtual = var->yres; + + /* Round up xres_virtual to have proper alignment of lines */ + step = vt8623fb_formats[rv].xresstep - 1; + var->xres_virtual = (var->xres_virtual+step) & ~step; + + /* Check whether have enough memory */ + mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual; + if (mem > info->screen_size) + { + printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n", info->node, mem >> 10, (unsigned int) (info->screen_size >> 10)); + return -EINVAL; + } + + /* Text mode is limited to 256 kB of memory */ + if ((var->bits_per_pixel == 0) && (mem > (256*1024))) + { + printk(KERN_ERR "fb%d: text framebuffer size too large (%d kB requested, 256 kB possible)\n", info->node, mem >> 10); + return -EINVAL; + } + + rv = svga_check_timings (&vt8623_timing_regs, var, info->node); + if (rv < 0) + { + printk(KERN_ERR "fb%d: invalid timings requested\n", info->node); + return rv; + } + + /* Interlaced mode not supported */ + if (var->vmode & FB_VMODE_INTERLACED) + return -EINVAL; + + return 0; +} + + +static int vt8623fb_set_par(struct fb_info *info) +{ + u32 mode, offset_value, fetch_value, screen_size; + u32 bpp = info->var.bits_per_pixel; + + if (bpp != 0) { + info->fix.ypanstep = 1; + info->fix.line_length = (info->var.xres_virtual * bpp) / 8; + + info->flags &= ~FBINFO_MISC_TILEBLITTING; + info->tileops = NULL; + + /* in 4bpp supports 8p wide tiles only, any tiles otherwise */ + info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0); + info->pixmap.blit_y = ~(u32)0; + + offset_value = (info->var.xres_virtual * bpp) / 64; + fetch_value = ((info->var.xres * bpp) / 128) + 4; + + if (bpp == 4) + fetch_value = (info->var.xres / 8) + 8; /* + 0 is OK */ + + screen_size = info->var.yres_virtual * info->fix.line_length; + } else { + info->fix.ypanstep = 16; + info->fix.line_length = 0; + + info->flags |= FBINFO_MISC_TILEBLITTING; + info->tileops = &vt8623fb_tile_ops; + + /* supports 8x16 tiles only */ + info->pixmap.blit_x = 1 << (8 - 1); + info->pixmap.blit_y = 1 << (16 - 1); + + offset_value = info->var.xres_virtual / 16; + fetch_value = (info->var.xres / 8) + 8; + screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64; + } + + info->var.xoffset = 0; + info->var.yoffset = 0; + info->var.activate = FB_ACTIVATE_NOW; + + /* Unlock registers */ + svga_wseq_mask(0x10, 0x01, 0x01); + svga_wcrt_mask(0x11, 0x00, 0x80); + svga_wcrt_mask(0x47, 0x00, 0x01); + + /* Device, screen and sync off */ + svga_wseq_mask(0x01, 0x20, 0x20); + svga_wcrt_mask(0x36, 0x30, 0x30); + svga_wcrt_mask(0x17, 0x00, 0x80); + + /* Set default values */ + svga_set_default_gfx_regs(); + svga_set_default_atc_regs(); + svga_set_default_seq_regs(); + svga_set_default_crt_regs(); + svga_wcrt_multi(vt8623_line_compare_regs, 0xFFFFFFFF); + svga_wcrt_multi(vt8623_start_address_regs, 0); + + svga_wcrt_multi(vt8623_offset_regs, offset_value); + svga_wseq_multi(vt8623_fetch_count_regs, fetch_value); + + if (info->var.vmode & FB_VMODE_DOUBLE) + svga_wcrt_mask(0x09, 0x80, 0x80); + else + svga_wcrt_mask(0x09, 0x00, 0x80); + + svga_wseq_mask(0x1E, 0xF0, 0xF0); // DI/DVP bus + svga_wseq_mask(0x2A, 0x0F, 0x0F); // DI/DVP bus + svga_wseq_mask(0x16, 0x08, 0xBF); // FIFO read treshold + vga_wseq(NULL, 0x17, 0x1F); // FIFO depth + vga_wseq(NULL, 0x18, 0x4E); + svga_wseq_mask(0x1A, 0x08, 0x08); // enable MMIO ? + + vga_wcrt(NULL, 0x32, 0x00); + vga_wcrt(NULL, 0x34, 0x00); + vga_wcrt(NULL, 0x6A, 0x80); + vga_wcrt(NULL, 0x6A, 0xC0); + + vga_wgfx(NULL, 0x20, 0x00); + vga_wgfx(NULL, 0x21, 0x00); + vga_wgfx(NULL, 0x22, 0x00); + + /* Set SR15 according to number of bits per pixel */ + mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix)); + switch (mode) { + case 0: + pr_debug("fb%d: text mode\n", info->node); + svga_set_textmode_vga_regs(); + svga_wseq_mask(0x15, 0x00, 0xFE); + svga_wcrt_mask(0x11, 0x60, 0x70); + break; + case 1: + pr_debug("fb%d: 4 bit pseudocolor\n", info->node); + vga_wgfx(NULL, VGA_GFX_MODE, 0x40); + svga_wseq_mask(0x15, 0x20, 0xFE); + svga_wcrt_mask(0x11, 0x00, 0x70); + break; + case 2: + pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); + svga_wseq_mask(0x15, 0x00, 0xFE); + svga_wcrt_mask(0x11, 0x00, 0x70); + break; + case 3: + pr_debug("fb%d: 8 bit pseudocolor\n", info->node); + svga_wseq_mask(0x15, 0x22, 0xFE); + break; + case 4: + pr_debug("fb%d: 5/6/5 truecolor\n", info->node); + svga_wseq_mask(0x15, 0xB6, 0xFE); + break; + case 5: + pr_debug("fb%d: 8/8/8 truecolor\n", info->node); + svga_wseq_mask(0x15, 0xAE, 0xFE); + break; + default: + printk(KERN_ERR "vt8623fb: unsupported mode - bug\n"); + return (-EINVAL); + } + + vt8623_set_pixclock(info, info->var.pixclock); + svga_set_timings(&vt8623_timing_regs, &(info->var), 1, 1, + (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1, + 1, info->node); + + memset_io(info->screen_base, 0x00, screen_size); + + /* Device and screen back on */ + svga_wcrt_mask(0x17, 0x80, 0x80); + svga_wcrt_mask(0x36, 0x00, 0x30); + svga_wseq_mask(0x01, 0x00, 0x20); + + return 0; +} + + +static int vt8623fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *fb) +{ + switch (fb->var.bits_per_pixel) { + case 0: + case 4: + if (regno >= 16) + return -EINVAL; + + outb(0x0F, VGA_PEL_MSK); + outb(regno, VGA_PEL_IW); + outb(red >> 10, VGA_PEL_D); + outb(green >> 10, VGA_PEL_D); + outb(blue >> 10, VGA_PEL_D); + break; + case 8: + if (regno >= 256) + return -EINVAL; + + outb(0xFF, VGA_PEL_MSK); + outb(regno, VGA_PEL_IW); + outb(red >> 10, VGA_PEL_D); + outb(green >> 10, VGA_PEL_D); + outb(blue >> 10, VGA_PEL_D); + break; + case 16: + if (regno >= 16) + return 0; + + if (fb->var.green.length == 5) + ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) | + ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11); + else if (fb->var.green.length == 6) + ((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) | + ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); + else + return -EINVAL; + break; + case 24: + case 32: + if (regno >= 16) + return 0; + + /* ((transp & 0xFF00) << 16) */ + ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) | + (green & 0xFF00) | ((blue & 0xFF00) >> 8); + break; + default: + return -EINVAL; + } + + return 0; +} + + +static int vt8623fb_blank(int blank_mode, struct fb_info *info) +{ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + pr_debug("fb%d: unblank\n", info->node); + svga_wcrt_mask(0x36, 0x00, 0x30); + svga_wseq_mask(0x01, 0x00, 0x20); + break; + case FB_BLANK_NORMAL: + pr_debug("fb%d: blank\n", info->node); + svga_wcrt_mask(0x36, 0x00, 0x30); + svga_wseq_mask(0x01, 0x20, 0x20); + break; + case FB_BLANK_HSYNC_SUSPEND: + pr_debug("fb%d: DPMS standby (hsync off)\n", info->node); + svga_wcrt_mask(0x36, 0x10, 0x30); + svga_wseq_mask(0x01, 0x20, 0x20); + break; + case FB_BLANK_VSYNC_SUSPEND: + pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node); + svga_wcrt_mask(0x36, 0x20, 0x30); + svga_wseq_mask(0x01, 0x20, 0x20); + break; + case FB_BLANK_POWERDOWN: + pr_debug("fb%d: DPMS off (no sync)\n", info->node); + svga_wcrt_mask(0x36, 0x30, 0x30); + svga_wseq_mask(0x01, 0x20, 0x20); + break; + } + + return 0; +} + + +static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +{ + unsigned int offset; + + /* Calculate the offset */ + if (var->bits_per_pixel == 0) { + offset = (var->yoffset / 16) * var->xres_virtual + var->xoffset; + offset = offset >> 3; + } else { + offset = (var->yoffset * info->fix.line_length) + + (var->xoffset * var->bits_per_pixel / 8); + offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 1); + } + + /* Set the offset */ + svga_wcrt_multi(vt8623_start_address_regs, offset); + + return 0; +} + + +/* ------------------------------------------------------------------------- */ + + +/* Frame buffer operations */ + +static struct fb_ops vt8623fb_ops = { + .owner = THIS_MODULE, + .fb_open = vt8623fb_open, + .fb_release = vt8623fb_release, + .fb_check_var = vt8623fb_check_var, + .fb_set_par = vt8623fb_set_par, + .fb_setcolreg = vt8623fb_setcolreg, + .fb_blank = vt8623fb_blank, + .fb_pan_display = vt8623fb_pan_display, + .fb_fillrect = vt8623fb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = vt8623fb_imageblit, + .fb_get_caps = svga_get_caps, +}; + + +/* PCI probe */ + +static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct fb_info *info; + struct vt8623fb_info *par; + unsigned int memsize1, memsize2; + int rc; + + /* Ignore secondary VGA device because there is no VGA arbitration */ + if (! svga_primary_device(dev)) { + dev_info(&(dev->dev), "ignoring secondary device\n"); + return -ENODEV; + } + + /* Allocate and fill driver data structure */ + info = framebuffer_alloc(sizeof(struct vt8623fb_info), NULL); + if (! info) { + dev_err(&(dev->dev), "cannot allocate memory\n"); + return -ENOMEM; + } + + par = info->par; + mutex_init(&par->open_lock); + + info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN; + info->fbops = &vt8623fb_ops; + + /* Prepare PCI device */ + + rc = pci_enable_device(dev); + if (rc < 0) { + dev_err(&(dev->dev), "cannot enable PCI device\n"); + goto err_enable_device; + } + + rc = pci_request_regions(dev, "vt8623fb"); + if (rc < 0) { + dev_err(&(dev->dev), "cannot reserve framebuffer region\n"); + goto err_request_regions; + } + + info->fix.smem_start = pci_resource_start(dev, 0); + info->fix.smem_len = pci_resource_len(dev, 0); + info->fix.mmio_start = pci_resource_start(dev, 1); + info->fix.mmio_len = pci_resource_len(dev, 1); + + /* Map physical IO memory address into kernel space */ + info->screen_base = pci_iomap(dev, 0, 0); + if (! info->screen_base) { + rc = -ENOMEM; + dev_err(&(dev->dev), "iomap for framebuffer failed\n"); + goto err_iomap_1; + } + + par->mmio_base = pci_iomap(dev, 1, 0); + if (! par->mmio_base) { + rc = -ENOMEM; + dev_err(&(dev->dev), "iomap for MMIO failed\n"); + goto err_iomap_2; + } + + /* Find how many physical memory there is on card */ + memsize1 = (vga_rseq(NULL, 0x34) + 1) >> 1; + memsize2 = vga_rseq(NULL, 0x39) << 2; + + if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2)) + info->screen_size = memsize1 << 20; + else { + dev_err(&(dev->dev), "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2); + info->screen_size = 16 << 20; + } + + info->fix.smem_len = info->screen_size; + strcpy(info->fix.id, "VIA VT8623"); + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + info->fix.ypanstep = 0; + info->fix.accel = FB_ACCEL_NONE; + info->pseudo_palette = (void*)par->pseudo_palette; + + /* Prepare startup mode */ + + rc = fb_find_mode(&(info->var), info, mode, NULL, 0, NULL, 8); + if (! ((rc == 1) || (rc == 2))) { + rc = -EINVAL; + dev_err(&(dev->dev), "mode %s not found\n", mode); + goto err_find_mode; + } + + rc = fb_alloc_cmap(&info->cmap, 256, 0); + if (rc < 0) { + dev_err(&(dev->dev), "cannot allocate colormap\n"); + goto err_alloc_cmap; + } + + rc = register_framebuffer(info); + if (rc < 0) { + dev_err(&(dev->dev), "cannot register framebugger\n"); + goto err_reg_fb; + } + + printk(KERN_INFO "fb%d: %s on %s, %d MB RAM\n", info->node, info->fix.id, + pci_name(dev), info->fix.smem_len >> 20); + + /* Record a reference to the driver data */ + pci_set_drvdata(dev, info); + +#ifdef CONFIG_MTRR + if (mtrr) { + par->mtrr_reg = -1; + par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1); + } +#endif + + return 0; + + /* Error handling */ +err_reg_fb: + fb_dealloc_cmap(&info->cmap); +err_alloc_cmap: +err_find_mode: + pci_iounmap(dev, par->mmio_base); +err_iomap_2: + pci_iounmap(dev, info->screen_base); +err_iomap_1: + pci_release_regions(dev); +err_request_regions: +/* pci_disable_device(dev); */ +err_enable_device: + framebuffer_release(info); + return rc; +} + +/* PCI remove */ + +static void __devexit vt8623_pci_remove(struct pci_dev *dev) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct vt8623fb_info *par = info->par; + + if (info) { +#ifdef CONFIG_MTRR + if (par->mtrr_reg >= 0) { + mtrr_del(par->mtrr_reg, 0, 0); + par->mtrr_reg = -1; + } +#endif + + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + + pci_iounmap(dev, info->screen_base); + pci_iounmap(dev, par->mmio_base); + pci_release_regions(dev); +/* pci_disable_device(dev); */ + + pci_set_drvdata(dev, NULL); + framebuffer_release(info); + } +} + + +#ifdef CONFIG_PM +/* PCI suspend */ + +static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct vt8623fb_info *par = info->par; + + dev_info(&(dev->dev), "suspend\n"); + + acquire_console_sem(); + mutex_lock(&(par->open_lock)); + + if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { + mutex_unlock(&(par->open_lock)); + release_console_sem(); + return 0; + } + + fb_set_suspend(info, 1); + + pci_save_state(dev); + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + + mutex_unlock(&(par->open_lock)); + release_console_sem(); + + return 0; +} + + +/* PCI resume */ + +static int vt8623_pci_resume(struct pci_dev* dev) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct vt8623fb_info *par = info->par; + + dev_info(&(dev->dev), "resume\n"); + + acquire_console_sem(); + mutex_lock(&(par->open_lock)); + + if (par->ref_count == 0) { + mutex_unlock(&(par->open_lock)); + release_console_sem(); + return 0; + } + + pci_set_power_state(dev, PCI_D0); + pci_restore_state(dev); + + if (pci_enable_device(dev)) + goto fail; + + pci_set_master(dev); + + vt8623fb_set_par(info); + fb_set_suspend(info, 0); + + mutex_unlock(&(par->open_lock)); +fail: + release_console_sem(); + + return 0; +} +#else +#define vt8623_pci_suspend NULL +#define vt8623_pci_resume NULL +#endif /* CONFIG_PM */ + +/* List of boards that we are trying to support */ + +static struct pci_device_id vt8623_devices[] __devinitdata = { + {PCI_DEVICE(PCI_VENDOR_ID_VIA, 0x3122)}, + {0, 0, 0, 0, 0, 0, 0} +}; + +MODULE_DEVICE_TABLE(pci, vt8623_devices); + +static struct pci_driver vt8623fb_pci_driver = { + .name = "vt8623fb", + .id_table = vt8623_devices, + .probe = vt8623_pci_probe, + .remove = __devexit_p(vt8623_pci_remove), + .suspend = vt8623_pci_suspend, + .resume = vt8623_pci_resume, +}; + +/* Cleanup */ + +static void __exit vt8623fb_cleanup(void) +{ + pr_debug("vt8623fb: cleaning up\n"); + pci_unregister_driver(&vt8623fb_pci_driver); +} + +/* Driver Initialisation */ + +int __init vt8623fb_init(void) +{ + +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("vt8623fb", &option)) + return -ENODEV; + + if (option && *option) + mode = option; +#endif + + pr_debug("vt8623fb: initializing\n"); + return pci_register_driver(&vt8623fb_pci_driver); +} + +/* ------------------------------------------------------------------------- */ + +/* Modularization */ + +module_init(vt8623fb_init); +module_exit(vt8623fb_cleanup); diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c new file mode 100644 index 0000000..1d29a89 --- /dev/null +++ b/drivers/video/xilinxfb.c @@ -0,0 +1,381 @@ +/* + * xilinxfb.c + * + * Xilinx TFT LCD frame buffer driver + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * 2002-2007 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is licensed + * "as is" without any warranty of any kind, whether express or implied. + */ + +/* + * This driver was based on au1100fb.c by MontaVista rewritten for 2.6 + * by Embedded Alley Solutions <source@embeddedalley.com>, which in turn + * was based on skeletonfb.c, Skeleton for a frame buffer device by + * Geert Uytterhoeven. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> + +#include <asm/io.h> +#include <syslib/virtex_devices.h> + +#define DRIVER_NAME "xilinxfb" +#define DRIVER_DESCRIPTION "Xilinx TFT LCD frame buffer driver" + +/* + * Xilinx calls it "PLB TFT LCD Controller" though it can also be used for + * the VGA port on the Xilinx ML40x board. This is a hardware display controller + * for a 640x480 resolution TFT or VGA screen. + * + * The interface to the framebuffer is nice and simple. There are two + * control registers. The first tells the LCD interface where in memory + * the frame buffer is (only the 11 most significant bits are used, so + * don't start thinking about scrolling). The second allows the LCD to + * be turned on or off as well as rotated 180 degrees. + */ +#define NUM_REGS 2 +#define REG_FB_ADDR 0 +#define REG_CTRL 1 +#define REG_CTRL_ENABLE 0x0001 +#define REG_CTRL_ROTATE 0x0002 + +/* + * The hardware only handles a single mode: 640x480 24 bit true + * color. Each pixel gets a word (32 bits) of memory. Within each word, + * the 8 most significant bits are ignored, the next 8 bits are the red + * level, the next 8 bits are the green level and the 8 least + * significant bits are the blue level. Each row of the LCD uses 1024 + * words, but only the first 640 pixels are displayed with the other 384 + * words being ignored. There are 480 rows. + */ +#define BYTES_PER_PIXEL 4 +#define BITS_PER_PIXEL (BYTES_PER_PIXEL * 8) +#define XRES 640 +#define YRES 480 +#define XRES_VIRTUAL 1024 +#define YRES_VIRTUAL YRES +#define LINE_LENGTH (XRES_VIRTUAL * BYTES_PER_PIXEL) +#define FB_SIZE (YRES_VIRTUAL * LINE_LENGTH) + +#define RED_SHIFT 16 +#define GREEN_SHIFT 8 +#define BLUE_SHIFT 0 + +#define PALETTE_ENTRIES_NO 16 /* passed to fb_alloc_cmap() */ + +/* + * Here are the default fb_fix_screeninfo and fb_var_screeninfo structures + */ +static struct fb_fix_screeninfo xilinx_fb_fix __initdata = { + .id = "Xilinx", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .smem_len = FB_SIZE, + .line_length = LINE_LENGTH, + .accel = FB_ACCEL_NONE +}; + +static struct fb_var_screeninfo xilinx_fb_var __initdata = { + .xres = XRES, + .yres = YRES, + .xres_virtual = XRES_VIRTUAL, + .yres_virtual = YRES_VIRTUAL, + + .bits_per_pixel = BITS_PER_PIXEL, + + .red = { RED_SHIFT, 8, 0 }, + .green = { GREEN_SHIFT, 8, 0 }, + .blue = { BLUE_SHIFT, 8, 0 }, + .transp = { 0, 0, 0 }, + + .activate = FB_ACTIVATE_NOW +}; + +struct xilinxfb_drvdata { + + struct fb_info info; /* FB driver info record */ + + u32 regs_phys; /* phys. address of the control registers */ + u32 __iomem *regs; /* virt. address of the control registers */ + + unsigned char __iomem *fb_virt; /* virt. address of the frame buffer */ + dma_addr_t fb_phys; /* phys. address of the frame buffer */ + + u32 reg_ctrl_default; + + u32 pseudo_palette[PALETTE_ENTRIES_NO]; + /* Fake palette of 16 colors */ +}; + +#define to_xilinxfb_drvdata(_info) \ + container_of(_info, struct xilinxfb_drvdata, info) + +/* + * The LCD controller has DCR interface to its registers, but all + * the boards and configurations the driver has been tested with + * use opb2dcr bridge. So the registers are seen as memory mapped. + * This macro is to make it simple to add the direct DCR access + * when it's needed. + */ +#define xilinx_fb_out_be32(driverdata, offset, val) \ + out_be32(driverdata->regs + offset, val) + +static int +xilinx_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *fbi) +{ + u32 *palette = fbi->pseudo_palette; + + if (regno >= PALETTE_ENTRIES_NO) + return -EINVAL; + + if (fbi->var.grayscale) { + /* Convert color to grayscale. + * grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = + (red * 77 + green * 151 + blue * 28 + 127) >> 8; + } + + /* fbi->fix.visual is always FB_VISUAL_TRUECOLOR */ + + /* We only handle 8 bits of each color. */ + red >>= 8; + green >>= 8; + blue >>= 8; + palette[regno] = (red << RED_SHIFT) | (green << GREEN_SHIFT) | + (blue << BLUE_SHIFT); + + return 0; +} + +static int +xilinx_fb_blank(int blank_mode, struct fb_info *fbi) +{ + struct xilinxfb_drvdata *drvdata = to_xilinxfb_drvdata(fbi); + + switch (blank_mode) { + case FB_BLANK_UNBLANK: + /* turn on panel */ + xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default); + break; + + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + /* turn off panel */ + xilinx_fb_out_be32(drvdata, REG_CTRL, 0); + default: + break; + + } + return 0; /* success */ +} + +static struct fb_ops xilinxfb_ops = +{ + .owner = THIS_MODULE, + .fb_setcolreg = xilinx_fb_setcolreg, + .fb_blank = xilinx_fb_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +/* === The device driver === */ + +static int +xilinxfb_drv_probe(struct device *dev) +{ + struct platform_device *pdev; + struct xilinxfb_platform_data *pdata; + struct xilinxfb_drvdata *drvdata; + struct resource *regs_res; + int retval; + + if (!dev) + return -EINVAL; + + pdev = to_platform_device(dev); + pdata = pdev->dev.platform_data; + + if (pdata == NULL) { + printk(KERN_ERR "Couldn't find platform data.\n"); + return -EFAULT; + } + + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) { + printk(KERN_ERR "Couldn't allocate device private record\n"); + return -ENOMEM; + } + dev_set_drvdata(dev, drvdata); + + /* Map the control registers in */ + regs_res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!regs_res || (regs_res->end - regs_res->start + 1 < 8)) { + printk(KERN_ERR "Couldn't get registers resource\n"); + retval = -EFAULT; + goto failed1; + } + + if (!request_mem_region(regs_res->start, 8, DRIVER_NAME)) { + printk(KERN_ERR + "Couldn't lock memory region at 0x%08X\n", + regs_res->start); + retval = -EBUSY; + goto failed1; + } + drvdata->regs = (u32 __iomem*) ioremap(regs_res->start, 8); + drvdata->regs_phys = regs_res->start; + + /* Allocate the framebuffer memory */ + drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(FB_SIZE), + &drvdata->fb_phys, GFP_KERNEL); + if (!drvdata->fb_virt) { + printk(KERN_ERR "Could not allocate frame buffer memory\n"); + retval = -ENOMEM; + goto failed2; + } + + /* Clear (turn to black) the framebuffer */ + memset_io((void *) drvdata->fb_virt, 0, FB_SIZE); + + /* Tell the hardware where the frame buffer is */ + xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys); + + /* Turn on the display */ + if (pdata->rotate_screen) { + drvdata->reg_ctrl_default = REG_CTRL_ENABLE | REG_CTRL_ROTATE; + } else { + drvdata->reg_ctrl_default = REG_CTRL_ENABLE; + } + xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default); + + /* Fill struct fb_info */ + drvdata->info.device = dev; + drvdata->info.screen_base = drvdata->fb_virt; + drvdata->info.fbops = &xilinxfb_ops; + drvdata->info.fix = xilinx_fb_fix; + drvdata->info.fix.smem_start = drvdata->fb_phys; + drvdata->info.pseudo_palette = drvdata->pseudo_palette; + + if (fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0) < 0) { + printk(KERN_ERR "Fail to allocate colormap (%d entries)\n", + PALETTE_ENTRIES_NO); + retval = -EFAULT; + goto failed3; + } + + drvdata->info.flags = FBINFO_DEFAULT; + xilinx_fb_var.height = pdata->screen_height_mm; + xilinx_fb_var.width = pdata->screen_width_mm; + drvdata->info.var = xilinx_fb_var; + + /* Register new frame buffer */ + if (register_framebuffer(&drvdata->info) < 0) { + printk(KERN_ERR "Could not register frame buffer\n"); + retval = -EINVAL; + goto failed4; + } + + return 0; /* success */ + +failed4: + fb_dealloc_cmap(&drvdata->info.cmap); + +failed3: + dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt, + drvdata->fb_phys); + + /* Turn off the display */ + xilinx_fb_out_be32(drvdata, REG_CTRL, 0); + iounmap(drvdata->regs); + +failed2: + release_mem_region(regs_res->start, 8); + +failed1: + kfree(drvdata); + dev_set_drvdata(dev, NULL); + + return retval; +} + +static int +xilinxfb_drv_remove(struct device *dev) +{ + struct xilinxfb_drvdata *drvdata; + + if (!dev) + return -ENODEV; + + drvdata = (struct xilinxfb_drvdata *) dev_get_drvdata(dev); + +#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) + xilinx_fb_blank(VESA_POWERDOWN, &drvdata->info); +#endif + + unregister_framebuffer(&drvdata->info); + + fb_dealloc_cmap(&drvdata->info.cmap); + + dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt, + drvdata->fb_phys); + + /* Turn off the display */ + xilinx_fb_out_be32(drvdata, REG_CTRL, 0); + iounmap(drvdata->regs); + + release_mem_region(drvdata->regs_phys, 8); + + kfree(drvdata); + dev_set_drvdata(dev, NULL); + + return 0; +} + + +static struct device_driver xilinxfb_driver = { + .name = DRIVER_NAME, + .bus = &platform_bus_type, + + .probe = xilinxfb_drv_probe, + .remove = xilinxfb_drv_remove +}; + +static int __init +xilinxfb_init(void) +{ + /* + * No kernel boot options used, + * so we just need to register the driver + */ + return driver_register(&xilinxfb_driver); +} + +static void __exit +xilinxfb_cleanup(void) +{ + driver_unregister(&xilinxfb_driver); +} + +module_init(xilinxfb_init); +module_exit(xilinxfb_cleanup); + +MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); +MODULE_DESCRIPTION(DRIVER_DESCRIPTION); +MODULE_LICENSE("GPL"); |