diff options
-rw-r--r-- | Documentation/fb/cyblafb/bugs | 1 | ||||
-rw-r--r-- | Documentation/fb/cyblafb/fb.modes | 57 | ||||
-rw-r--r-- | Documentation/fb/cyblafb/performance | 1 | ||||
-rw-r--r-- | Documentation/fb/cyblafb/todo | 5 | ||||
-rw-r--r-- | Documentation/fb/cyblafb/usage | 33 | ||||
-rw-r--r-- | Documentation/fb/cyblafb/whatsnew | 29 | ||||
-rw-r--r-- | drivers/video/Kconfig | 2 | ||||
-rw-r--r-- | drivers/video/cyblafb.c | 1523 | ||||
-rw-r--r-- | include/video/cyblafb.h | 4 |
9 files changed, 960 insertions, 695 deletions
diff --git a/Documentation/fb/cyblafb/bugs b/Documentation/fb/cyblafb/bugs index f90cc66ea91..9443a6d72cd 100644 --- a/Documentation/fb/cyblafb/bugs +++ b/Documentation/fb/cyblafb/bugs @@ -11,4 +11,3 @@ Untested features All LCD stuff is untested. If it worked in tridentfb, it should work in cyblafb. Please test and report the results to Knut_Petersen@t-online.de. - diff --git a/Documentation/fb/cyblafb/fb.modes b/Documentation/fb/cyblafb/fb.modes index cf4351fc32f..fe0e5223ba8 100644 --- a/Documentation/fb/cyblafb/fb.modes +++ b/Documentation/fb/cyblafb/fb.modes @@ -14,142 +14,141 @@ # mode "640x480-50" - geometry 640 480 640 3756 8 + geometry 640 480 2048 4096 8 timings 47619 4294967256 24 17 0 216 3 endmode mode "640x480-60" - geometry 640 480 640 3756 8 + geometry 640 480 2048 4096 8 timings 39682 4294967256 24 17 0 216 3 endmode mode "640x480-70" - geometry 640 480 640 3756 8 + geometry 640 480 2048 4096 8 timings 34013 4294967256 24 17 0 216 3 endmode mode "640x480-72" - geometry 640 480 640 3756 8 + geometry 640 480 2048 4096 8 timings 33068 4294967256 24 17 0 216 3 endmode mode "640x480-75" - geometry 640 480 640 3756 8 + geometry 640 480 2048 4096 8 timings 31746 4294967256 24 17 0 216 3 endmode mode "640x480-80" - geometry 640 480 640 3756 8 + geometry 640 480 2048 4096 8 timings 29761 4294967256 24 17 0 216 3 endmode mode "640x480-85" - geometry 640 480 640 3756 8 + geometry 640 480 2048 4096 8 timings 28011 4294967256 24 17 0 216 3 endmode mode "800x600-50" - geometry 800 600 800 3221 8 + geometry 800 600 2048 4096 8 timings 30303 96 24 14 0 136 11 endmode mode "800x600-60" - geometry 800 600 800 3221 8 + geometry 800 600 2048 4096 8 timings 25252 96 24 14 0 136 11 endmode mode "800x600-70" - geometry 800 600 800 3221 8 + geometry 800 600 2048 4096 8 timings 21645 96 24 14 0 136 11 endmode mode "800x600-72" - geometry 800 600 800 3221 8 + geometry 800 600 2048 4096 8 timings 21043 96 24 14 0 136 11 endmode mode "800x600-75" - geometry 800 600 800 3221 8 + geometry 800 600 2048 4096 8 timings 20202 96 24 14 0 136 11 endmode mode "800x600-80" - geometry 800 600 800 3221 8 + geometry 800 600 2048 4096 8 timings 18939 96 24 14 0 136 11 endmode mode "800x600-85" - geometry 800 600 800 3221 8 + geometry 800 600 2048 4096 8 timings 17825 96 24 14 0 136 11 endmode mode "1024x768-50" - geometry 1024 768 1024 2815 8 + geometry 1024 768 2048 4096 8 timings 19054 144 24 29 0 120 3 endmode mode "1024x768-60" - geometry 1024 768 1024 2815 8 + geometry 1024 768 2048 4096 8 timings 15880 144 24 29 0 120 3 endmode mode "1024x768-70" - geometry 1024 768 1024 2815 8 + geometry 1024 768 2048 4096 8 timings 13610 144 24 29 0 120 3 endmode mode "1024x768-72" - geometry 1024 768 1024 2815 8 + geometry 1024 768 2048 4096 8 timings 13232 144 24 29 0 120 3 endmode mode "1024x768-75" - geometry 1024 768 1024 2815 8 + geometry 1024 768 2048 4096 8 timings 12703 144 24 29 0 120 3 endmode mode "1024x768-80" - geometry 1024 768 1024 2815 8 + geometry 1024 768 2048 4096 8 timings 11910 144 24 29 0 120 3 endmode mode "1024x768-85" - geometry 1024 768 1024 2815 8 + geometry 1024 768 2048 4096 8 timings 11209 144 24 29 0 120 3 endmode mode "1280x1024-50" - geometry 1280 1024 1280 2662 8 + geometry 1280 1024 2048 4096 8 timings 11114 232 16 39 0 160 3 endmode mode "1280x1024-60" - geometry 1280 1024 1280 2662 8 + geometry 1280 1024 2048 4096 8 timings 9262 232 16 39 0 160 3 endmode mode "1280x1024-70" - geometry 1280 1024 1280 2662 8 + geometry 1280 1024 2048 4096 8 timings 7939 232 16 39 0 160 3 endmode mode "1280x1024-72" - geometry 1280 1024 1280 2662 8 + geometry 1280 1024 2048 4096 8 timings 7719 232 16 39 0 160 3 endmode mode "1280x1024-75" - geometry 1280 1024 1280 2662 8 + geometry 1280 1024 2048 4096 8 timings 7410 232 16 39 0 160 3 endmode mode "1280x1024-80" - geometry 1280 1024 1280 2662 8 + geometry 1280 1024 2048 4096 8 timings 6946 232 16 39 0 160 3 endmode mode "1280x1024-85" - geometry 1280 1024 1280 2662 8 + geometry 1280 1024 2048 4096 8 timings 6538 232 16 39 0 160 3 endmode - diff --git a/Documentation/fb/cyblafb/performance b/Documentation/fb/cyblafb/performance index eb4e47a9cea..8d15d5dfc6b 100644 --- a/Documentation/fb/cyblafb/performance +++ b/Documentation/fb/cyblafb/performance @@ -77,4 +77,3 @@ patch that speeds up kernel bitblitting a lot ( > 20%). | | | | | | | | | | +-----------+-----------------+-----------------+-----------------+ - diff --git a/Documentation/fb/cyblafb/todo b/Documentation/fb/cyblafb/todo index 80fb2f89b6c..c5f6d0eae54 100644 --- a/Documentation/fb/cyblafb/todo +++ b/Documentation/fb/cyblafb/todo @@ -22,11 +22,10 @@ accelerated color blitting Who needs it? The console driver does use color everything else is done using color expanding blitting of 1bpp character bitmaps. -xpanning Who needs it? - ioctls Who needs it? -TV-out Will be done later +TV-out Will be done later. Use "vga= " at boot time + to set a suitable video mode. ??? Feel free to contact me if you have any feature requests diff --git a/Documentation/fb/cyblafb/usage b/Documentation/fb/cyblafb/usage index e627c8f5421..a39bb3d402a 100644 --- a/Documentation/fb/cyblafb/usage +++ b/Documentation/fb/cyblafb/usage @@ -40,6 +40,16 @@ Selecting Modes None of the modes possible to select as startup modes are affected by the problems described at the end of the next subsection. + For all startup modes cyblafb chooses a virtual x resolution of 2048, + the only exception is mode 1280x1024 in combination with 32 bpp. This + allows ywrap scrolling for all those modes if rotation is 0 or 2, and + also fast scrolling if rotation is 1 or 3. The default virtual y reso- + lution is 4096 for bpp == 8, 2048 for bpp==16 and 1024 for bpp == 32, + again with the only exception of 1280x1024 at 32 bpp. + + Please do set your video memory size to 8 Mb in the Bios setup. Other + values will work, but performace is decreased for a lot of modes. + Mode changes using fbset ======================== @@ -54,20 +64,26 @@ Selecting Modes - if a flat panel is found, cyblafb does not allow you to program a resolution higher than the physical resolution of the flat panel monitor - - cyblafb does not allow xres to differ from xres_virtual - cyblafb does not allow vclk to exceed 230 MHz. As 32 bpp and (currently) 24 bit modes use a doubled vclk internally, the dotclock limit as seen by fbset is 115 MHz for those modes and 230 MHz for 8 and 16 bpp modes. + - cyblafb will allow you to select very high resolutions as + long as the hardware can be programmed to these modes. The + documented limit 1600x1200 is not enforced, but don't expect + perfect signal quality. - Any request that violates the rules given above will be ignored and - fbset will return an error. + Any request that violates the rules given above will be either changed + to something the hardware supports or an error value will be returned. If you program a virtual y resolution higher than the hardware limit, cyblafb will silently decrease that value to the highest possible - value. + value. The same is true for a virtual x resolution that is not + supported by the hardware. Cyblafb tries to adapt vyres first because + vxres decides if ywrap scrolling is possible or not. - Attempts to disable acceleration are ignored. + Attempts to disable acceleration are ignored, I believe that this is + safe. Some video modes that should work do not work as expected. If you use the standard fb.modes, fbset 640x480-60 will program that mode, but @@ -129,10 +145,6 @@ mode 640x480 or 800x600 or 1024x768 or 1280x1024 verbosity 0 is the default, increase to at least 2 for every bug report! -vesafb allows cyblafb to be loaded after vesafb has been - loaded. See sections "Module unloading ...". - - Development hints ================= @@ -195,7 +207,7 @@ a graphics mode. After booting, load cyblafb without any mode and bpp parameter and assign cyblafb to individual ttys using con2fb, e.g.: - modprobe cyblafb vesafb=1 + modprobe cyblafb con2fb /dev/fb1 /dev/tty1 Unloading cyblafb works without problems after you assign vesafb to all @@ -203,4 +215,3 @@ ttys again, e.g.: con2fb /dev/fb0 /dev/tty1 rmmod cyblafb - diff --git a/Documentation/fb/cyblafb/whatsnew b/Documentation/fb/cyblafb/whatsnew new file mode 100644 index 00000000000..76c07a26e04 --- /dev/null +++ b/Documentation/fb/cyblafb/whatsnew @@ -0,0 +1,29 @@ +0.62 +==== + + - the vesafb parameter has been removed as I decided to allow the + feature without any special parameter. + + - Cyblafb does not use the vga style of panning any longer, now the + "right view" register in the graphics engine IO space is used. Without + that change it was impossible to use all available memory, and without + access to all available memory it is impossible to ywrap. + + - The imageblit function now uses hardware acceleration for all font + widths. Hardware blitting across pixel column 2048 is broken in the + cyberblade/i1 graphics core, but we work around that hardware bug. + + - modes with vxres != xres are supported now. + + - ywrap scrolling is supported now and the default. This is a big + performance gain. + + - default video modes use vyres > yres and vxres > xres to allow + almost optimal scrolling speed for normal and rotated screens + + - some features mainly usefull for debugging the upper layers of the + framebuffer system have been added, have a look at the code + + - fixed: Oops after unloading cyblafb when reading /proc/io* + + - we work around some bugs of the higher framebuffer layers. diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index cc8e3bf5001..3f04427c902 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1151,7 +1151,7 @@ config FB_VOODOO1 config FB_CYBLA tristate "Cyberblade/i1 support" - depends on FB && PCI + depends on FB && PCI && X86_32 && !64BIT select FB_CFB_IMAGEBLIT select VIDEO_SELECT ---help--- diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c index 03fbe83d71a..e9f5dee67e3 100644 --- a/drivers/video/cyblafb.c +++ b/drivers/video/cyblafb.c @@ -7,11 +7,12 @@ * tridentfb.c by Jani Monoses * see files above for further credits * - * TODO: - * */ #define CYBLAFB_DEBUG 0 +#define CYBLAFB_KD_GRAPHICS_QUIRK 1 + +#define CYBLAFB_PIXMAPSIZE 8192 #include <linux/config.h> #include <linux/module.h> @@ -22,7 +23,7 @@ #include <asm/types.h> #include <video/cyblafb.h> -#define VERSION "0.54" +#define VERSION "0.62" struct cyblafb_par { u32 pseudo_pal[16]; @@ -32,7 +33,9 @@ struct cyblafb_par { static struct fb_fix_screeninfo cyblafb_fix __devinitdata = { .id = "CyBla", .type = FB_TYPE_PACKED_PIXELS, + .xpanstep = 1, .ypanstep = 1, + .ywrapstep = 1, .visual = FB_VISUAL_PSEUDOCOLOR, .accel = FB_ACCEL_NONE, }; @@ -43,8 +46,9 @@ static int ref __devinitdata = 75; static int fp __devinitdata; static int crt __devinitdata; static int memsize __devinitdata; -static int vesafb __devinitdata; +static int basestride; +static int vesafb; static int nativex; static int center; static int stretch; @@ -52,26 +56,50 @@ static int pciwb = 1; static int pcirb = 1; static int pciwr = 1; static int pcirr = 1; +static int disabled; static int verbosity; static int displaytype; -static void __iomem * io_virt; // iospace virtual memory address - -module_param(mode,charp,0); -module_param(bpp,int,0); -module_param(ref,int,0); -module_param(fp,int,0); -module_param(crt,int,0); -module_param(nativex,int,0); -module_param(center,int,0); -module_param(stretch,int,0); -module_param(pciwb,int,0); -module_param(pcirb,int,0); -module_param(pciwr,int,0); -module_param(pcirr,int,0); -module_param(memsize,int,0); -module_param(verbosity,int,0); -module_param(vesafb,int,0); +static void __iomem *io_virt; // iospace virtual memory address + +module_param(mode, charp, 0); +module_param(bpp, int, 0); +module_param(ref, int, 0); +module_param(fp, int, 0); +module_param(crt, int, 0); +module_param(nativex, int, 0); +module_param(center, int, 0); +module_param(stretch, int, 0); +module_param(pciwb, int, 0); +module_param(pcirb, int, 0); +module_param(pciwr, int, 0); +module_param(pcirr, int, 0); +module_param(memsize, int, 0); +module_param(verbosity, int, 0); + +//========================================= +// +// Well, we have to fix the upper layers. +// Until this has been done, we work around +// the bugs. +// +//========================================= + +#if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG) + if (disabled) { \ + printk("********\n");\ + dump_stack();\ + return val;\ + } + +#elif CYBLAFB_KD_GRAPHICS_QUIRK +#define KD_GRAPHICS_RETURN(val)\ + if (disabled) {\ + return val;\ + } +#else +#define KD_GRAPHICS_RETURN(val) +#endif //========================================= // @@ -79,10 +107,10 @@ module_param(vesafb,int,0); // //========================================= -#define out8(r,v) writeb(v,io_virt+r) -#define out32(r,v) writel(v,io_virt+r) -#define in8(r) readb(io_virt+r) -#define in32(r) readl(io_virt+r) +#define out8(r, v) writeb(v, io_virt + r) +#define out32(r, v) writel(v, io_virt + r) +#define in8(r) readb(io_virt + r) +#define in32(r) readl(io_virt + r) //====================================== // @@ -90,47 +118,47 @@ module_param(vesafb,int,0); // //====================================== -static inline unsigned char read3X4(int reg) +static inline u8 read3X4(u32 reg) { - out8(0x3D4,reg); + out8(0x3D4, reg); return in8(0x3D5); } -static inline unsigned char read3C4(int reg) +static inline u8 read3C4(u32 reg) { - out8(0x3C4,reg); + out8(0x3C4, reg); return in8(0x3C5); } -static inline unsigned char read3CE(int reg) +static inline u8 read3CE(u32 reg) { - out8(0x3CE,reg); + out8(0x3CE, reg); return in8(0x3CF); } -static inline void write3X4(int reg,unsigned char val) +static inline void write3X4(u32 reg, u8 val) { - out8(0x3D4,reg); - out8(0x3D5,val); + out8(0x3D4, reg); + out8(0x3D5, val); } -static inline void write3C4(int reg,unsigned char val) +static inline void write3C4(u32 reg, u8 val) { - out8(0x3C4,reg); - out8(0x3C5,val); + out8(0x3C4, reg); + out8(0x3C5, val); } -static inline void write3CE(int reg,unsigned char val) +static inline void write3CE(u32 reg, u8 val) { - out8(0x3CE,reg); - out8(0x3CF,val); + out8(0x3CE, reg); + out8(0x3CF, val); } -static inline void write3C0(int reg,unsigned char val) +static inline void write3C0(u32 reg, u8 val) { - in8(0x3DA); // read to reset index - out8(0x3C0,reg); - out8(0x3C0,val); + in8(0x3DA); // read to reset index + out8(0x3C0, reg); + out8(0x3C0, val); } //================================================= @@ -139,58 +167,62 @@ static inline void write3C0(int reg,unsigned char val) // //================================================= -static inline void enable_mmio(void) +static void enable_mmio(void) { - int tmp; + u8 tmp; - outb(0x0B,0x3C4); + outb(0x0B, 0x3C4); inb(0x3C5); // Set NEW mode - outb(SR0E,0x3C4); // write enable a lot of extended ports - outb(0x80,0x3C5); + outb(SR0E, 0x3C4); // write enable a lot of extended ports + outb(0x80, 0x3C5); - outb(SR11,0x3C4); // write enable those extended ports that - outb(0x87,0x3C5); // are not affected by SR0E_New + outb(SR11, 0x3C4); // write enable those extended ports that + outb(0x87, 0x3C5); // are not affected by SR0E_New - outb(CR1E,0x3d4); // clear write protect bit for port 0x3c2 - tmp=inb(0x3d5) & 0xBF; - outb(CR1E,0x3d4); - outb(tmp,0x3d5); + outb(CR1E, 0x3d4); // clear write protect bit for port 0x3c2 + tmp = inb(0x3d5) & 0xBF; + outb(CR1E, 0x3d4); + outb(tmp, 0x3d5); - outb(CR39,0x3D4); - outb(inb(0x3D5)|0x01,0x3D5); // Enable mmio, everything else untouched + outb(CR39, 0x3D4); + outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio } //================================================= // // Set pixel clock VCLK1 -// - multipliers set elswhere -// - freq in units of 0.01 MHz +// - multipliers set elswhere +// - freq in units of 0.01 MHz +// +// Hardware bug: SR18 >= 250 is broken for the +// cyberblade/i1 // //================================================= static void set_vclk(struct cyblafb_par *par, int freq) { - u32 m,n,k; - int f,fi,d,di; - u8 lo=0,hi=0; + u32 m, n, k; + int f, fi, d, di; + u8 lo = 0, hi = 0; d = 2000; k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3; - for(m = 0;m<64;m++) - for(n = 0;n<250;n++) { // max 249 is a hardware limit for cybla/i1 ! - fi = (int)(((5864727*(n+8))/((m+2)*(1<<k)))>>12); - if ((di = abs(fi - freq)) < d) { - d = di; - f = fi; - lo = (u8) n; - hi = (u8) ((k<<6) | m); + for (m = 0; m < 64; m++) + for (n = 0; n < 250; n++) { + fi = (int)(((5864727 * (n + 8)) / + ((m + 2) * (1 << k))) >> 12); + if ((di = abs(fi - freq)) < d) { + d = di; + f = fi; + lo = (u8) n; + hi = (u8) ((k << 6) | m); + } } - } - write3C4(SR19,hi); - write3C4(SR18,lo); - if(verbosity > 1) + write3C4(SR19, hi); + write3C4(SR18, lo); + if (verbosity > 0) output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n", - freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo); + freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo); } //================================================ @@ -199,83 +231,83 @@ static void set_vclk(struct cyblafb_par *par, int freq) // //================================================ -static void cyblafb_setup_GE(int pitch,int bpp) +static void cyblafb_setup_GE(int pitch, int bpp) { - int base = (pitch>>3)<<20; + KD_GRAPHICS_RETURN(); switch (bpp) { - case 8: base |= (0<<29); break; - case 15: base |= (5<<29); break; - case 16: base |= (1<<29); break; - case 24: - case 32: base |= (2<<29); break; + case 8: + basestride = ((pitch >> 3) << 20) | (0 << 29); + break; + case 15: + basestride = ((pitch >> 3) << 20) | (5 << 29); + break; + case 16: + basestride = ((pitch >> 3) << 20) | (1 << 29); + break; + case 24: + case 32: + basestride = ((pitch >> 3) << 20) | (2 << 29); + break; } - write3X4(CR36,0x90); // reset GE - write3X4(CR36,0x80); // enable GE - - out32(GE24,1<<7); // reset all GE pointers - out32(GE24,0); - - write3X4(CR2D,0x00); // GE Timinigs, no delays - - out32(GEB8,base); // Destination Stride / Buffer Base 0, p 133 - out32(GEBC,base); // Destination Stride / Buffer Base 1, p 133 - out32(GEC0,base); // Destination Stride / Buffer Base 2, p 133 - out32(GEC4,base); // Destination Stride / Buffer Base 3, p 133 - out32(GEC8,base); // Source Stride / Buffer Base 0, p 133 - out32(GECC,base); // Source Stride / Buffer Base 1, p 133 - out32(GED0,base); // Source Stride / Buffer Base 2, p 133 - out32(GED4,base); // Source Stride / Buffer Base 3, p 133 - out32(GE6C,0); // Pattern and Style, p 129, ok + write3X4(CR36, 0x90); // reset GE + write3X4(CR36, 0x80); // enable GE + out32(GE24, 1 << 7); // reset all GE pointers by toggling + out32(GE24, 0); // d7 of GE24 + write3X4(CR2D, 0x00); // GE Timinigs, no delays + out32(GE6C, 0); // Pattern and Style, p 129, ok } //===================================================================== // -// Although this is a .fb_sync function that could be enabled in -// cyblafb_ops, we do not include it there. We sync immediately before -// new GE operations to improve performance. +// Cyberblade specific syncing +// +// A timeout might be caused by disabled mmio. +// Cause: +// - bit CR39 & 1 == 0 upon return, X trident driver bug +// - kdm bug (KD_GRAPHICS not set on first switch) +// - kernel design flaw (it believes in the correctness +// of kdm/X +// First we try to sync ignoring that problem, as most of the +// time that will succeed immediately and the enable_mmio() +// would only degrade performance. // //===================================================================== static int cyblafb_sync(struct fb_info *info) { - int status, i=100000; - while( ((status=in32(GE20)) & 0xFA800000) && i != 0) + u32 status, i = 100000; + + KD_GRAPHICS_RETURN(0); + + while (((status = in32(GE20)) & 0xFe800000) && i != 0) i--; if (i == 0) { - // The timeout might be caused by disabled mmio. - // Cause: - // - bit CR39 & 1 == 0 upon return, X trident driver bug - // - kdm bug (KD_GRAPHICS not set on first switch) - // - kernel design flaw (it believes in the correctness - // of kdm/X - // So we make sure that mmio is enabled first ... enable_mmio(); -// show_trace(NULL,&status); - i=1000000; - while( ((status=in32(GE20)) & 0xFA800000) && i != 0) + i = 1000000; + while (((status = in32(GE20)) & 0xFA800000) && i != 0) i--; if (i == 0) { - output("GE Timeout, status: %x\n",status); - if(status & 0x80000000) + output("GE Timeout, status: %x\n", status); + if (status & 0x80000000) output("Bresenham Engine : Busy\n"); - if(status & 0x40000000) + if (status & 0x40000000) output("Setup Engine : Busy\n"); - if(status & 0x20000000) + if (status & 0x20000000) output("SP / DPE : Busy\n"); - if(status & 0x10000000) + if (status & 0x10000000) output("Memory Interface : Busy\n"); - if(status & 0x08000000) + if (status & 0x08000000) output("Com Lst Proc : Busy\n"); - if(status & 0x04000000) + if (status & 0x04000000) output("Block Write : Busy\n"); - if(status & 0x02000000) + if (status & 0x02000000) output("Command Buffer : Full\n"); - if(status & 0x01000000) + if (status & 0x01000000) output("RESERVED : Busy\n"); - if(status & 0x00800000) + if (status & 0x00800000) output("PCI Write Buffer : Busy\n"); cyblafb_setup_GE(info->var.xres, info->var.bits_per_pixel); @@ -291,142 +323,193 @@ static int cyblafb_sync(struct fb_info *info) // //============================== -static void cyblafb_fillrect(struct fb_info * info, - const struct fb_fillrect *fr) +static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr) { - int bpp = info->var.bits_per_pixel; - int col; + u32 bpp = info->var.bits_per_pixel, col, desty, height; + + KD_GRAPHICS_RETURN(); switch (bpp) { - default: - case 8: col = fr->color; - col |= col <<8; - col |= col <<16; - break; - case 16: col = ((u32 *)(info->pseudo_palette))[fr->color]; - col |= col <<16; - break; - case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; - break; + default: + case 8: + col = fr->color; + col |= col << 8; + col |= col << 16; + break; + case 16: + col = ((u32 *) (info->pseudo_palette))[fr->color]; + col |= col << 16; + break; + case 32: + col = ((u32 *) (info->pseudo_palette))[fr->color]; + break; } - cyblafb_sync(info); - - out32(GE60,col); - out32(GE48,fr->rop ? 0x66:ROP_S); - out32(GE44,0x20000000|1<<19|1<<4|2<<2); - out32(GE08,point(fr->dx,fr->dy)); - out32(GE0C,point(fr->dx+fr->width-1,fr->dy+fr->height-1)); - + desty = fr->dy; + height = fr->height; + while (height) { + out32(GEB8, basestride | ((desty * info->var.xres_virtual * + bpp) >> 6)); + out32(GE60, col); + out32(GE48, fr->rop ? 0x66 : ROP_S); + out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2); + out32(GE08, point(fr->dx, 0)); + out32(GE0C, point(fr->dx + fr->width - 1, + height > 4096 ? 4095 : height - 1)); + if (likely(height <= 4096)) + return; + desty += 4096; + height -= 4096; + } } -//============================== +//================================================ // // Cyberblade specific copyarea // -//============================== +// This function silently assumes that it never +// will be called with width or height exceeding +// 4096. +// +//================================================ -static void cyblafb_copyarea(struct fb_info *info, - const struct fb_copyarea *ca) +static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca) { - __u32 s1,s2,d1,d2; - int direction; + u32 s1, s2, d1, d2, direction; + + KD_GRAPHICS_RETURN(); + + s1 = point(ca->sx, 0); + s2 = point(ca->sx + ca->width - 1, ca->height - 1); + d1 = point(ca->dx, 0); + d2 = point(ca->dx + ca->width - 1, ca->height - 1); - s1 = point(ca->sx,ca->sy); - s2 = point(ca->sx+ca->width-1,ca->sy+ca->height-1); - d1 = point(ca->dx,ca->dy); - d2 = point(ca->dx+ca->width-1,ca->dy+ca->height-1); if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx))) direction = 0; else direction = 2; - cyblafb_sync(info); - - out32(GE44,0xa0000000|1<<19|1<<2|direction); - out32(GE00,direction?s2:s1); - out32(GE04,direction?s1:s2); - out32(GE08,direction?d2:d1); - out32(GE0C,direction?d1:d2); - + out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual * + info->var.bits_per_pixel) >> 6)); + out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual * + info->var.bits_per_pixel) >> 6)); + out32(GE44, 0xa0000000 | 1 << 19 | 1 << 2 | direction); + out32(GE00, direction ? s2 : s1); + out32(GE04, direction ? s1 : s2); + out32(GE08, direction ? d2 : d1); + out32(GE0C, direction ? d1 : d2); } //======================================================================= // // Cyberblade specific imageblit // -// Accelerated for the most usual case, blitting 1-bit deep character -// character images. Everything else is passed to the generic imageblit. +// Accelerated for the most usual case, blitting 1 - bit deep +// character images. Everything else is passed to the generic imageblit +// unless it is so insane that it is better to printk an alert. +// +// Hardware bug: _Never_ blit across pixel column 2048, that will lock +// the system. We split those blit requests into three blitting +// operations. // //======================================================================= static void cyblafb_imageblit(struct fb_info *info, const struct fb_image *image) { - u32 fgcol, bgcol; + u32 *pd = (u32 *) image->data; + u32 bpp = info->var.bits_per_pixel; - int i; - int bpp = info->var.bits_per_pixel; - int index = 0; - int index_end=image->height * image->width / 8; - int width_dds=image->width / 32; - int width_dbs=image->width % 32; - - if (image->depth != 1 || bpp < 8 || bpp > 32 || bpp % 8 != 0 || - image->width % 8 != 0 || image->width == 0 || image->height == 0) { - cfb_imageblit(info,image); + KD_GRAPHICS_RETURN(); + + // Used only for drawing the penguine (image->depth > 1) + if (image->depth != 1) { + cfb_imageblit(info, image); + return; + } + // That should never happen, but it would be fatal + if (image->width == 0 || image->height == 0) { + output("imageblit: width/height 0 detected\n"); return; } if (info->fix.visual == FB_VISUAL_TRUECOLOR || info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - fgcol = ((u32*)(info->pseudo_palette))[image->fg_color]; - bgcol = ((u32*)(info->pseudo_palette))[image->bg_color]; + fgcol = ((u32 *) (info->pseudo_palette))[image->fg_color]; + bgcol = ((u32 *) (info->pseudo_palette))[image->bg_color]; } else { fgcol = image->fg_color; bgcol = image->bg_color; } switch (bpp) { - case 8: - fgcol |= fgcol <<8; fgcol |= fgcol <<16; - bgcol |= bgcol <<8; bgcol |= bgcol <<16; - break; - case 16: - fgcol |= fgcol <<16; - bgcol |= bgcol <<16; - break; - default: - break; + case 8: + fgcol |= fgcol << 8; + bgcol |= bgcol << 8; + case 16: + fgcol |= fgcol << 16; + bgcol |= bgcol << 16; + default: + break; } - cyblafb_sync(info); - - out32(GE60,fgcol); - out32(GE64,bgcol); - out32(GE44,0xa0000000 | 1<<20 | 1<<19); - out32(GE08,point(image->dx,image->dy)); - out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1)); + out32(GEB8, basestride | ((image->dy * info->var.xres_virtual * + bpp) >> 6)); + out32(GE60, fgcol); + out32(GE64, bgcol); + + if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) { + u32 dds = ((image->width + 31) >> 5) * image->height; + out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); + out32(GE08, point(image->dx, 0)); + out32(GE0C, point(image->dx + image->width - 1, + image->height - 1)); + while (dds--) + out32(GE9C, *pd++); + } else { + int i, j; + u32 ddstotal = (image->width + 31) >> 5; + u32 ddsleft = (2048 - image->dx + 31) >> 5; + u32 skipleft = ddstotal - ddsleft; + + out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); + out32(GE08, point(image->dx, 0)); + out32(GE0C, point(2048 - 1, image->height - 1)); + for (i = 0; i < image->height; i++) { + for (j = 0; j < ddsleft; j++) + out32(GE9C, *pd++); + pd += skipleft; + } - while(index < index_end) { - const char *p = image->data + index; - for(i=0;i<width_dds;i++) { - out32(GE9C,*(u32*)p); - p+=4; - index+=4; + if (image->dx % 32) { + out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); + out32(GE08, point(2048, 0)); + if (image->width > ddsleft << 5) + out32(GE0C, point(image->dx + (ddsleft << 5) - + 1, image->height - 1)); + else + out32(GE0C, point(image->dx + image->width - 1, + image->height - 1)); + pd = ((u32 *) image->data) + ddstotal - skipleft - 1; + for (i = 0; i < image->height; i++) { + out32(GE9C, swab32(swab32(*pd) << ((32 - + (image->dx & 31)) & 31))); + pd += ddstotal; + } } - switch(width_dbs) { - case 0: break; - case 8: out32(GE9C,*(u8*)p); - index+=1; - break; - case 16: out32(GE9C,*(u16*)p); - index+=2; - break; - case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16); - index+=3; - break; + + if (skipleft) { + out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); + out32(GE08, point(image->dx + (ddsleft << 5), 0)); + out32(GE0C, point(image->dx + image->width - 1, + image->height - 1)); + pd = (u32 *) image->data; + for (i = 0; i < image->height; i++) { + pd += ddsleft; + for (j = 0; j < skipleft; j++) + out32(GE9C, *pd++); + } } } } @@ -443,7 +526,6 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { int bpp = var->bits_per_pixel; - int s,t,maxvyres; // // we try to support 8, 16, 24 and 32 bpp modes, @@ -453,9 +535,9 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var, // (This is what tridentfb does ... will be changed in the future) // // - if ( bpp % 8 != 0 || bpp < 8 || bpp >32) + if (bpp % 8 != 0 || bpp < 8 || bpp > 32) bpp = 8; - if (bpp == 24 ) + if (bpp == 24) bpp = var->bits_per_pixel = 32; // @@ -472,65 +554,93 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var, return -EINVAL; // - // xres != xres_virtual is broken, fail if such an - // unusual mode is requested + // we do not allow vclk to exceed 230 MHz. If the requested + // vclk is too high, we default to 200 MHz // - if (var->xres != var->xres_virtua |