diff options
author | Knut Petersen <Knut_Petersen@t-online.de> | 2006-01-09 09:04:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-09 13:00:36 -0500 |
commit | 44637a12f80b80157d9c1bc5b7d6ef09c9e05713 (patch) | |
tree | 17384805725f7b429685ba4cad0d9488d93f9f25 /drivers | |
parent | 8b78e83bfbc12f7e9bdefd400abdfde9e6c9ac51 (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/Kconfig | 2 | ||||
-rw-r--r-- | drivers/video/cyblafb.c | 1523 |
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 | ||
1152 | config FB_CYBLA | 1152 | config 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 | ||
27 | struct cyblafb_par { | 28 | struct cyblafb_par { |
28 | u32 pseudo_pal[16]; | 29 | u32 pseudo_pal[16]; |
@@ -32,7 +33,9 @@ struct cyblafb_par { | |||
32 | static struct fb_fix_screeninfo cyblafb_fix __devinitdata = { | 33 | static 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; | |||
43 | static int fp __devinitdata; | 46 | static int fp __devinitdata; |
44 | static int crt __devinitdata; | 47 | static int crt __devinitdata; |
45 | static int memsize __devinitdata; | 48 | static int memsize __devinitdata; |
46 | static int vesafb __devinitdata; | ||
47 | 49 | ||
50 | static int basestride; | ||
51 | static int vesafb; | ||
48 | static int nativex; | 52 | static int nativex; |
49 | static int center; | 53 | static int center; |
50 | static int stretch; | 54 | static int stretch; |
@@ -52,26 +56,50 @@ static int pciwb = 1; | |||
52 | static int pcirb = 1; | 56 | static int pcirb = 1; |
53 | static int pciwr = 1; | 57 | static int pciwr = 1; |
54 | static int pcirr = 1; | 58 | static int pcirr = 1; |
59 | static int disabled; | ||
55 | static int verbosity; | 60 | static int verbosity; |
56 | static int displaytype; | 61 | static int displaytype; |
57 | 62 | ||
58 | static void __iomem * io_virt; // iospace virtual memory address | 63 | static void __iomem *io_virt; // iospace virtual memory address |
59 | 64 | ||
60 | module_param(mode,charp,0); | 65 | module_param(mode, charp, 0); |
61 | module_param(bpp,int,0); | 66 | module_param(bpp, int, 0); |
62 | module_param(ref,int,0); | 67 | module_param(ref, int, 0); |
63 | module_param(fp,int,0); | 68 | module_param(fp, int, 0); |
64 | module_param(crt,int,0); | 69 | module_param(crt, int, 0); |
65 | module_param(nativex,int,0); | 70 | module_param(nativex, int, 0); |
66 | module_param(center,int,0); | 71 | module_param(center, int, 0); |
67 | module_param(stretch,int,0); | 72 | module_param(stretch, int, 0); |
68 | module_param(pciwb,int,0); | 73 | module_param(pciwb, int, 0); |
69 | module_param(pcirb,int,0); | 74 | module_param(pcirb, int, 0); |
70 | module_param(pciwr,int,0); | 75 | module_param(pciwr, int, 0); |
71 | module_param(pcirr,int,0); | 76 | module_param(pcirr, int, 0); |
72 | module_param(memsize,int,0); | 77 | module_param(memsize, int, 0); |
73 | module_param(verbosity,int,0); | 78 | module_param(verbosity, int, 0); |
74 | module_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 | ||
93 | static inline unsigned char read3X4(int reg) | 121 | static 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 | ||
99 | static inline unsigned char read3C4(int reg) | 127 | static 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 | ||
105 | static inline unsigned char read3CE(int reg) | 133 | static 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 | ||
111 | static inline void write3X4(int reg,unsigned char val) | 139 | static 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 | ||
117 | static inline void write3C4(int reg,unsigned char val) | 145 | static 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 | ||
123 | static inline void write3CE(int reg,unsigned char val) | 151 | static 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 | ||
129 | static inline void write3C0(int reg,unsigned char val) | 157 | static 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 | ||
142 | static inline void enable_mmio(void) | 170 | static 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 | ||
171 | static void set_vclk(struct cyblafb_par *par, int freq) | 202 | static 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 | ||
202 | static void cyblafb_setup_GE(int pitch,int bpp) | 234 | static 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 | ||
241 | static int cyblafb_sync(struct fb_info *info) | 278 | static 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 | ||
294 | static void cyblafb_fillrect(struct fb_info * info, | 326 | static 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 | ||
329 | static void cyblafb_copyarea(struct fb_info *info, | 376 | static 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 | ||
363 | static void cyblafb_imageblit(struct fb_info *info, | 417 | static 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 | ||
548 | static int cyblafb_pan_display(struct fb_var_screeninfo *var, | 666 | static 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 | ||
756 | static 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 | |||
777 | static 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) | |||
640 | static int cyblafb_set_par(struct fb_info *info) | 792 | static 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 | ||
919 | static int cyblafb_blank(int blank_mode, struct fb_info *info) | 1091 | static 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 | ||
961 | static struct fb_ops cyblafb_ops __devinitdata = { | 1134 | static 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 | ||
987 | static int __devinit getstartupmode(struct fb_info *info) | 1163 | static 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 | ||
1204 | static int __devinit get_nativex(void) | 1404 | static 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 | ||
1227 | static int __devinit cybla_pci_probe(struct pci_dev * dev, | 1433 | static 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 | // |
1372 | static struct pci_device_id cybla_devices[] = { | 1598 | static 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 | ||
1377 | MODULE_DEVICE_TABLE(pci,cybla_devices); | 1603 | MODULE_DEVICE_TABLE(pci, cybla_devices); |
1378 | 1604 | ||
1379 | static struct pci_driver cyblafb_pci_driver = { | 1605 | static 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 | ||