aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKnut Petersen <Knut_Petersen@t-online.de>2006-01-09 09:04:20 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-09 13:00:36 -0500
commit44637a12f80b80157d9c1bc5b7d6ef09c9e05713 (patch)
tree17384805725f7b429685ba4cad0d9488d93f9f25 /drivers
parent8b78e83bfbc12f7e9bdefd400abdfde9e6c9ac51 (diff)
[PATCH] Update cyblafb driver
This is a major update to the cyblafb framebuffer driver. Most of the stuff has been tested in the mm tree. Main advantages: ============ - vxres > xres support - ywrap and xpan support - much faster for almost all modes (e.g. 1280x1024-16bpp draws more than 41 full screens of text instead of about 25 full screens of text per second on authors Epia 5000) - module init/exit code fixed - bugs triggered by console rotation fixed - lots of minor improvements - startup modes suitable for high performance scrolling in all directions This diff also contains a lot of white space fixes. No side effects are possible, only one single graphics core is affected. Signed-off-by: Knut Petersen <Knut_Petersen@t-online.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/cyblafb.c1523
2 files changed, 875 insertions, 650 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cc8e3bf5001b..3f04427c9026 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1151,7 +1151,7 @@ config FB_VOODOO1
1151 1151
1152config FB_CYBLA 1152config FB_CYBLA
1153 tristate "Cyberblade/i1 support" 1153 tristate "Cyberblade/i1 support"
1154 depends on FB && PCI 1154 depends on FB && PCI && X86_32 && !64BIT
1155 select FB_CFB_IMAGEBLIT 1155 select FB_CFB_IMAGEBLIT
1156 select VIDEO_SELECT 1156 select VIDEO_SELECT
1157 ---help--- 1157 ---help---
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 03fbe83d71a8..e9f5dee67e3c 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -7,11 +7,12 @@
7 * tridentfb.c by Jani Monoses 7 * tridentfb.c by Jani Monoses
8 * see files above for further credits 8 * see files above for further credits
9 * 9 *
10 * TODO:
11 *
12 */ 10 */
13 11
14#define CYBLAFB_DEBUG 0 12#define CYBLAFB_DEBUG 0
13#define CYBLAFB_KD_GRAPHICS_QUIRK 1
14
15#define CYBLAFB_PIXMAPSIZE 8192
15 16
16#include <linux/config.h> 17#include <linux/config.h>
17#include <linux/module.h> 18#include <linux/module.h>
@@ -22,7 +23,7 @@
22#include <asm/types.h> 23#include <asm/types.h>
23#include <video/cyblafb.h> 24#include <video/cyblafb.h>
24 25
25#define VERSION "0.54" 26#define VERSION "0.62"
26 27
27struct cyblafb_par { 28struct cyblafb_par {
28 u32 pseudo_pal[16]; 29 u32 pseudo_pal[16];
@@ -32,7 +33,9 @@ struct cyblafb_par {
32static struct fb_fix_screeninfo cyblafb_fix __devinitdata = { 33static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
33 .id = "CyBla", 34 .id = "CyBla",
34 .type = FB_TYPE_PACKED_PIXELS, 35 .type = FB_TYPE_PACKED_PIXELS,
36 .xpanstep = 1,
35 .ypanstep = 1, 37 .ypanstep = 1,
38 .ywrapstep = 1,
36 .visual = FB_VISUAL_PSEUDOCOLOR, 39 .visual = FB_VISUAL_PSEUDOCOLOR,
37 .accel = FB_ACCEL_NONE, 40 .accel = FB_ACCEL_NONE,
38}; 41};
@@ -43,8 +46,9 @@ static int ref __devinitdata = 75;
43static int fp __devinitdata; 46static int fp __devinitdata;
44static int crt __devinitdata; 47static int crt __devinitdata;
45static int memsize __devinitdata; 48static int memsize __devinitdata;
46static int vesafb __devinitdata;
47 49
50static int basestride;
51static int vesafb;
48static int nativex; 52static int nativex;
49static int center; 53static int center;
50static int stretch; 54static int stretch;
@@ -52,26 +56,50 @@ static int pciwb = 1;
52static int pcirb = 1; 56static int pcirb = 1;
53static int pciwr = 1; 57static int pciwr = 1;
54static int pcirr = 1; 58static int pcirr = 1;
59static int disabled;
55static int verbosity; 60static int verbosity;
56static int displaytype; 61static int displaytype;
57 62
58static void __iomem * io_virt; // iospace virtual memory address 63static void __iomem *io_virt; // iospace virtual memory address
59 64
60module_param(mode,charp,0); 65module_param(mode, charp, 0);
61module_param(bpp,int,0); 66module_param(bpp, int, 0);
62module_param(ref,int,0); 67module_param(ref, int, 0);
63module_param(fp,int,0); 68module_param(fp, int, 0);
64module_param(crt,int,0); 69module_param(crt, int, 0);
65module_param(nativex,int,0); 70module_param(nativex, int, 0);
66module_param(center,int,0); 71module_param(center, int, 0);
67module_param(stretch,int,0); 72module_param(stretch, int, 0);
68module_param(pciwb,int,0); 73module_param(pciwb, int, 0);
69module_param(pcirb,int,0); 74module_param(pcirb, int, 0);
70module_param(pciwr,int,0); 75module_param(pciwr, int, 0);
71module_param(pcirr,int,0); 76module_param(pcirr, int, 0);
72module_param(memsize,int,0); 77module_param(memsize, int, 0);
73module_param(verbosity,int,0); 78module_param(verbosity, int, 0);
74module_param(vesafb,int,0); 79
80//=========================================
81//
82// Well, we have to fix the upper layers.
83// Until this has been done, we work around
84// the bugs.
85//
86//=========================================
87
88#if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG)
89 if (disabled) { \
90 printk("********\n");\
91 dump_stack();\
92 return val;\
93 }
94
95#elif CYBLAFB_KD_GRAPHICS_QUIRK
96#define KD_GRAPHICS_RETURN(val)\
97 if (disabled) {\
98 return val;\
99 }
100#else
101#define KD_GRAPHICS_RETURN(val)
102#endif
75 103
76//========================================= 104//=========================================
77// 105//
@@ -79,10 +107,10 @@ module_param(vesafb,int,0);
79// 107//
80//========================================= 108//=========================================
81 109
82#define out8(r,v) writeb(v,io_virt+r) 110#define out8(r, v) writeb(v, io_virt + r)
83#define out32(r,v) writel(v,io_virt+r) 111#define out32(r, v) writel(v, io_virt + r)
84#define in8(r) readb(io_virt+r) 112#define in8(r) readb(io_virt + r)
85#define in32(r) readl(io_virt+r) 113#define in32(r) readl(io_virt + r)
86 114
87//====================================== 115//======================================
88// 116//
@@ -90,47 +118,47 @@ module_param(vesafb,int,0);
90// 118//
91//====================================== 119//======================================
92 120
93static inline unsigned char read3X4(int reg) 121static inline u8 read3X4(u32 reg)
94{ 122{
95 out8(0x3D4,reg); 123 out8(0x3D4, reg);
96 return in8(0x3D5); 124 return in8(0x3D5);
97} 125}
98 126
99static inline unsigned char read3C4(int reg) 127static inline u8 read3C4(u32 reg)
100{ 128{
101 out8(0x3C4,reg); 129 out8(0x3C4, reg);
102 return in8(0x3C5); 130 return in8(0x3C5);
103} 131}
104 132
105static inline unsigned char read3CE(int reg) 133static inline u8 read3CE(u32 reg)
106{ 134{
107 out8(0x3CE,reg); 135 out8(0x3CE, reg);
108 return in8(0x3CF); 136 return in8(0x3CF);
109} 137}
110 138
111static inline void write3X4(int reg,unsigned char val) 139static inline void write3X4(u32 reg, u8 val)
112{ 140{
113 out8(0x3D4,reg); 141 out8(0x3D4, reg);
114 out8(0x3D5,val); 142 out8(0x3D5, val);
115} 143}
116 144
117static inline void write3C4(int reg,unsigned char val) 145static inline void write3C4(u32 reg, u8 val)
118{ 146{
119 out8(0x3C4,reg); 147 out8(0x3C4, reg);
120 out8(0x3C5,val); 148 out8(0x3C5, val);
121} 149}
122 150
123static inline void write3CE(int reg,unsigned char val) 151static inline void write3CE(u32 reg, u8 val)
124{ 152{
125 out8(0x3CE,reg); 153 out8(0x3CE, reg);
126 out8(0x3CF,val); 154 out8(0x3CF, val);
127} 155}
128 156
129static inline void write3C0(int reg,unsigned char val) 157static inline void write3C0(u32 reg, u8 val)
130{ 158{
131 in8(0x3DA); // read to reset index 159 in8(0x3DA); // read to reset index
132 out8(0x3C0,reg); 160 out8(0x3C0, reg);
133 out8(0x3C0,val); 161 out8(0x3C0, val);
134} 162}
135 163
136//================================================= 164//=================================================
@@ -139,58 +167,62 @@ static inline void write3C0(int reg,unsigned char val)
139// 167//
140//================================================= 168//=================================================
141 169
142static inline void enable_mmio(void) 170static void enable_mmio(void)
143{ 171{
144 int tmp; 172 u8 tmp;
145 173
146 outb(0x0B,0x3C4); 174 outb(0x0B, 0x3C4);
147 inb(0x3C5); // Set NEW mode 175 inb(0x3C5); // Set NEW mode
148 outb(SR0E,0x3C4); // write enable a lot of extended ports 176 outb(SR0E, 0x3C4); // write enable a lot of extended ports
149 outb(0x80,0x3C5); 177 outb(0x80, 0x3C5);
150 178
151 outb(SR11,0x3C4); // write enable those extended ports that 179 outb(SR11, 0x3C4); // write enable those extended ports that
152 outb(0x87,0x3C5); // are not affected by SR0E_New 180 outb(0x87, 0x3C5); // are not affected by SR0E_New
153 181
154 outb(CR1E,0x3d4); // clear write protect bit for port 0x3c2 182 outb(CR1E, 0x3d4); // clear write protect bit for port 0x3c2
155 tmp=inb(0x3d5) & 0xBF; 183 tmp = inb(0x3d5) & 0xBF;
156 outb(CR1E,0x3d4); 184 outb(CR1E, 0x3d4);
157 outb(tmp,0x3d5); 185 outb(tmp, 0x3d5);
158 186
159 outb(CR39,0x3D4); 187 outb(CR39, 0x3D4);
160 outb(inb(0x3D5)|0x01,0x3D5); // Enable mmio, everything else untouched 188 outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio
161} 189}
162 190
163//================================================= 191//=================================================
164// 192//
165// Set pixel clock VCLK1 193// Set pixel clock VCLK1
166// - multipliers set elswhere 194// - multipliers set elswhere
167// - freq in units of 0.01 MHz 195// - freq in units of 0.01 MHz
196//
197// Hardware bug: SR18 >= 250 is broken for the
198// cyberblade/i1
168// 199//
169//================================================= 200//=================================================
170 201
171static void set_vclk(struct cyblafb_par *par, int freq) 202static void set_vclk(struct cyblafb_par *par, int freq)
172{ 203{
173 u32 m,n,k; 204 u32 m, n, k;
174 int f,fi,d,di; 205 int f, fi, d, di;
175 u8 lo=0,hi=0; 206 u8 lo = 0, hi = 0;
176 207
177 d = 2000; 208 d = 2000;
178 k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3; 209 k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3;
179 for(m = 0;m<64;m++) 210 for (m = 0; m < 64; m++)
180 for(n = 0;n<250;n++) { // max 249 is a hardware limit for cybla/i1 ! 211 for (n = 0; n < 250; n++) {
181 fi = (int)(((5864727*(n+8))/((m+2)*(1<<k)))>>12); 212 fi = (int)(((5864727 * (n + 8)) /
182 if ((di = abs(fi - freq)) < d) { 213 ((m + 2) * (1 << k))) >> 12);
183 d = di; 214 if ((di = abs(fi - freq)) < d) {
184 f = fi; 215 d = di;
185 lo = (u8) n; 216 f = fi;
186 hi = (u8) ((k<<6) | m); 217 lo = (u8) n;
218 hi = (u8) ((k << 6) | m);
219 }
187 } 220 }
188 } 221 write3C4(SR19, hi);
189 write3C4(SR19,hi); 222 write3C4(SR18, lo);
190 write3C4(SR18,lo); 223 if (verbosity > 0)
191 if(verbosity > 1)
192 output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n", 224 output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
193 freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo); 225 freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo);
194} 226}
195 227
196//================================================ 228//================================================
@@ -199,83 +231,83 @@ static void set_vclk(struct cyblafb_par *par, int freq)
199// 231//
200//================================================ 232//================================================
201 233
202static void cyblafb_setup_GE(int pitch,int bpp) 234static void cyblafb_setup_GE(int pitch, int bpp)
203{ 235{
204 int base = (pitch>>3)<<20; 236 KD_GRAPHICS_RETURN();
205 237
206 switch (bpp) { 238 switch (bpp) {
207 case 8: base |= (0<<29); break; 239 case 8:
208 case 15: base |= (5<<29); break; 240 basestride = ((pitch >> 3) << 20) | (0 << 29);
209 case 16: base |= (1<<29); break; 241 break;
210 case 24: 242 case 15:
211 case 32: base |= (2<<29); break; 243 basestride = ((pitch >> 3) << 20) | (5 << 29);
244 break;
245 case 16:
246 basestride = ((pitch >> 3) << 20) | (1 << 29);
247 break;
248 case 24:
249 case 32:
250 basestride = ((pitch >> 3) << 20) | (2 << 29);
251 break;
212 } 252 }
213 253
214 write3X4(CR36,0x90); // reset GE 254 write3X4(CR36, 0x90); // reset GE
215 write3X4(CR36,0x80); // enable GE 255 write3X4(CR36, 0x80); // enable GE
216 256 out32(GE24, 1 << 7); // reset all GE pointers by toggling
217 out32(GE24,1<<7); // reset all GE pointers 257 out32(GE24, 0); // d7 of GE24
218 out32(GE24,0); 258 write3X4(CR2D, 0x00); // GE Timinigs, no delays
219 259 out32(GE6C, 0); // Pattern and Style, p 129, ok
220 write3X4(CR2D,0x00); // GE Timinigs, no delays
221
222 out32(GEB8,base); // Destination Stride / Buffer Base 0, p 133
223 out32(GEBC,base); // Destination Stride / Buffer Base 1, p 133
224 out32(GEC0,base); // Destination Stride / Buffer Base 2, p 133
225 out32(GEC4,base); // Destination Stride / Buffer Base 3, p 133
226 out32(GEC8,base); // Source Stride / Buffer Base 0, p 133
227 out32(GECC,base); // Source Stride / Buffer Base 1, p 133
228 out32(GED0,base); // Source Stride / Buffer Base 2, p 133
229 out32(GED4,base); // Source Stride / Buffer Base 3, p 133
230 out32(GE6C,0); // Pattern and Style, p 129, ok
231} 260}
232 261
233//===================================================================== 262//=====================================================================
234// 263//
235// Although this is a .fb_sync function that could be enabled in 264// Cyberblade specific syncing
236// cyblafb_ops, we do not include it there. We sync immediately before 265//
237// new GE operations to improve performance. 266// A timeout might be caused by disabled mmio.
267// Cause:
268// - bit CR39 & 1 == 0 upon return, X trident driver bug
269// - kdm bug (KD_GRAPHICS not set on first switch)
270// - kernel design flaw (it believes in the correctness
271// of kdm/X
272// First we try to sync ignoring that problem, as most of the
273// time that will succeed immediately and the enable_mmio()
274// would only degrade performance.
238// 275//
239//===================================================================== 276//=====================================================================
240 277
241static int cyblafb_sync(struct fb_info *info) 278static int cyblafb_sync(struct fb_info *info)
242{ 279{
243 int status, i=100000; 280 u32 status, i = 100000;
244 while( ((status=in32(GE20)) & 0xFA800000) && i != 0) 281
282 KD_GRAPHICS_RETURN(0);
283
284 while (((status = in32(GE20)) & 0xFe800000) && i != 0)
245 i--; 285 i--;
246 286
247 if (i == 0) { 287 if (i == 0) {
248 // The timeout might be caused by disabled mmio.
249 // Cause:
250 // - bit CR39 & 1 == 0 upon return, X trident driver bug
251 // - kdm bug (KD_GRAPHICS not set on first switch)
252 // - kernel design flaw (it believes in the correctness
253 // of kdm/X
254 // So we make sure that mmio is enabled first ...
255 enable_mmio(); 288 enable_mmio();
256// show_trace(NULL,&status); 289 i = 1000000;
257 i=1000000; 290 while (((status = in32(GE20)) & 0xFA800000) && i != 0)
258 while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
259 i--; 291 i--;
260 if (i == 0) { 292 if (i == 0) {
261 output("GE Timeout, status: %x\n",status); 293 output("GE Timeout, status: %x\n", status);
262 if(status & 0x80000000) 294 if (status & 0x80000000)
263 output("Bresenham Engine : Busy\n"); 295 output("Bresenham Engine : Busy\n");
264 if(status & 0x40000000) 296 if (status & 0x40000000)
265 output("Setup Engine : Busy\n"); 297 output("Setup Engine : Busy\n");
266 if(status & 0x20000000) 298 if (status & 0x20000000)
267 output("SP / DPE : Busy\n"); 299 output("SP / DPE : Busy\n");
268 if(status & 0x10000000) 300 if (status & 0x10000000)
269 output("Memory Interface : Busy\n"); 301 output("Memory Interface : Busy\n");
270 if(status & 0x08000000) 302 if (status & 0x08000000)
271 output("Com Lst Proc : Busy\n"); 303 output("Com Lst Proc : Busy\n");
272 if(status & 0x04000000) 304 if (status & 0x04000000)
273 output("Block Write : Busy\n"); 305 output("Block Write : Busy\n");
274 if(status & 0x02000000) 306 if (status & 0x02000000)
275 output("Command Buffer : Full\n"); 307 output("Command Buffer : Full\n");
276 if(status & 0x01000000) 308 if (status & 0x01000000)
277 output("RESERVED : Busy\n"); 309 output("RESERVED : Busy\n");
278 if(status & 0x00800000) 310 if (status & 0x00800000)
279 output("PCI Write Buffer : Busy\n"); 311 output("PCI Write Buffer : Busy\n");
280 cyblafb_setup_GE(info->var.xres, 312 cyblafb_setup_GE(info->var.xres,
281 info->var.bits_per_pixel); 313 info->var.bits_per_pixel);
@@ -291,142 +323,193 @@ static int cyblafb_sync(struct fb_info *info)
291// 323//
292//============================== 324//==============================
293 325
294static void cyblafb_fillrect(struct fb_info * info, 326static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr)
295 const struct fb_fillrect *fr)
296{ 327{
297 int bpp = info->var.bits_per_pixel; 328 u32 bpp = info->var.bits_per_pixel, col, desty, height;
298 int col; 329
330 KD_GRAPHICS_RETURN();
299 331
300 switch (bpp) { 332 switch (bpp) {
301 default: 333 default:
302 case 8: col = fr->color; 334 case 8:
303 col |= col <<8; 335 col = fr->color;
304 col |= col <<16; 336 col |= col << 8;
305 break; 337 col |= col << 16;
306 case 16: col = ((u32 *)(info->pseudo_palette))[fr->color]; 338 break;
307 col |= col <<16; 339 case 16:
308 break; 340 col = ((u32 *) (info->pseudo_palette))[fr->color];
309 case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; 341 col |= col << 16;
310 break; 342 break;
343 case 32:
344 col = ((u32 *) (info->pseudo_palette))[fr->color];
345 break;
311 } 346 }
312 347
313 cyblafb_sync(info); 348 desty = fr->dy;
314 349 height = fr->height;
315 out32(GE60,col); 350 while (height) {
316 out32(GE48,fr->rop ? 0x66:ROP_S); 351 out32(GEB8, basestride | ((desty * info->var.xres_virtual *
317 out32(GE44,0x20000000|1<<19|1<<4|2<<2); 352 bpp) >> 6));
318 out32(GE08,point(fr->dx,fr->dy)); 353 out32(GE60, col);
319 out32(GE0C,point(fr->dx+fr->width-1,fr->dy+fr->height-1)); 354 out32(GE48, fr->rop ? 0x66 : ROP_S);
320 355 out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
356 out32(GE08, point(fr->dx, 0));
357 out32(GE0C, point(fr->dx + fr->width - 1,
358 height > 4096 ? 4095 : height - 1));
359 if (likely(height <= 4096))
360 return;
361 desty += 4096;
362 height -= 4096;
363 }
321} 364}
322 365
323//============================== 366//================================================
324// 367//
325// Cyberblade specific copyarea 368// Cyberblade specific copyarea
326// 369//
327//============================== 370// This function silently assumes that it never
371// will be called with width or height exceeding
372// 4096.
373//
374//================================================
328 375
329static void cyblafb_copyarea(struct fb_info *info, 376static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca)
330 const struct fb_copyarea *ca)
331{ 377{
332 __u32 s1,s2,d1,d2; 378 u32 s1, s2, d1, d2, direction;
333 int direction; 379
380 KD_GRAPHICS_RETURN();
381
382 s1 = point(ca->sx, 0);
383 s2 = point(ca->sx + ca->width - 1, ca->height - 1);
384 d1 = point(ca->dx, 0);
385 d2 = point(ca->dx + ca->width - 1, ca->height - 1);
334 386
335 s1 = point(ca->sx,ca->sy);
336 s2 = point(ca->sx+ca->width-1,ca->sy+ca->height-1);
337 d1 = point(ca->dx,ca->dy);
338 d2 = point(ca->dx+ca->width-1,ca->dy+ca->height-1);
339 if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx))) 387 if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx)))
340 direction = 0; 388 direction = 0;
341 else 389 else
342 direction = 2; 390 direction = 2;
343 391
344 cyblafb_sync(info); 392 out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual *
345 393 info->var.bits_per_pixel) >> 6));
346 out32(GE44,0xa0000000|1<<19|1<<2|direction); 394 out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual *
347 out32(GE00,direction?s2:s1); 395 info->var.bits_per_pixel) >> 6));
348 out32(GE04,direction?s1:s2); 396 out32(GE44, 0xa0000000 | 1 << 19 | 1 << 2 | direction);
349 out32(GE08,direction?d2:d1); 397 out32(GE00, direction ? s2 : s1);
350 out32(GE0C,direction?d1:d2); 398 out32(GE04, direction ? s1 : s2);
351 399 out32(GE08, direction ? d2 : d1);
400 out32(GE0C, direction ? d1 : d2);
352} 401}
353 402
354//======================================================================= 403//=======================================================================
355// 404//
356// Cyberblade specific imageblit 405// Cyberblade specific imageblit
357// 406//
358// Accelerated for the most usual case, blitting 1-bit deep character 407// Accelerated for the most usual case, blitting 1 - bit deep
359// character images. Everything else is passed to the generic imageblit. 408// character images. Everything else is passed to the generic imageblit
409// unless it is so insane that it is better to printk an alert.
410//
411// Hardware bug: _Never_ blit across pixel column 2048, that will lock
412// the system. We split those blit requests into three blitting
413// operations.
360// 414//
361//======================================================================= 415//=======================================================================
362 416
363static void cyblafb_imageblit(struct fb_info *info, 417static void cyblafb_imageblit(struct fb_info *info,
364 const struct fb_image *image) 418 const struct fb_image *image)
365{ 419{
366
367 u32 fgcol, bgcol; 420 u32 fgcol, bgcol;
421 u32 *pd = (u32 *) image->data;
422 u32 bpp = info->var.bits_per_pixel;
368 423
369 int i; 424 KD_GRAPHICS_RETURN();
370 int bpp = info->var.bits_per_pixel; 425
371 int index = 0; 426 // Used only for drawing the penguine (image->depth > 1)
372 int index_end=image->height * image->width / 8; 427 if (image->depth != 1) {
373 int width_dds=image->width / 32; 428 cfb_imageblit(info, image);
374 int width_dbs=image->width % 32; 429 return;
375 430 }
376 if (image->depth != 1 || bpp < 8 || bpp > 32 || bpp % 8 != 0 || 431 // That should never happen, but it would be fatal
377 image->width % 8 != 0 || image->width == 0 || image->height == 0) { 432 if (image->width == 0 || image->height == 0) {
378 cfb_imageblit(info,image); 433 output("imageblit: width/height 0 detected\n");
379 return; 434 return;
380 } 435 }
381 436
382 if (info->fix.visual == FB_VISUAL_TRUECOLOR || 437 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
383 info->fix.visual == FB_VISUAL_DIRECTCOLOR) { 438 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
384 fgcol = ((u32*)(info->pseudo_palette))[image->fg_color]; 439 fgcol = ((u32 *) (info->pseudo_palette))[image->fg_color];
385 bgcol = ((u32*)(info->pseudo_palette))[image->bg_color]; 440 bgcol = ((u32 *) (info->pseudo_palette))[image->bg_color];
386 } else { 441 } else {
387 fgcol = image->fg_color; 442 fgcol = image->fg_color;
388 bgcol = image->bg_color; 443 bgcol = image->bg_color;
389 } 444 }
390 445
391 switch (bpp) { 446 switch (bpp) {
392 case 8: 447 case 8:
393 fgcol |= fgcol <<8; fgcol |= fgcol <<16; 448 fgcol |= fgcol << 8;
394 bgcol |= bgcol <<8; bgcol |= bgcol <<16; 449 bgcol |= bgcol << 8;
395 break; 450 case 16:
396 case 16: 451 fgcol |= fgcol << 16;
397 fgcol |= fgcol <<16; 452 bgcol |= bgcol << 16;
398 bgcol |= bgcol <<16; 453 default:
399 break; 454 break;
400 default:
401 break;
402 } 455 }
403 456
404 cyblafb_sync(info); 457 out32(GEB8, basestride | ((image->dy * info->var.xres_virtual *
405 458 bpp) >> 6));
406 out32(GE60,fgcol); 459 out32(GE60, fgcol);
407 out32(GE64,bgcol); 460 out32(GE64, bgcol);
408 out32(GE44,0xa0000000 | 1<<20 | 1<<19); 461
409 out32(GE08,point(image->dx,image->dy)); 462 if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) {
410 out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1)); 463 u32 dds = ((image->width + 31) >> 5) * image->height;
464 out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
465 out32(GE08, point(image->dx, 0));
466 out32(GE0C, point(image->dx + image->width - 1,
467 image->height - 1));
468 while (dds--)
469 out32(GE9C, *pd++);
470 } else {
471 int i, j;
472 u32 ddstotal = (image->width + 31) >> 5;
473 u32 ddsleft = (2048 - image->dx + 31) >> 5;
474 u32 skipleft = ddstotal - ddsleft;
475
476 out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
477 out32(GE08, point(image->dx, 0));
478 out32(GE0C, point(2048 - 1, image->height - 1));
479 for (i = 0; i < image->height; i++) {
480 for (j = 0; j < ddsleft; j++)
481 out32(GE9C, *pd++);
482 pd += skipleft;
483 }
411 484
412 while(index < index_end) { 485 if (image->dx % 32) {
413 const char *p = image->data + index; 486 out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
414 for(i=0;i<width_dds;i++) { 487 out32(GE08, point(2048, 0));
415 out32(GE9C,*(u32*)p); 488 if (image->width > ddsleft << 5)
416 p+=4; 489 out32(GE0C, point(image->dx + (ddsleft << 5) -
417 index+=4; 490 1, image->height - 1));
491 else
492 out32(GE0C, point(image->dx + image->width - 1,
493 image->height - 1));
494 pd = ((u32 *) image->data) + ddstotal - skipleft - 1;
495 for (i = 0; i < image->height; i++) {
496 out32(GE9C, swab32(swab32(*pd) << ((32 -
497 (image->dx & 31)) & 31)));
498 pd += ddstotal;
499 }
418 } 500 }
419 switch(width_dbs) { 501
420 case 0: break; 502 if (skipleft) {
421 case 8: out32(GE9C,*(u8*)p); 503 out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
422 index+=1; 504 out32(GE08, point(image->dx + (ddsleft << 5), 0));
423 break; 505 out32(GE0C, point(image->dx + image->width - 1,
424 case 16: out32(GE9C,*(u16*)p); 506 image->height - 1));
425 index+=2; 507 pd = (u32 *) image->data;
426 break; 508 for (i = 0; i < image->height; i++) {
427 case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16); 509 pd += ddsleft;
428 index+=3; 510 for (j = 0; j < skipleft; j++)
429 break; 511 out32(GE9C, *pd++);
512 }
430 } 513 }
431 } 514 }
432} 515}
@@ -443,7 +526,6 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
443 struct fb_info *info) 526 struct fb_info *info)
444{ 527{
445 int bpp = var->bits_per_pixel; 528 int bpp = var->bits_per_pixel;
446 int s,t,maxvyres;
447 529
448 // 530 //
449 // we try to support 8, 16, 24 and 32 bpp modes, 531 // 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,
453 // (This is what tridentfb does ... will be changed in the future) 535 // (This is what tridentfb does ... will be changed in the future)
454 // 536 //
455 // 537 //
456 if ( bpp % 8 != 0 || bpp < 8 || bpp >32) 538 if (bpp % 8 != 0 || bpp < 8 || bpp > 32)
457 bpp = 8; 539 bpp = 8;
458 if (bpp == 24 ) 540 if (bpp == 24)
459 bpp = var->bits_per_pixel = 32; 541 bpp = var->bits_per_pixel = 32;
460 542
461 // 543 //
@@ -472,65 +554,93 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
472 return -EINVAL; 554 return -EINVAL;
473 555
474 // 556 //
475 // xres != xres_virtual is broken, fail if such an 557 // we do not allow vclk to exceed 230 MHz. If the requested
476 // unusual mode is requested 558 // vclk is too high, we default to 200 MHz
477 // 559 //
478 if (var->xres != var->xres_virtual) 560 if ((bpp == 32 ? 200000000 : 100000000) / var->pixclock > 23000)
479 return -EINVAL; 561 var->pixclock = (bpp == 32 ? 200000000 : 100000000) / 20000;
480 562
481 // 563 //
482 // we do not allow vclk to exceed 230 MHz 564 // enforce (h|v)sync_len limits
483 // 565 //
484 if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000) 566 var->hsync_len &= ~7;
485 return -EINVAL; 567 if(var->hsync_len > 248)
568 var->hsync_len = 248;
569
570 var->vsync_len &= 15;
486 571
487 // 572 //
488 // calc max yres_virtual that would fit in memory 573 // Enforce horizontal and vertical hardware limits.
489 // and max yres_virtual that could be used for scrolling 574 // 1600x1200 is mentioned as a maximum, but higher resolutions could
490 // and use minimum of the results as maxvyres 575 // work with slow refresh, small margins and short sync.
491 //
492 // adjust vyres_virtual to maxvyres if necessary
493 // fail if requested yres is bigger than maxvyres
494 // 576 //
495 s = (0x1fffff / (var->xres * bpp/8)) + var->yres; 577 var->xres &= ~7;
496 t = info->fix.smem_len / (var->xres * bpp/8); 578
497 maxvyres = t < s ? t : s; 579 if (((var->xres + var->left_margin + var->right_margin +
498 if (maxvyres < var->yres_virtual) 580 var->hsync_len) > (bpp == 32 ? 2040 : 4088)) ||
499 var->yres_virtual=maxvyres; 581 ((var->yres + var->upper_margin + var->lower_margin +
500 if (maxvyres < var->yres) 582 var->vsync_len) > 2047))
501 return -EINVAL; 583 return -EINVAL;
502 584
503 switch (bpp) { 585 if ((var->xres > 1600) || (var->yres > 1200))
504 case 8: 586 output("Mode %dx%d exceeds documented limits.\n",
505 var->red.offset = 0; 587 var->xres, var->yres);
506 var->green.offset = 0; 588 //
507 var->blue.offset = 0; 589 // try to be smart about (x|y)res_virtual problems.
508 var->red.length = 6; 590 //
509 var->green.length = 6; 591 if (var->xres > var->xres_virtual)
510 var->blue.length = 6; 592 var->xres_virtual = var->xres;
511 break; 593 if (var->yres > var->yres_virtual)
512 case 16: 594 var->yres_virtual = var->yres;
513 var->red.offset = 11; 595
514 var->green.offset = 5; 596 if (bpp == 8 || bpp == 16) {
515 var->blue.offset = 0; 597 if (var->xres_virtual > 4088)
516 var->red.length = 5; 598 var->xres_virtual = 4088;
517 var->green.length = 6; 599 } else {
518 var->blue.length = 5; 600 if (var->xres_virtual > 2040)
519 break; 601 var->xres_virtual = 2040;
520 case 32: 602 }
521 var->red.offset = 16; 603 var->xres_virtual &= ~7;
522 var->green.offset = 8; 604 while (var->xres_virtual * var->yres_virtual * bpp / 8 >
523 var->blue.offset = 0; 605 info->fix.smem_len) {
524 var->red.length = 8; 606 if (var->yres_virtual > var->yres)
525 var->green.length = 8; 607 var->yres_virtual--;
526 var->blue.length = 8; 608 else if (var->xres_virtual > var->xres)
527 break; 609 var->xres_virtual -= 8;
528 default: 610 else
529 return -EINVAL; 611 return -EINVAL;
530 } 612 }
531 613
532 return 0; 614 switch (bpp) {
615 case 8:
616 var->red.offset = 0;
617 var->green.offset = 0;
618 var->blue.offset = 0;
619 var->red.length = 6;
620 var->green.length = 6;
621 var->blue.length = 6;
622 break;
623 case 16:
624 var->red.offset = 11;
625 var->green.offset = 5;
626 var->blue.offset = 0;
627 var->red.length = 5;
628 var->green.length = 6;
629 var->blue.length = 5;
630 break;
631 case 32:
632 var->red.offset = 16;
633 var->green.offset = 8;
634 var->blue.offset = 0;
635 var->red.length = 8;
636 var->green.length = 8;
637 var->blue.length = 8;
638 break;
639 default:
640 return -EINVAL;
641 }
533 642
643 return 0;
534} 644}
535 645
536//===================================================================== 646//=====================================================================
@@ -543,23 +653,25 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
543// it, so it is also safe to be used here. BTW: datasheet CR0E on page 653// it, so it is also safe to be used here. BTW: datasheet CR0E on page
544// 90 really is CR1E, the real CRE is documented on page 72. 654// 90 really is CR1E, the real CRE is documented on page 72.
545// 655//
656// BUT:
657//
658// As of internal version 0.60 we do not use vga panning any longer.
659// Vga panning did not allow us the use of all available video memory
660// and thus prevented ywrap scrolling. We do use the "right view"
661// register now.
662//
663//
546//===================================================================== 664//=====================================================================
547 665
548static int cyblafb_pan_display(struct fb_var_screeninfo *var, 666static int cyblafb_pan_display(struct fb_var_screeninfo *var,
549 struct fb_info *info) 667 struct fb_info *info)
550{ 668{
551 unsigned int offset; 669 KD_GRAPHICS_RETURN(0);
552 670
553 offset=(var->xoffset+(var->yoffset*var->xres))*var->bits_per_pixel/32;
554 info->var.xoffset = var->xoffset; 671 info->var.xoffset = var->xoffset;
555 info->var.yoffset = var->yoffset; 672 info->var.yoffset = var->yoffset;
556 673 out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset *
557 write3X4(CR0D,offset & 0xFF); 674 var->xres_virtual)) * var->bits_per_pixel / 32));
558 write3X4(CR0C,(offset & 0xFF00) >> 8);
559 write3X4(CR1E,(read3X4(CR1E) & 0xDF) | ((offset & 0x10000) >> 11));
560 write3X4(CR27,(read3X4(CR27) & 0xF8) | ((offset & 0xE0000) >> 17));
561 write3X4(CR2B,(read3X4(CR2B) & 0xDF) | ((offset & 0x100000) >> 15));
562
563 return 0; 675 return 0;
564} 676}
565 677
@@ -578,56 +690,96 @@ static void regdump(struct cyblafb_par *par)
578 return; 690 return;
579 691
580 printk("\n"); 692 printk("\n");
581 for(i=0; i<=0xff; i++) { 693 for (i = 0; i <= 0xff; i++) {
582 outb(i,0x3d4); 694 outb(i, 0x3d4);
583 printk("CR%02x=%02x ",i,inb(0x3d5)); 695 printk("CR%02x=%02x ", i, inb(0x3d5));
584 if (i%16==15) 696 if (i % 16 == 15)
585 printk("\n"); 697 printk("\n");
586 } 698 }
587 699
588 outb(0x30,0x3ce); 700 outb(0x30, 0x3ce);
589 outb(inb(0x3cf) | 0x40,0x3cf); 701 outb(inb(0x3cf) | 0x40, 0x3cf);
590 for(i=0; i<=0x1f; i++) { 702 for (i = 0; i <= 0x1f; i++) {
591 if (i==0 || (i>2 && i<8) || i==0x10 || i==0x11 || i==0x16) { 703 if (i == 0 || (i > 2 && i < 8) || i == 0x10 || i == 0x11
592 outb(i,0x3d4); 704 || i == 0x16) {
593 printk("CR%02x=%02x ",i,inb(0x3d5)); 705 outb(i, 0x3d4);
706 printk("CR%02x=%02x ", i, inb(0x3d5));
594 } else 707 } else
595 printk("------- "); 708 printk("------- ");
596 if (i%16==15) 709 if (i % 16 == 15)
597 printk("\n"); 710 printk("\n");
598 } 711 }
599 outb(0x30,0x3ce); 712 outb(0x30, 0x3ce);
600 outb(inb(0x3cf) & 0xbf,0x3cf); 713 outb(inb(0x3cf) & 0xbf, 0x3cf);
601 714
602 printk("\n"); 715 printk("\n");
603 for(i=0; i<=0x7f; i++) { 716 for (i = 0; i <= 0x7f; i++) {
604 outb(i,0x3ce); 717 outb(i, 0x3ce);
605 printk("GR%02x=%02x ",i,inb(0x3cf)); 718 printk("GR%02x=%02x ", i, inb(0x3cf));
606 if (i%16==15) 719 if (i % 16 == 15)
607 printk("\n"); 720 printk("\n");
608 } 721 }
609 722
610 printk("\n"); 723 printk("\n");
611 for(i=0; i<=0xff; i++) { 724 for (i = 0; i <= 0xff; i++) {
612 outb(i,0x3c4); 725 outb(i, 0x3c4);
613 printk("SR%02x=%02x ",i,inb(0x3c5)); 726 printk("SR%02x=%02x ", i, inb(0x3c5));
614 if (i%16==15) 727 if (i % 16 == 15)
615 printk("\n"); 728 printk("\n");
616 } 729 }
617 730
618 printk("\n"); 731 printk("\n");
619 for(i=0; i <= 0x1F; i++) { 732 for (i = 0; i <= 0x1F; i++) {
620 inb(0x3da); // next access is index! 733 inb(0x3da); // next access is index!
621 outb(i,0x3c0); 734 outb(i, 0x3c0);
622 printk("AR%02x=%02x ",i,inb(0x3c1)); 735 printk("AR%02x=%02x ", i, inb(0x3c1));
623 if (i%16==15) 736 if (i % 16 == 15)
624 printk("\n"); 737 printk("\n");
625 } 738 }
626 printk("\n"); 739 printk("\n");
627 740
628 inb(0x3DA); // reset internal flag to 3c0 index 741 inb(0x3DA); // reset internal flag to 3c0 index
629 outb(0x20,0x3C0); // enable attr 742 outb(0x20, 0x3C0); // enable attr
743
744 return;
745}
746
747//=======================================================================
748//
749// Save State
750//
751// This function is called while a switch to KD_TEXT is in progress,
752// before any of the other functions are called.
753//
754//=======================================================================
630 755
756static void cyblafb_save_state(struct fb_info *info)
757{
758 struct cyblafb_par *par = info->par;
759 if (verbosity > 0)
760 output("Switching to KD_TEXT\n");
761 disabled = 0;
762 regdump(par);
763 enable_mmio();
764 return;
765}
766
767//=======================================================================
768//
769// Restore State
770//
771// This function is called while a switch to KD_GRAPHICS is in progress,
772// We have to turn on vga style panning registers again because the
773// trident driver of X does not know about GE10.
774//
775//=======================================================================
776
777static void cyblafb_restore_state(struct fb_info *info)
778{
779 if (verbosity > 0)
780 output("Switching to KD_GRAPHICS\n");
781 out32(GE10, 0);
782 disabled = 1;
631 return; 783 return;
632} 784}
633 785
@@ -640,32 +792,34 @@ static void regdump(struct cyblafb_par *par)
640static int cyblafb_set_par(struct fb_info *info) 792static int cyblafb_set_par(struct fb_info *info)
641{ 793{
642 struct cyblafb_par *par = info->par; 794 struct cyblafb_par *par = info->par;
643 u32 795 u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart,
644 htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,preendfetch, 796 hblankend, preendfetch, vtotal, vdispend, vsyncstart,
645 vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend; 797 vsyncend, vblankstart, vblankend;
646 struct fb_var_screeninfo *var = &info->var; 798 struct fb_var_screeninfo *var = &info->var;
647 int bpp = var->bits_per_pixel; 799 int bpp = var->bits_per_pixel;
648 int i; 800 int i;
649 801
802 KD_GRAPHICS_RETURN(0);
803
650 if (verbosity > 0) 804 if (verbosity > 0)
651 output("Switching to new mode: " 805 output("Switching to new mode: "
652 "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n", 806 "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n",
653 var->xres,var->yres,var->xres_virtual, 807 var->xres, var->yres, var->xres_virtual,
654 var->yres_virtual,var->bits_per_pixel,var->pixclock, 808 var->yres_virtual, var->bits_per_pixel, var->pixclock,
655 var->left_margin,var->right_margin,var->upper_margin, 809 var->left_margin, var->right_margin, var->upper_margin,
656 var->lower_margin,var->hsync_len,var->vsync_len); 810 var->lower_margin, var->hsync_len, var->vsync_len);
657 811
658 htotal = (var->xres + var->left_margin + var->right_margin + 812 htotal = (var->xres + var->left_margin + var->right_margin +
659 var->hsync_len) / 8 - 5; 813 var->hsync_len) / 8 - 5;
660 hdispend = var->xres/8 - 1; 814 hdispend = var->xres / 8 - 1;
661 hsyncstart = (var->xres + var->right_margin)/8; 815 hsyncstart = (var->xres + var->right_margin) / 8;
662 hsyncend = var->hsync_len/8; 816 hsyncend = var->hsync_len / 8;
663 hblankstart = hdispend + 1; 817 hblankstart = hdispend + 1;
664 hblankend = htotal + 3; // should be htotal + 5, bios does it this way 818 hblankend = htotal + 3; // should be htotal + 5, bios does it this way
665 preendfetch = ((var->xres >> 3) + 1) * ((bpp+1) >> 3); 819 preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3);
666 820
667 vtotal = var->yres + var->upper_margin + var->lower_margin + 821 vtotal = var->yres + var->upper_margin + var->lower_margin +
668 var->vsync_len - 2; 822 var->vsync_len - 2;
669 vdispend = var->yres - 1; 823 vdispend = var->yres - 1;
670 vsyncstart = var->yres + var->lower_margin; 824 vsyncstart = var->yres + var->lower_margin;
671 vblankstart = var->yres; 825 vblankstart = var->yres;
@@ -674,101 +828,99 @@ static int cyblafb_set_par(struct fb_info *info)
674 828
675 enable_mmio(); // necessary! ... check X ... 829 enable_mmio(); // necessary! ... check X ...
676 830
677 write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07 831 write3X4(CR11, read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
678 832
679 write3CE(GR30,8); 833 write3CE(GR30, 8);
680 834
681 if ((displaytype == DISPLAY_FP) && var->xres < nativex) { 835 if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
682 836
683 // stretch or center ? 837 // stretch or center ?
684 838
685 out8(0x3C2,0xEB); 839 out8(0x3C2, 0xEB);
686 840
687 write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on 841 write3CE(GR30, read3CE(GR30) | 0x81); // shadow mode on
688 842
689 if (center) { 843 if (center) {
690 write3CE(GR52,(read3CE(GR52) & 0x7C) | 0x80); 844 write3CE(GR52, (read3CE(GR52) & 0x7C) | 0x80);
691 write3CE(GR53,(read3CE(GR53) & 0x7C) | 0x80); 845 write3CE(GR53, (read3CE(GR53) & 0x7C) | 0x80);
692 } 846 } else if (stretch) {
693 else if (stretch) { 847 write3CE(GR5D, 0);
694 write3CE(GR5D,0); 848 write3CE(GR52, (read3CE(GR52) & 0x7C) | 1);
695 write3CE(GR52,(read3CE(GR52) & 0x7C) | 1); 849 write3CE(GR53, (read3CE(GR53) & 0x7C) | 1);
696 write3CE(GR53,(read3CE(GR53) & 0x7C) | 1);
697 } 850 }
698 851
699 } else { 852 } else {
700 out8(0x3C2,0x2B); 853 out8(0x3C2, 0x2B);
701 write3CE(GR30,8); 854 write3CE(GR30, 8);
702 } 855 }
703 856
704 // 857 //
705 // Setup CRxx regs 858 // Setup CRxx regs
706 // 859 //
707 860
708 write3X4(CR00,htotal & 0xFF); 861 write3X4(CR00, htotal & 0xFF);
709 write3X4(CR01,hdispend & 0xFF); 862 write3X4(CR01, hdispend & 0xFF);
710 write3X4(CR02,hblankstart & 0xFF); 863 write3X4(CR02, hblankstart & 0xFF);
711 write3X4(CR03,hblankend & 0x1F); 864 write3X4(CR03, hblankend & 0x1F);
712 write3X4(CR04,hsyncstart & 0xFF); 865 write3X4(CR04, hsyncstart & 0xFF);
713 write3X4(CR05,(hsyncend & 0x1F) | ((hblankend & 0x20)<<2)); 866 write3X4(CR05, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
714 write3X4(CR06,vtotal & 0xFF); 867 write3X4(CR06, vtotal & 0xFF);
715 write3X4(CR07,(vtotal & 0x100) >> 8 | 868 write3X4(CR07, (vtotal & 0x100) >> 8 |
716 (vdispend & 0x100) >> 7 | 869 (vdispend & 0x100) >> 7 |
717 (vsyncstart & 0x100) >> 6 | 870 (vsyncstart & 0x100) >> 6 |
718 (vblankstart & 0x100) >> 5 | 871 (vblankstart & 0x100) >> 5 |
719 0x10 | 872 0x10 |
720 (vtotal & 0x200) >> 4 | 873 (vtotal & 0x200) >> 4 |
721 (vdispend & 0x200) >> 3 | 874 (vdispend & 0x200) >> 3 | (vsyncstart & 0x200) >> 2);
722 (vsyncstart & 0x200) >> 2); 875 write3X4(CR08, 0);
723 write3X4(CR08,0); 876 write3X4(CR09, (vblankstart & 0x200) >> 4 | 0x40 | // FIX !!!
724 write3X4(CR09,(vblankstart & 0x200) >> 4 | 0x40 | // FIX !!! 877 ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));
725 ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0)); 878 write3X4(CR0A, 0); // Init to some reasonable default
726 write3X4(CR0A,0); // Init to some reasonable default 879 write3X4(CR0B, 0); // Init to some reasonable default
727 write3X4(CR0B,0); // Init to some reasonable default 880 write3X4(CR0C, 0); // Offset 0
728 write3X4(CR0C,0); // Offset 0 881 write3X4(CR0D, 0); // Offset 0
729 write3X4(CR0D,0); // Offset 0 882 write3X4(CR0E, 0); // Init to some reasonable default
730 write3X4(CR0E,0); // Init to some reasonable default 883 write3X4(CR0F, 0); // Init to some reasonable default
731 write3X4(CR0F,0); // Init to some reasonable default 884 write3X4(CR10, vsyncstart & 0xFF);
732 write3X4(CR10,vsyncstart & 0xFF); 885 write3X4(CR11, (vsyncend & 0x0F));
733 write3X4(CR11,(vsyncend & 0x0F)); 886 write3X4(CR12, vdispend & 0xFF);
734 write3X4(CR12,vdispend & 0xFF); 887 write3X4(CR13, ((info->var.xres_virtual * bpp) / (4 * 16)) & 0xFF);
735 write3X4(CR13,((info->var.xres * bpp)/(4*16)) & 0xFF); 888 write3X4(CR14, 0x40); // double word mode
736 write3X4(CR14,0x40); // double word mode 889 write3X4(CR15, vblankstart & 0xFF);
737 write3X4(CR15,vblankstart & 0xFF); 890 write3X4(CR16, vblankend & 0xFF);
738 write3X4(CR16,vblankend & 0xFF); 891 write3X4(CR17, 0xE3);
739 write3X4(CR17,0xC3); 892 write3X4(CR18, 0xFF);
740 write3X4(CR18,0xFF);
741 // CR19: needed for interlaced modes ... ignore it for now 893 // CR19: needed for interlaced modes ... ignore it for now
742 write3X4(CR1A,0x07); // Arbitration Control Counter 1 894 write3X4(CR1A, 0x07); // Arbitration Control Counter 1
743 write3X4(CR1B,0x07); // Arbitration Control Counter 2 895 write3X4(CR1B, 0x07); // Arbitration Control Counter 2
744 write3X4(CR1C,0x07); // Arbitration Control Counter 3 896 write3X4(CR1C, 0x07); // Arbitration Control Counter 3
745 write3X4(CR1D,0x00); // Don't know, doesn't hurt ;-) 897 write3X4(CR1D, 0x00); // Don't know, doesn't hurt ; -)
746 write3X4(CR1E,(info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80); 898 write3X4(CR1E, (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);
747 // CR1F: do not set, contains BIOS info about memsize 899 // CR1F: do not set, contains BIOS info about memsize
748 write3X4(CR20,0x20); // enabe wr buf, disable 16bit planar mode 900 write3X4(CR20, 0x20); // enabe wr buf, disable 16bit planar mode
749 write3X4(CR21,0x20); // enable linear memory access 901 write3X4(CR21, 0x20); // enable linear memory access
750 // CR22: RO cpu latch readback 902 // CR22: RO cpu latch readback
751 // CR23: ??? 903 // CR23: ???
752 // CR24: RO AR flag state 904 // CR24: RO AR flag state
753 // CR25: RAMDAC rw timing, pclk buffer tristate control ???? 905 // CR25: RAMDAC rw timing, pclk buffer tristate control ????
754 // CR26: ??? 906 // CR26: ???
755 write3X4(CR27,(vdispend & 0x400) >> 6 | 907 write3X4(CR27, (vdispend & 0x400) >> 6 |
756 (vsyncstart & 0x400) >> 5 | 908 (vsyncstart & 0x400) >> 5 |
757 (vblankstart & 0x400) >> 4 | 909 (vblankstart & 0x400) >> 4 |
758 (vtotal & 0x400) >> 3 | 910 (vtotal & 0x400) >> 3 |
759 0x8); 911 0x8);
760 // CR28: ??? 912 // CR28: ???
761 write3X4(CR29,(read3X4(CR29) & 0xCF) | 913 write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual *
762 ((((info->var.xres * bpp) / (4*16)) & 0x300) >>4)); 914 bpp) / (4 * 16)) & 0x300) >> 4));
763 write3X4(CR2A,read3X4(CR2A) | 0x40); 915 write3X4(CR2A, read3X4(CR2A) | 0x40);
764 write3X4(CR2B,(htotal & 0x100) >> 8 | 916 write3X4(CR2B, (htotal & 0x100) >> 8 |
765 (hdispend & 0x100) >> 7 | 917 (hdispend & 0x100) >> 7 |
766 // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ??? 918 // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ???
767 (hsyncstart & 0x100) >> 5 | 919 (hsyncstart & 0x100) >> 5 |
768 (hblankstart & 0x100) >> 4); 920 (hblankstart & 0x100) >> 4);
769 // CR2C: ??? 921 // CR2C: ???
770 // CR2D: initialized in cyblafb_setup_GE() 922 // CR2D: initialized in cyblafb_setup_GE()
771 write3X4(CR2F,0x92); // conservative, better signal quality 923 write3X4(CR2F, 0x92); // conservative, better signal quality
772 // CR30: reserved 924 // CR30: reserved
773 // CR31: reserved 925 // CR31: reserved
774 // CR32: reserved 926 // CR32: reserved
@@ -777,96 +929,116 @@ static int cyblafb_set_par(struct fb_info *info)
777 // CR35: disabled in CR36 929 // CR35: disabled in CR36
778 // CR36: initialized in cyblafb_setup_GE 930 // CR36: initialized in cyblafb_setup_GE
779 // CR37: i2c, ignore for now 931 // CR37: i2c, ignore for now
780 write3X4(CR38,(bpp == 8) ? 0x00 : // 932 write3X4(CR38, (bpp == 8) ? 0x00 : //
781 (bpp == 16) ? 0x05 : // highcolor 933 (bpp == 16) ? 0x05 : // highcolor
782 (bpp == 24) ? 0x29 : // packed 24bit truecolor 934 (bpp == 24) ? 0x29 : // packed 24bit truecolor
783 (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus 935 (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus
784 write3X4(CR39,0x01 | // MMIO enable 936 write3X4(CR39, 0x01 | // MMIO enable
785 (pcirb ? 0x02 : 0) | // pci read burst enable 937 (pcirb ? 0x02 : 0) | // pci read burst enable
786 (pciwb ? 0x04 : 0)); // pci write burst enable 938 (pciwb ? 0x04 : 0)); // pci write burst enable
787 write3X4(CR55,0x1F | // pci clocks * 2 for STOP# during 1st data phase 939 write3X4(CR55, 0x1F | // pci clocks * 2 for STOP# during 1st data phase
788 (pcirr ? 0x40 : 0) | // pci read retry enable 940 (pcirr ? 0x40 : 0) | // pci read retry enable
789 (pciwr ? 0x80 : 0)); // pci write retry enable 941 (pciwr ? 0x80 : 0)); // pci write retry enable
790 write3X4(CR56,preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01)|2 : 0); 942 write3X4(CR56, preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01) | 2
791 write3X4(CR57,preendfetch >> 8 < 2 ? preendfetch & 0xff : 0); 943 : 0);
792 write3X4(CR58,0x82); // Bios does this .... don't know more 944 write3X4(CR57, preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);
945 write3X4(CR58, 0x82); // Bios does this .... don't know more
793 // 946 //
794 // Setup SRxx regs 947 // Setup SRxx regs
795 // 948 //
796 write3C4(SR00,3); 949 write3C4(SR00, 3);
797 write3C4(SR01,1); //set char clock 8 dots wide 950 write3C4(SR01, 1); //set char clock 8 dots wide
798 write3C4(SR02,0x0F); //enable 4 maps needed in chain4 mode 951 write3C4(SR02, 0x0F); //enable 4 maps needed in chain4 mode
799 write3C4(SR03,0); //no character map select 952 write3C4(SR03, 0); //no character map select
800 write3C4(SR04,0x0E); //memory mode: ext mem, even, chain4 953 write3C4(SR04, 0x0E); //memory mode: ext mem, even, chain4
801 954
802 out8(0x3C4,0x0b); 955 out8(0x3C4, 0x0b);
803 in8(0x3C5); // Set NEW mode 956 in8(0x3C5); // Set NEW mode
804 write3C4(SR0D,0x00); // test ... check 957 write3C4(SR0D, 0x00); // test ... check
805 958
806 set_vclk(par,(bpp==32 ? 200000000 : 100000000)/ 959 set_vclk(par, (bpp == 32 ? 200000000 : 100000000)
807 info->var.pixclock); //SR18,SR19 960 / info->var.pixclock); //SR18, SR19
808 961
809 // 962 //
810 // Setup GRxx regs 963 // Setup GRxx regs
811 // 964 //
812 write3CE(GR00,0x00); // test ... check 965 write3CE(GR00, 0x00); // test ... check
813 write3CE(GR01,0x00); // test ... check 966 write3CE(GR01, 0x00); // test ... check
814 write3CE(GR02,0x00); // test ... check 967 write3CE(GR02, 0x00); // test ... check
815 write3CE(GR03,0x00); // test ... check 968 write3CE(GR03, 0x00); // test ... check
816 write3CE(GR04,0x00); // test ... check 969 write3CE(GR04, 0x00); // test ... check
817 write3CE(GR05,0x40); // no CGA compat,allow 256 col 970 write3CE(GR05, 0x40); // no CGA compat, allow 256 col
818 write3CE(GR06,0x05); // graphics mode 971 write3CE(GR06, 0x05); // graphics mode
819 write3CE(GR07,0x0F); // planes? 972 write3CE(GR07, 0x0F); // planes?
820 write3CE(GR08,0xFF); // test ... check 973 write3CE(GR08, 0xFF); // test ... check
821 write3CE(GR0F,(bpp==32)?0x1A:0x12); // div vclk by 2 if 32bpp, chain4 974 write3CE(GR0F, (bpp == 32) ? 0x1A : 0x12); // vclk / 2 if 32bpp, chain4
822 write3CE(GR20,0xC0); // test ... check 975 write3CE(GR20, 0xC0); // test ... check
823 write3CE(GR2F,0xA0); // PCLK = VCLK, no skew, 976 write3CE(GR2F, 0xA0); // PCLK = VCLK, no skew,
824 977
825 // 978 //
826 // Setup ARxx regs 979 // Setup ARxx regs
827 // 980 //
828 for(i = 0;i < 0x10;i++) // set AR00 .. AR0f 981 for (i = 0; i < 0x10; i++) // set AR00 .. AR0f
829 write3C0(i,i); 982 write3C0(i, i);
830 write3C0(AR10,0x41); // graphics mode and support 256 color modes 983 write3C0(AR10, 0x41); // graphics mode and support 256 color modes
831 write3C0(AR12,0x0F); // planes 984 write3C0(AR12, 0x0F); // planes
832 write3C0(AR13,0); // horizontal pel panning 985 write3C0(AR13, 0); // horizontal pel panning
833 in8(0x3DA); // reset internal flag to 3c0 index 986 in8(0x3DA); // reset internal flag to 3c0 index
834 out8(0x3C0,0x20); // enable attr 987 out8(0x3C0, 0x20); // enable attr
835 988
836 // 989 //
837 // Setup hidden RAMDAC command register 990 // Setup hidden RAMDAC command register
838 // 991 //
839 in8(0x3C8); // these reads are 992 in8(0x3C8); // these reads are
840 in8(0x3C6); // necessary to 993 in8(0x3C6); // necessary to
841 in8(0x3C6); // unmask the RAMDAC 994 in8(0x3C6); // unmask the RAMDAC
842 in8(0x3C6); // command reg, otherwise 995 in8(0x3C6); // command reg, otherwise
843 in8(0x3C6); // we would write the pixelmask reg! 996 in8(0x3C6); // we would write the pixelmask reg!
844 out8(0x3C6,(bpp == 8) ? 0x00 : // 256 colors 997 out8(0x3C6, (bpp == 8) ? 0x00 : // 256 colors
845 (bpp == 15) ? 0x10 : // 998 (bpp == 15) ? 0x10 : //
846 (bpp == 16) ? 0x30 : // hicolor 999 (bpp == 16) ? 0x30 : // hicolor
847 (bpp == 24) ? 0xD0 : // truecolor 1000 (bpp == 24) ? 0xD0 : // truecolor
848 (bpp == 32) ? 0xD0 : 0); // truecolor 1001 (bpp == 32) ? 0xD0 : 0); // truecolor
849 in8(0x3C8); 1002 in8(0x3C8);
850 1003
851 // 1004 //
852 // GR31 is not mentioned in the datasheet 1005 // GR31 is not mentioned in the datasheet
853 // 1006 //
854 if (displaytype == DISPLAY_FP) 1007 if (displaytype == DISPLAY_FP)
855 write3CE(GR31,(read3CE(GR31) & 0x8F) | 1008 write3CE(GR31, (read3CE(GR31) & 0x8F) |
856 ((info->var.yres > 1024) ? 0x50 : 1009 ((info->var.yres > 1024) ? 0x50 :
857 (info->var.yres > 768) ? 0x30 : 1010 (info->var.yres > 768) ? 0x30 :
858 (info->var.yres > 600) ? 0x20 : 1011 (info->var.yres > 600) ? 0x20 :
859 (info->var.yres > 480) ? 0x10 : 0)); 1012 (info->var.yres > 480) ? 0x10 : 0));
860 1013
861 info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR 1014 info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR
862 : FB_VISUAL_TRUECOLOR; 1015 : FB_VISUAL_TRUECOLOR;
863 info->fix.line_length = info->var.xres * (bpp >> 3); 1016 info->fix.line_length = info->var.xres_virtual * (bpp >> 3);
864 info->cmap.len = (bpp == 8) ? 256: 16; 1017 info->cmap.len = (bpp == 8) ? 256 : 16;
865 1018
866 // 1019 //
867 // init acceleration engine 1020 // init acceleration engine
868 // 1021 //
869 cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel); 1022 cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel);
1023
1024 //
1025 // Set/clear flags to allow proper scroll mode selection.
1026 //
1027 if (var->xres == var->xres_virtual)
1028 info->flags &= ~FBINFO_HWACCEL_XPAN;
1029 else
1030 info->flags |= FBINFO_HWACCEL_XPAN;
1031
1032 if (var->yres == var->yres_virtual)
1033 info->flags &= ~FBINFO_HWACCEL_YPAN;
1034 else
1035 info->flags |= FBINFO_HWACCEL_YPAN;
1036
1037 if (info->fix.smem_len !=
1038 var->xres_virtual * var->yres_virtual * bpp / 8)
1039 info->flags &= ~FBINFO_HWACCEL_YWRAP;
1040 else
1041 info->flags |= FBINFO_HWACCEL_YWRAP;
870 1042
871 regdump(par); 1043 regdump(par);
872 1044
@@ -885,27 +1057,27 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
885{ 1057{
886 int bpp = info->var.bits_per_pixel; 1058 int bpp = info->var.bits_per_pixel;
887 1059
1060 KD_GRAPHICS_RETURN(0);
1061
888 if (regno >= info->cmap.len) 1062 if (regno >= info->cmap.len)
889 return 1; 1063 return 1;
890 1064
891 if (bpp == 8) { 1065 if (bpp == 8) {
892 out8(0x3C6,0xFF); 1066 out8(0x3C6, 0xFF);
893 out8(0x3C8,regno); 1067 out8(0x3C8, regno);
894 out8(0x3C9,red>>10); 1068 out8(0x3C9, red >> 10);
895 out8(0x3C9,green>>10); 1069 out8(0x3C9, green >> 10);
896 out8(0x3C9,blue>>10); 1070 out8(0x3C9, blue >> 10);
897 1071
898 } else if (bpp == 16) // RGB 565 1072 } else if (bpp == 16) // RGB 565
899 ((u32*)info->pseudo_palette)[regno] = 1073 ((u32 *) info->pseudo_palette)[regno] =
900 (red & 0xF800) | 1074 (red & 0xF800) |
901 ((green & 0xFC00) >> 5) | 1075 ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
902 ((blue & 0xF800) >> 11); 1076 else if (bpp == 32) // ARGB 8888
903 else if (bpp == 32) // ARGB 8888 1077 ((u32 *) info->pseudo_palette)[regno] =
904 ((u32*)info->pseudo_palette)[regno] = 1078 ((transp & 0xFF00) << 16) |
905 ((transp & 0xFF00) <<16) | 1079 ((red & 0xFF00) << 8) |
906 ((red & 0xFF00) << 8) | 1080 ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
907 ((green & 0xFF00)) |
908 ((blue & 0xFF00)>>8);
909 1081
910 return 0; 1082 return 0;
911} 1083}
@@ -918,40 +1090,41 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
918 1090
919static int cyblafb_blank(int blank_mode, struct fb_info *info) 1091static int cyblafb_blank(int blank_mode, struct fb_info *info)
920{ 1092{
921 unsigned char PMCont,DPMSCont; 1093 unsigned char PMCont, DPMSCont;
1094
1095 KD_GRAPHICS_RETURN(0);
922 1096
923 if (displaytype == DISPLAY_FP) 1097 if (displaytype == DISPLAY_FP)
924 return 0; 1098 return 0;
925 1099
926 out8(0x83C8,0x04); // DPMS Control 1100 out8(0x83C8, 0x04); // DPMS Control
927 PMCont = in8(0x83C6) & 0xFC; 1101 PMCont = in8(0x83C6) & 0xFC;
928 1102
929 DPMSCont = read3CE(GR23) & 0xFC; 1103 DPMSCont = read3CE(GR23) & 0xFC;
930 1104
931 switch (blank_mode) 1105 switch (blank_mode) {
932 { 1106 case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On
933 case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On 1107 case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On
934 case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On
935 PMCont |= 0x03; 1108 PMCont |= 0x03;
936 DPMSCont |= 0x00; 1109 DPMSCont |= 0x00;
937 break; 1110 break;
938 case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On 1111 case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On
939 PMCont |= 0x02; 1112 PMCont |= 0x02;
940 DPMSCont |= 0x01; 1113 DPMSCont |= 0x01;
941 break; 1114 break;
942 case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off 1115 case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off
943 PMCont |= 0x02; 1116 PMCont |= 0x02;
944 DPMSCont |= 0x02; 1117 DPMSCont |= 0x02;
945 break; 1118 break;
946 case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off 1119 case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off
947 PMCont |= 0x00; 1120 PMCont |= 0x00;
948 DPMSCont |= 0x03; 1121 DPMSCont |= 0x03;
949 break; 1122 break;
950 } 1123 }
951 1124
952 write3CE(GR23,DPMSCont); 1125 write3CE(GR23, DPMSCont);
953 out8(0x83C8,4); 1126 out8(0x83C8, 4);
954 out8(0x83C6,PMCont); 1127 out8(0x83C6, PMCont);
955 // 1128 //
956 // let fbcon do a softblank for us 1129 // let fbcon do a softblank for us
957 // 1130 //
@@ -959,15 +1132,18 @@ static int cyblafb_blank(int blank_mode, struct fb_info *info)
959} 1132}
960 1133
961static struct fb_ops cyblafb_ops __devinitdata = { 1134static struct fb_ops cyblafb_ops __devinitdata = {
962 .owner = THIS_MODULE, 1135 .owner = THIS_MODULE,
963 .fb_setcolreg = cyblafb_setcolreg, 1136 .fb_setcolreg = cyblafb_setcolreg,
964 .fb_pan_display = cyblafb_pan_display, 1137 .fb_pan_display = cyblafb_pan_display,
965 .fb_blank = cyblafb_blank, 1138 .fb_blank = cyblafb_blank,
966 .fb_check_var = cyblafb_check_var, 1139 .fb_check_var = cyblafb_check_var,
967 .fb_set_par = cyblafb_set_par, 1140 .fb_set_par = cyblafb_set_par,
968 .fb_fillrect = cyblafb_fillrect, 1141 .fb_fillrect = cyblafb_fillrect,
969 .fb_copyarea= cyblafb_copyarea, 1142 .fb_copyarea = cyblafb_copyarea,
970 .fb_imageblit = cyblafb_imageblit, 1143 .fb_imageblit = cyblafb_imageblit,
1144 .fb_sync = cyblafb_sync,
1145 .fb_restore_state = cyblafb_restore_state,
1146 .fb_save_state = cyblafb_save_state,
971}; 1147};
972 1148
973//========================================================================== 1149//==========================================================================
@@ -986,74 +1162,89 @@ static struct fb_ops cyblafb_ops __devinitdata = {
986 1162
987static int __devinit getstartupmode(struct fb_info *info) 1163static int __devinit getstartupmode(struct fb_info *info)
988{ 1164{
989 u32 htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend, 1165 u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend,
990 vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend, 1166 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend,
991 cr00,cr01,cr02,cr03,cr04,cr05,cr2b, 1167 cr00, cr01, cr02, cr03, cr04, cr05, cr2b,
992 cr06,cr07,cr09,cr10,cr11,cr12,cr15,cr16,cr27, 1168 cr06, cr07, cr09, cr10, cr11, cr12, cr15, cr16, cr27,
993 cr38, 1169 cr38, sr0d, sr18, sr19, gr0f, fi, pxclkdiv, vclkdiv, tmp, i;
994 sr0d,sr18,sr19,
995 gr0f,
996 fi,pxclkdiv,vclkdiv,tmp,i;
997 1170
998 struct modus { 1171 struct modus {
999 int xres; int yres; int vyres; int bpp; int pxclk; 1172 int xres; int vxres; int yres; int vyres;
1000 int left_margin; int right_margin; int upper_margin; 1173 int bpp; int pxclk;
1001 int lower_margin; int hsync_len; int vsync_len; 1174 int left_margin; int right_margin;
1002 } modedb[5] = { 1175 int upper_margin; int lower_margin;
1003 { 0, 0, 8000, 0, 0, 0, 0, 0, 0, 0, 0}, 1176 int hsync_len; int vsync_len;
1004 { 640, 480, 3756, 0, 0, -40, 24, 17, 0, 216, 3}, 1177 } modedb[5] = {
1005 { 800, 600, 3221, 0, 0, 96, 24, 14, 0, 136, 11}, 1178 {
1006 {1024, 768, 2815, 0, 0, 144, 24, 29, 0, 120, 3}, 1179 0, 2048, 0, 4096, 0, 0, 0, 0, 0, 0, 0, 0}, {
1007 {1280, 1024, 2662, 0, 0, 232, 16, 39, 0, 160, 3} 1180 640, 2048, 480, 4096, 0, 0, -40, 24, 17, 0, 216, 3}, {
1181 800, 2048, 600, 4096, 0, 0, 96, 24, 14, 0, 136, 11}, {
1182 1024, 2048, 768, 4096, 0, 0, 144, 24, 29, 0, 120, 3}, {
1183 1280, 2048, 1024, 4096, 0, 0, 232, 16, 39, 0, 160, 3}
1008 }; 1184 };
1009 1185
1010 outb(0x00,0x3d4); cr00=inb(0x3d5); outb(0x01,0x3d4); cr01=inb(0x3d5); 1186 outb(0x00, 0x3d4); cr00 = inb(0x3d5);
1011 outb(0x02,0x3d4); cr02=inb(0x3d5); outb(0x03,0x3d4); cr03=inb(0x3d5); 1187 outb(0x01, 0x3d4); cr01 = inb(0x3d5);
1012 outb(0x04,0x3d4); cr04=inb(0x3d5); outb(0x05,0x3d4); cr05=inb(0x3d5); 1188 outb(0x02, 0x3d4); cr02 = inb(0x3d5);
1013 outb(0x06,0x3d4); cr06=inb(0x3d5); outb(0x07,0x3d4); cr07=inb(0x3d5); 1189 outb(0x03, 0x3d4); cr03 = inb(0x3d5);
1014 outb(0x09,0x3d4); cr09=inb(0x3d5); outb(0x10,0x3d4); cr10=inb(0x3d5); 1190 outb(0x04, 0x3d4); cr04 = inb(0x3d5);
1015 outb(0x11,0x3d4); cr11=inb(0x3d5); outb(0x12,0x3d4); cr12=inb(0x3d5); 1191 outb(0x05, 0x3d4); cr05 = inb(0x3d5);
1016 outb(0x15,0x3d4); cr15=inb(0x3d5); outb(0x16,0x3d4); cr16=inb(0x3d5); 1192 outb(0x06, 0x3d4); cr06 = inb(0x3d5);
1017 outb(0x27,0x3d4); cr27=inb(0x3d5); outb(0x2b,0x3d4); cr2b=inb(0x3d5); 1193 outb(0x07, 0x3d4); cr07 = inb(0x3d5);
1018 outb(0x38,0x3d4); cr38=inb(0x3d5); outb(0x0b,0x3c4); inb(0x3c5); 1194 outb(0x09, 0x3d4); cr09 = inb(0x3d5);
1019 outb(0x0d,0x3c4); sr0d=inb(0x3c5); outb(0x18,0x3c4); sr18=inb(0x3c5); 1195 outb(0x10, 0x3d4); cr10 = inb(0x3d5);
1020 outb(0x19,0x3c4); sr19=inb(0x3c5); outb(0x0f,0x3ce); gr0f=inb(0x3cf); 1196 outb(0x11, 0x3d4); cr11 = inb(0x3d5);
1021 1197 outb(0x12, 0x3d4); cr12 = inb(0x3d5);
1022 htotal = cr00 | (cr2b & 0x01) << 8; 1198 outb(0x15, 0x3d4); cr15 = inb(0x3d5);
1023 hdispend = cr01 | (cr2b & 0x02) << 7; 1199 outb(0x16, 0x3d4); cr16 = inb(0x3d5);
1200 outb(0x27, 0x3d4); cr27 = inb(0x3d5);
1201 outb(0x2b, 0x3d4); cr2b = inb(0x3d5);
1202 outb(0x38, 0x3d4); cr38 = inb(0x3d5);
1203
1204 outb(0x0b, 0x3c4);
1205 inb(0x3c5);
1206
1207 outb(0x0d, 0x3c4); sr0d = inb(0x3c5);
1208 outb(0x18, 0x3c4); sr18 = inb(0x3c5);
1209 outb(0x19, 0x3c4); sr19 = inb(0x3c5);
1210 outb(0x0f, 0x3ce); gr0f = inb(0x3cf);
1211
1212 htotal = cr00 | (cr2b & 0x01) << 8;
1213 hdispend = cr01 | (cr2b & 0x02) << 7;
1024 hblankstart = cr02 | (cr2b & 0x10) << 4; 1214 hblankstart = cr02 | (cr2b & 0x10) << 4;
1025 hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2; 1215 hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2;
1026 hsyncstart = cr04 | (cr2b & 0x08) << 5; 1216 hsyncstart = cr04 | (cr2b & 0x08) << 5;
1027 hsyncend = cr05 & 0x1f; 1217 hsyncend = cr05 & 0x1f;
1028 1218
1029 modedb[0].xres = hblankstart * 8; 1219 modedb[0].xres = hblankstart * 8;
1030 modedb[0].hsync_len = hsyncend * 8; 1220 modedb[0].hsync_len = hsyncend * 8;
1031 modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres; 1221 modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres;
1032 modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres - 1222 modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres -
1033 modedb[0].right_margin - modedb[0].hsync_len; 1223 modedb[0].right_margin - modedb[0].hsync_len;
1034 1224
1035 vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4 1225 vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4
1036 | (cr27 & 0x80) << 3; 1226 | (cr27 & 0x80) << 3;
1037 vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3 1227 vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3
1038 | (cr27 & 0x10) << 6; 1228 | (cr27 & 0x10) << 6;
1039 vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2 1229 vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2
1040 | (cr27 & 0x20) << 5; 1230 | (cr27 & 0x20) << 5;
1041 vsyncend = cr11 & 0x0f; 1231 vsyncend = cr11 & 0x0f;
1042 vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4 1232 vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4
1043 | (cr27 & 0x40) << 4; 1233 | (cr27 & 0x40) << 4;
1044 vblankend = cr16; 1234 vblankend = cr16;
1045 1235
1046 modedb[0].yres = vdispend + 1; 1236 modedb[0].yres = vdispend + 1;
1047 modedb[0].vsync_len = vsyncend; 1237 modedb[0].vsync_len = vsyncend;
1048 modedb[0].lower_margin = vsyncstart - modedb[0].yres; 1238 modedb[0].lower_margin = vsyncstart - modedb[0].yres;
1049 modedb[0].upper_margin = vtotal - modedb[0].yres - 1239 modedb[0].upper_margin = vtotal - modedb[0].yres -
1050 modedb[0].lower_margin - modedb[0].vsync_len + 2; 1240 modedb[0].lower_margin - modedb[0].vsync_len + 2;
1051 1241
1052 tmp = cr38 & 0x3c; 1242 tmp = cr38 & 0x3c;
1053 modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 : 1243 modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 :
1054 tmp == 8 ? 32 : 8; 1244 tmp == 8 ? 32 : 8;
1055 1245
1056 fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12; 1246 fi = ((5864727 * (sr18 + 8)) /
1247 (((sr19 & 0x3f) + 2) * (1 << ((sr19 & 0xc0) >> 6)))) >> 12;
1057 pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1; 1248 pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1;
1058 tmp = sr0d & 0x06; 1249 tmp = sr0d & 0x06;
1059 vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 ! 1250 vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 !
@@ -1062,10 +1253,10 @@ static int __devinit getstartupmode(struct fb_info *info)
1062 if (verbosity > 0) 1253 if (verbosity > 0)
1063 output("detected startup mode: " 1254 output("detected startup mode: "
1064 "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n", 1255 "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n",
1065 modedb[0].xres,modedb[0].yres,modedb[0].xres, 1256 modedb[0].xres, modedb[0].yres, modedb[0].xres,
1066 modedb[0].bpp,modedb[0].pxclk,modedb[0].left_margin, 1257 modedb[0].bpp, modedb[0].pxclk, modedb[0].left_margin,
1067 modedb[0].right_margin,modedb[0].upper_margin, 1258 modedb[0].right_margin, modedb[0].upper_margin,
1068 modedb[0].lower_margin,modedb[0].hsync_len, 1259 modedb[0].lower_margin, modedb[0].hsync_len,
1069 modedb[0].vsync_len); 1260 modedb[0].vsync_len);
1070 1261
1071 // 1262 //
@@ -1073,36 +1264,39 @@ static int __devinit getstartupmode(struct fb_info *info)
1073 // do not want to do it in another way! 1264 // do not want to do it in another way!
1074 // 1265 //
1075 1266
1076 tryagain: 1267 tryagain:
1077 1268
1078 i = (mode == NULL) ? 0 : 1269 i = (mode == NULL) ? 0 :
1079 !strncmp(mode,"640x480",7) ? 1 : 1270 !strncmp(mode, "640x480", 7) ? 1 :
1080 !strncmp(mode,"800x600",7) ? 2 : 1271 !strncmp(mode, "800x600", 7) ? 2 :
1081 !strncmp(mode,"1024x768",8) ? 3 : 1272 !strncmp(mode, "1024x768", 8) ? 3 :
1082 !strncmp(mode,"1280x1024",9) ? 4 : 0; 1273 !strncmp(mode, "1280x1024", 9) ? 4 : 0;
1083 1274
1084 ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref; 1275 ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref;
1085 1276
1086 if(i==0) { 1277 if (i == 0) {
1087 info->var.pixclock = modedb[i].pxclk; 1278 info->var.pixclock = modedb[i].pxclk;
1088 info->var.bits_per_pixel = modedb[i].bpp; 1279 info->var.bits_per_pixel = modedb[i].bpp;
1089 } else { 1280 } else {
1090 info->var.pixclock = (100000000 / 1281 info->var.pixclock = (100000000 /
1091 ((modedb[i].left_margin + modedb[i].xres + 1282 ((modedb[i].left_margin +
1092 modedb[i].right_margin + modedb[i].hsync_len 1283 modedb[i].xres +
1093 ) * ( 1284 modedb[i].right_margin +
1094 modedb[i].upper_margin + modedb[i].yres + 1285 modedb[i].hsync_len) *
1095 modedb[i].lower_margin + modedb[i].vsync_len 1286 (modedb[i].upper_margin +
1096 ) * 1287 modedb[i].yres +
1097 ref / 10000 1288 modedb[i].lower_margin +
1098 )); 1289 modedb[i].vsync_len) * ref / 10000));
1099 info->var.bits_per_pixel = bpp; 1290 info->var.bits_per_pixel = bpp;
1100 } 1291 }
1101 1292
1102 info->var.left_margin = modedb[i].left_margin; 1293 info->var.left_margin = modedb[i].left_margin;
1103 info->var.right_margin = modedb[i].right_margin; 1294 info->var.right_margin = modedb[i].right_margin;
1104 info->var.xres = modedb[i].xres; 1295 info->var.xres = modedb[i].xres;
1105 info->var.xres_virtual = modedb[i].xres; 1296 if (!(modedb[i].yres == 1280 && modedb[i].bpp == 32))
1297 info->var.xres_virtual = modedb[i].vxres;
1298 else
1299 info->var.xres_virtual = modedb[i].xres;
1106 info->var.xoffset = 0; 1300 info->var.xoffset = 0;
1107 info->var.hsync_len = modedb[i].hsync_len; 1301 info->var.hsync_len = modedb[i].hsync_len;
1108 info->var.upper_margin = modedb[i].upper_margin; 1302 info->var.upper_margin = modedb[i].upper_margin;
@@ -1114,33 +1308,32 @@ static int __devinit getstartupmode(struct fb_info *info)
1114 info->var.sync = 0; 1308 info->var.sync = 0;
1115 info->var.vmode = FB_VMODE_NONINTERLACED; 1309 info->var.vmode = FB_VMODE_NONINTERLACED;
1116 1310
1117 if(cyblafb_check_var(&info->var,info)) { 1311 if (cyblafb_check_var(&info->var, info)) {
1118 // 640x480-8@75 should really never fail. One case would 1312 // 640x480 - 8@75 should really never fail. One case would
1119 // be fp == 1 and nativex < 640 ... give up then 1313 // be fp == 1 and nativex < 640 ... give up then
1120 if(i==1 && bpp == 8 && ref == 75){ 1314 if (i == 1 && bpp == 8 && ref == 75) {
1121 output("Can't find a valid mode :-(\n"); 1315 output("Can't find a valid mode :-(\n");
1122 return -EINVAL; 1316 return -EINVAL;
1123 } 1317 }
1124 // Our detected mode is unlikely to fail. If it does, 1318 // Our detected mode is unlikely to fail. If it does,
1125 // try 640x480-8@75 ... 1319 // try 640x480 - 8@75 ...
1126 if(i==0) { 1320 if (i == 0) {
1127 mode="640x480"; 1321 mode = "640x480";
1128 bpp=8; 1322 bpp = 8;
1129 ref=75; 1323 ref = 75;
1130 output("Detected mode failed check_var! " 1324 output("Detected mode failed check_var! "
1131 "Trying 640x480-8@75\n"); 1325 "Trying 640x480 - 8@75\n");
1132 goto tryagain; 1326 goto tryagain;
1133 } 1327 }
1134 // A specified video mode failed for some reason. 1328 // A specified video mode failed for some reason.
1135 // Try the startup mode first 1329 // Try the startup mode first
1136 output("Specified mode '%s' failed check! " 1330 output("Specified mode '%s' failed check! "
1137 "Falling back to startup mode.\n",mode); 1331 "Falling back to startup mode.\n", mode);
1138 mode=NULL; 1332 mode = NULL;
1139 goto tryagain; 1333 goto tryagain;
1140 } 1334 }
1141 1335
1142 return 0; 1336 return 0;
1143
1144} 1337}
1145 1338
1146//======================================================== 1339//========================================================
@@ -1160,21 +1353,28 @@ static unsigned int __devinit get_memsize(void)
1160 else { 1353 else {
1161 tmp = read3X4(CR1F) & 0x0F; 1354 tmp = read3X4(CR1F) & 0x0F;
1162 switch (tmp) { 1355 switch (tmp) {
1163 case 0x03: k = 1 * Mb; break; 1356 case 0x03:
1164 case 0x07: k = 2 * Mb; break; 1357 k = 1 * 1024 * 1024;
1165 case 0x0F: k = 4 * Mb; break; 1358 break;
1166 case 0x04: k = 8 * Mb; break; 1359 case 0x07:
1167 default: 1360 k = 2 * 1024 * 1024;
1168 k = 1 * Mb; 1361 break;
1169 output("Unknown memory size code %x in CR1F." 1362 case 0x0F:
1170 " We default to 1 Mb for now, please" 1363 k = 4 * 1024 * 1024;
1171 " do provide a memsize parameter!\n", 1364 break;
1172 tmp); 1365 case 0x04:
1366 k = 8 * 1024 * 1024;
1367 break;
1368 default:
1369 k = 1 * 1024 * 1024;
1370 output("Unknown memory size code %x in CR1F."
1371 " We default to 1 Mb for now, please"
1372 " do provide a memsize parameter!\n", tmp);
1173 } 1373 }
1174 } 1374 }
1175 1375
1176 if (verbosity > 0) 1376 if (verbosity > 0)
1177 output("framebuffer size = %d Kb\n",k/Kb); 1377 output("framebuffer size = %d Kb\n", k / Kb);
1178 return k; 1378 return k;
1179} 1379}
1180 1380
@@ -1192,7 +1392,7 @@ static unsigned int __devinit get_displaytype(void)
1192 return DISPLAY_FP; 1392 return DISPLAY_FP;
1193 if (crt) 1393 if (crt)
1194 return DISPLAY_CRT; 1394 return DISPLAY_CRT;
1195 return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT; 1395 return (read3CE(GR33) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
1196} 1396}
1197 1397
1198//===================================== 1398//=====================================
@@ -1203,7 +1403,7 @@ static unsigned int __devinit get_displaytype(void)
1203 1403
1204static int __devinit get_nativex(void) 1404static int __devinit get_nativex(void)
1205{ 1405{
1206 int x,y,tmp; 1406 int x, y, tmp;
1207 1407
1208 if (nativex) 1408 if (nativex)
1209 return nativex; 1409 return nativex;
@@ -1211,29 +1411,45 @@ static int __devinit get_nativex(void)
1211 tmp = (read3CE(GR52) >> 4) & 3; 1411 tmp = (read3CE(GR52) >> 4) & 3;
1212 1412
1213 switch (tmp) { 1413 switch (tmp) {
1214 case 0: x = 1280; y = 1024; break; 1414 case 0: x = 1280; y = 1024;
1215 case 2: x = 1024; y = 768; break; 1415 break;
1216 case 3: x = 800; y = 600; break; 1416 case 2: x = 1024; y = 768;
1217 case 4: x = 1400; y = 1050; break; 1417 break;
1218 case 1: 1418 case 3: x = 800; y = 600;
1219 default: x = 640; y = 480; break; 1419 break;
1420 case 4: x = 1400; y = 1050;
1421 break;
1422 case 1:
1423 default:
1424 x = 640; y = 480;
1425 break;
1220 } 1426 }
1221 1427
1222 if (verbosity > 0) 1428 if (verbosity > 0)
1223 output("%dx%d flat panel found\n",x,y); 1429 output("%dx%d flat panel found\n", x, y);
1224 return x; 1430 return x;
1225} 1431}
1226 1432
1227static int __devinit cybla_pci_probe(struct pci_dev * dev, 1433static int __devinit cybla_pci_probe(struct pci_dev *dev,
1228 const struct pci_device_id * id) 1434 const struct pci_device_id *id)
1229{ 1435{
1230 struct fb_info *info; 1436 struct fb_info *info;
1231 struct cyblafb_par *par; 1437 struct cyblafb_par *par;
1232 1438
1233 info = framebuffer_alloc(sizeof(struct cyblafb_par),&dev->dev); 1439 info = framebuffer_alloc(sizeof(struct cyblafb_par), &dev->dev);
1234
1235 if (!info) 1440 if (!info)
1236 goto errout_alloc; 1441 goto errout_alloc_info;
1442
1443 info->pixmap.addr = kzalloc(CYBLAFB_PIXMAPSIZE, GFP_KERNEL);
1444 if (!info->pixmap.addr) {
1445 output("allocation of pixmap buffer failed!\n");
1446 goto errout_alloc_pixmap;
1447 }
1448 info->pixmap.size = CYBLAFB_PIXMAPSIZE - 4;
1449 info->pixmap.buf_align = 4;
1450 info->pixmap.access_align = 32;
1451 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1452 info->pixmap.scan_align = 4;
1237 1453
1238 par = info->par; 1454 par = info->par;
1239 par->ops = cyblafb_ops; 1455 par->ops = cyblafb_ops;
@@ -1246,26 +1462,31 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
1246 output("could not enable device!\n"); 1462 output("could not enable device!\n");
1247 goto errout_enable; 1463 goto errout_enable;
1248 } 1464 }
1249
1250 // might already be requested by vga console or vesafb, 1465 // might already be requested by vga console or vesafb,
1251 // so we do care about success 1466 // so we do care about success
1252 request_region(0x3c0,32,"cyblafb"); 1467 if (!request_region(0x3c0, 0x20, "cyblafb")) {
1468 output("region 0x3c0/0x20 already reserved\n");
1469 vesafb |= 1;
1253 1470
1471 }
1254 // 1472 //
1255 // Graphics Engine Registers 1473 // Graphics Engine Registers
1256 // 1474 //
1257 request_region(GEBase,0x100,"cyblafb"); 1475 if (!request_region(GEBase, 0x100, "cyblafb")) {
1476 output("region %#x/0x100 already reserved\n", GEBase);
1477 vesafb |= 2;
1478 }
1258 1479
1259 regdump(par); 1480 regdump(par);
1260 1481
1261 enable_mmio(); 1482 enable_mmio();
1262 1483
1263 // setup MMIO region 1484 // setup MMIO region
1264 info->fix.mmio_start = pci_resource_start(dev,1); 1485 info->fix.mmio_start = pci_resource_start(dev, 1);
1265 info->fix.mmio_len = 0x20000; 1486 info->fix.mmio_len = 0x20000;
1266 1487
1267 if (!request_mem_region(info->fix.mmio_start, 1488 if (!request_mem_region(info->fix.mmio_start,
1268 info->fix.mmio_len,"cyblafb")) { 1489 info->fix.mmio_len, "cyblafb")) {
1269 output("request_mem_region failed for mmio region!\n"); 1490 output("request_mem_region failed for mmio region!\n");
1270 goto errout_mmio_reqmem; 1491 goto errout_mmio_reqmem;
1271 } 1492 }
@@ -1276,18 +1497,17 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
1276 output("ioremap failed for mmio region\n"); 1497 output("ioremap failed for mmio region\n");
1277 goto errout_mmio_remap; 1498 goto errout_mmio_remap;
1278 } 1499 }
1279
1280 // setup framebuffer memory ... might already be requested 1500 // setup framebuffer memory ... might already be requested
1281 // by vesafb. Not to fail in case of an unsuccessful request 1501 // by vesafb. Not to fail in case of an unsuccessful request
1282 // is useful for the development cycle 1502 // is useful if both are loaded.
1283 info->fix.smem_start = pci_resource_start(dev,0); 1503 info->fix.smem_start = pci_resource_start(dev, 0);
1284 info->fix.smem_len = get_memsize(); 1504 info->fix.smem_len = get_memsize();
1285 1505
1286 if (!request_mem_region(info->fix.smem_start, 1506 if (!request_mem_region(info->fix.smem_start,
1287 info->fix.smem_len,"cyblafb")) { 1507 info->fix.smem_len, "cyblafb")) {
1288 output("request_mem_region failed for smem region!\n"); 1508 output("region %#lx/%#x already reserved\n",
1289 if (!vesafb) 1509 info->fix.smem_start, info->fix.smem_len);
1290 goto errout_smem_req; 1510 vesafb |= 4;
1291 } 1511 }
1292 1512
1293 info->screen_base = ioremap_nocache(info->fix.smem_start, 1513 info->screen_base = ioremap_nocache(info->fix.smem_start,
@@ -1300,31 +1520,30 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
1300 1520
1301 displaytype = get_displaytype(); 1521 displaytype = get_displaytype();
1302 1522
1303 if(displaytype == DISPLAY_FP) 1523 if (displaytype == DISPLAY_FP)
1304 nativex = get_nativex(); 1524 nativex = get_nativex();
1305 1525
1306 // 1526 info->flags = FBINFO_DEFAULT
1307 // FBINFO_HWACCEL_YWRAP .... does not work (could be made to work?) 1527 | FBINFO_HWACCEL_COPYAREA
1308 // FBINFO_PARTIAL_PAN_OK .... is not ok 1528 | FBINFO_HWACCEL_FILLRECT
1309 // FBINFO_READS_FAST .... is necessary for optimal scrolling 1529 | FBINFO_HWACCEL_IMAGEBLIT
1310 // 1530 | FBINFO_READS_FAST
1311 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN 1531// | FBINFO_PARTIAL_PAN_OK
1312 | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT 1532 | FBINFO_MISC_ALWAYS_SETPAR;
1313 | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_READS_FAST;
1314 1533
1315 info->pseudo_palette = par->pseudo_pal; 1534 info->pseudo_palette = par->pseudo_pal;
1316 1535
1317 if(getstartupmode(info)) 1536 if (getstartupmode(info))
1318 goto errout_findmode; 1537 goto errout_findmode;
1319 1538
1320 fb_alloc_cmap(&info->cmap,256,0); 1539 fb_alloc_cmap(&info->cmap, 256, 0);
1321 1540
1322 if (register_framebuffer(info)) { 1541 if (register_framebuffer(info)) {
1323 output("Could not register CyBla framebuffer\n"); 1542 output("Could not register CyBla framebuffer\n");
1324 goto errout_register; 1543 goto errout_register;
1325 } 1544 }
1326 1545
1327 pci_set_drvdata(dev,info); 1546 pci_set_drvdata(dev, info);
1328 1547
1329 // 1548 //
1330 // normal exit and error paths 1549 // normal exit and error paths
@@ -1332,23 +1551,24 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
1332 1551
1333 return 0; 1552 return 0;
1334 1553
1335 errout_register: 1554 errout_register:
1336 errout_findmode: 1555 errout_findmode:
1337 iounmap(info->screen_base); 1556 iounmap(info->screen_base);
1338 errout_smem_remap: 1557 errout_smem_remap:
1339 release_mem_region(info->fix.smem_start, 1558 if (!(vesafb & 4))
1340 info->fix.smem_len); 1559 release_mem_region(info->fix.smem_start, info->fix.smem_len);
1341 errout_smem_req:
1342 iounmap(io_virt); 1560 iounmap(io_virt);
1343 errout_mmio_remap: 1561 errout_mmio_remap:
1344 release_mem_region(info->fix.mmio_start, 1562 release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
1345 info->fix.mmio_len); 1563 errout_mmio_reqmem:
1346 errout_mmio_reqmem: 1564 if (!(vesafb & 1))
1347// release_region(0x3c0,32); 1565 release_region(0x3c0, 32);
1348 errout_enable: 1566 errout_enable:
1567 kfree(info->pixmap.addr);
1568 errout_alloc_pixmap:
1349 framebuffer_release(info); 1569 framebuffer_release(info);
1350 errout_alloc: 1570 errout_alloc_info:
1351 output("CyblaFB version %s aborting init.\n",VERSION); 1571 output("CyblaFB version %s aborting init.\n", VERSION);
1352 return -ENODEV; 1572 return -ENODEV;
1353} 1573}
1354 1574
@@ -1359,35 +1579,41 @@ static void __devexit cybla_pci_remove(struct pci_dev *dev)
1359 unregister_framebuffer(info); 1579 unregister_framebuffer(info);
1360 iounmap(io_virt); 1580 iounmap(io_virt);
1361 iounmap(info->screen_base); 1581 iounmap(info->screen_base);
1362 release_mem_region(info->fix.smem_start,info->fix.smem_len); 1582 if (!(vesafb & 4))
1363 release_mem_region(info->fix.mmio_start,info->fix.mmio_len); 1583 release_mem_region(info->fix.smem_start, info->fix.smem_len);
1584 release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
1364 fb_dealloc_cmap(&info->cmap); 1585 fb_dealloc_cmap(&info->cmap);
1586 if (!(vesafb & 2))
1587 release_region(GEBase, 0x100);
1588 if (!(vesafb & 1))
1589 release_region(0x3c0, 32);
1590 kfree(info->pixmap.addr);
1365 framebuffer_release(info); 1591 framebuffer_release(info);
1366 output("CyblaFB version %s normal exit.\n",VERSION); 1592 output("CyblaFB version %s normal exit.\n", VERSION);
1367} 1593}
1368 1594
1369// 1595//
1370// List of boards that we are trying to support 1596// List of boards that we are trying to support
1371// 1597//
1372static struct pci_device_id cybla_devices[] = { 1598static struct pci_device_id cybla_devices[] = {
1373 {PCI_VENDOR_ID_TRIDENT,CYBERBLADEi1,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, 1599 {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1374 {0,} 1600 {0,}
1375}; 1601};
1376 1602
1377MODULE_DEVICE_TABLE(pci,cybla_devices); 1603MODULE_DEVICE_TABLE(pci, cybla_devices);
1378 1604
1379static struct pci_driver cyblafb_pci_driver = { 1605static struct pci_driver cyblafb_pci_driver = {
1380 .name = "cyblafb", 1606 .name = "cyblafb",
1381 .id_table = cybla_devices, 1607 .id_table = cybla_devices,
1382 .probe = cybla_pci_probe, 1608 .probe = cybla_pci_probe,
1383 .remove = __devexit_p(cybla_pci_remove) 1609 .remove = __devexit_p(cybla_pci_remove)
1384}; 1610};
1385 1611
1386//============================================================= 1612//=============================================================
1387// 1613//
1388// kernel command line example: 1614// kernel command line example:
1389// 1615//
1390// video=cyblafb:1280x1024,bpp=16,ref=50 ... 1616// video=cyblafb:1280x1024, bpp=16, ref=50 ...
1391// 1617//
1392// modprobe command line example: 1618// modprobe command line example:
1393// 1619//
@@ -1401,45 +1627,44 @@ static int __devinit cyblafb_init(void)
1401 char *options = NULL; 1627 char *options = NULL;
1402 char *opt; 1628 char *opt;
1403 1629
1404 if (fb_get_options("cyblafb",&options)) 1630 if (fb_get_options("cyblafb", &options))
1405 return -ENODEV; 1631 return -ENODEV;
1406 1632
1407 if (options && *options) 1633 if (options && *options)
1408 while((opt = strsep(&options,",")) != NULL ) { 1634 while ((opt = strsep(&options, ",")) != NULL) {
1409 if (!*opt) continue; 1635 if (!*opt)
1410 else if (!strncmp(opt,"bpp=",4)) 1636 continue;
1411 bpp = simple_strtoul(opt+4,NULL,0); 1637 else if (!strncmp(opt, "bpp=", 4))
1412 else if (!strncmp(opt,"ref=",4)) 1638 bpp = simple_strtoul(opt + 4, NULL, 0);
1413 ref = simple_strtoul(opt+4,NULL,0); 1639 else if (!strncmp(opt, "ref=", 4))
1414 else if (!strncmp(opt,"fp",2)) 1640 ref = simple_strtoul(opt + 4, NULL, 0);
1641 else if (!strncmp(opt, "fp", 2))
1415 displaytype = DISPLAY_FP; 1642 displaytype = DISPLAY_FP;
1416 else if (!strncmp(opt,"crt",3)) 1643 else if (!strncmp(opt, "crt", 3))
1417 displaytype = DISPLAY_CRT; 1644 displaytype = DISPLAY_CRT;
1418 else if (!strncmp(opt,"nativex=",8)) 1645 else if (!strncmp(opt, "nativex=", 8))
1419 nativex = simple_strtoul(opt+8,NULL,0); 1646 nativex = simple_strtoul(opt + 8, NULL, 0);
1420 else if (!strncmp(opt,"center",6)) 1647 else if (!strncmp(opt, "center", 6))
1421 center = 1; 1648 center = 1;
1422 else if (!strncmp(opt,"stretch",7)) 1649 else if (!strncmp(opt, "stretch", 7))
1423 stretch = 1; 1650 stretch = 1;
1424 else if (!strncmp(opt,"pciwb=",6)) 1651 else if (!strncmp(opt, "pciwb=", 6))
1425 pciwb = simple_strtoul(opt+6,NULL,0); 1652 pciwb = simple_strtoul(opt + 6, NULL, 0);
1426 else if (!strncmp(opt,"pcirb=",6)) 1653 else if (!strncmp(opt, "pcirb=", 6))
1427 pcirb = simple_strtoul(opt+6,NULL,0); 1654 pcirb = simple_strtoul(opt + 6, NULL, 0);
1428 else if (!strncmp(opt,"pciwr=",6)) 1655 else if (!strncmp(opt, "pciwr=", 6))
1429 pciwr = simple_strtoul(opt+6,NULL,0); 1656 pciwr = simple_strtoul(opt + 6, NULL, 0);
1430 else if (!strncmp(opt,"pcirr=",6)) 1657 else if (!strncmp(opt, "pcirr=", 6))
1431 pcirr = simple_strtoul(opt+6,NULL,0); 1658 pcirr = simple_strtoul(opt + 6, NULL, 0);
1432 else if (!strncmp(opt,"memsize=",8)) 1659 else if (!strncmp(opt, "memsize=", 8))
1433 memsize = simple_strtoul(opt+8,NULL,0); 1660 memsize = simple_strtoul(opt + 8, NULL, 0);
1434 else if (!strncmp(opt,"verbosity=",10)) 1661 else if (!strncmp(opt, "verbosity=", 10))
1435 verbosity = simple_strtoul(opt+10,NULL,0); 1662 verbosity = simple_strtoul(opt + 10, NULL, 0);
1436 else if (!strncmp(opt,"vesafb",6))
1437 vesafb = 1;
1438 else 1663 else
1439 mode = opt; 1664 mode = opt;
1440 } 1665 }
1441#endif 1666#endif
1442 output("CyblaFB version %s initializing\n",VERSION); 1667 output("CyblaFB version %s initializing\n", VERSION);
1443 return pci_module_init(&cyblafb_pci_driver); 1668 return pci_module_init(&cyblafb_pci_driver);
1444} 1669}
1445 1670