diff options
Diffstat (limited to 'drivers/video/tdfxfb.c')
-rw-r--r-- | drivers/video/tdfxfb.c | 737 |
1 files changed, 376 insertions, 361 deletions
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 689ce0270b81..e6aced9df52d 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * Created : Thu Sep 23 18:17:43 1999, hmallat | 10 | * Created : Thu Sep 23 18:17:43 1999, hmallat |
11 | * Last modified: Tue Nov 2 21:19:47 1999, hmallat | 11 | * Last modified: Tue Nov 2 21:19:47 1999, hmallat |
12 | * | 12 | * |
13 | * Lots of the information here comes from the Daryll Strauss' Banshee | 13 | * Lots of the information here comes from the Daryll Strauss' Banshee |
14 | * patches to the XF86 server, and the rest comes from the 3dfx | 14 | * patches to the XF86 server, and the rest comes from the 3dfx |
15 | * Banshee specification. I'm very much indebted to Daryll for his | 15 | * Banshee specification. I'm very much indebted to Daryll for his |
16 | * work on the X server. | 16 | * work on the X server. |
@@ -23,7 +23,7 @@ | |||
23 | * behave very differently from the Voodoo3/4/5. For anyone wanting to | 23 | * behave very differently from the Voodoo3/4/5. For anyone wanting to |
24 | * use frame buffer on the Voodoo1/2, see the sstfb driver (which is | 24 | * use frame buffer on the Voodoo1/2, see the sstfb driver (which is |
25 | * located at http://www.sourceforge.net/projects/sstfb). | 25 | * located at http://www.sourceforge.net/projects/sstfb). |
26 | * | 26 | * |
27 | * While I _am_ grateful to 3Dfx for releasing the specs for Banshee, | 27 | * While I _am_ grateful to 3Dfx for releasing the specs for Banshee, |
28 | * I do wish the next version is a bit more complete. Without the XF86 | 28 | * I do wish the next version is a bit more complete. Without the XF86 |
29 | * patches I couldn't have gotten even this far... for instance, the | 29 | * patches I couldn't have gotten even this far... for instance, the |
@@ -33,7 +33,7 @@ | |||
33 | * | 33 | * |
34 | * The structure of this driver comes pretty much from the Permedia | 34 | * The structure of this driver comes pretty much from the Permedia |
35 | * driver by Ilario Nardinocchi, which in turn is based on skeletonfb. | 35 | * driver by Ilario Nardinocchi, which in turn is based on skeletonfb. |
36 | * | 36 | * |
37 | * TODO: | 37 | * TODO: |
38 | * - support for 16/32 bpp needs fixing (funky bootup penguin) | 38 | * - support for 16/32 bpp needs fixing (funky bootup penguin) |
39 | * - multihead support (basically need to support an array of fb_infos) | 39 | * - multihead support (basically need to support an array of fb_infos) |
@@ -76,12 +76,12 @@ | |||
76 | 76 | ||
77 | #include <video/tdfx.h> | 77 | #include <video/tdfx.h> |
78 | 78 | ||
79 | #undef TDFXFB_DEBUG | 79 | #undef TDFXFB_DEBUG |
80 | #ifdef TDFXFB_DEBUG | 80 | #ifdef TDFXFB_DEBUG |
81 | #define DPRINTK(a,b...) printk(KERN_DEBUG "fb: %s: " a, __FUNCTION__ , ## b) | 81 | #define DPRINTK(a,b...) printk(KERN_DEBUG "fb: %s: " a, __FUNCTION__ , ## b) |
82 | #else | 82 | #else |
83 | #define DPRINTK(a,b...) | 83 | #define DPRINTK(a,b...) |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | #define BANSHEE_MAX_PIXCLOCK 270000 | 86 | #define BANSHEE_MAX_PIXCLOCK 270000 |
87 | #define VOODOO3_MAX_PIXCLOCK 300000 | 87 | #define VOODOO3_MAX_PIXCLOCK 300000 |
@@ -90,9 +90,9 @@ | |||
90 | static struct fb_fix_screeninfo tdfx_fix __devinitdata = { | 90 | static struct fb_fix_screeninfo tdfx_fix __devinitdata = { |
91 | .id = "3Dfx", | 91 | .id = "3Dfx", |
92 | .type = FB_TYPE_PACKED_PIXELS, | 92 | .type = FB_TYPE_PACKED_PIXELS, |
93 | .visual = FB_VISUAL_PSEUDOCOLOR, | 93 | .visual = FB_VISUAL_PSEUDOCOLOR, |
94 | .ypanstep = 1, | 94 | .ypanstep = 1, |
95 | .ywrapstep = 1, | 95 | .ywrapstep = 1, |
96 | .accel = FB_ACCEL_3DFX_BANSHEE | 96 | .accel = FB_ACCEL_3DFX_BANSHEE |
97 | }; | 97 | }; |
98 | 98 | ||
@@ -102,7 +102,7 @@ static struct fb_var_screeninfo tdfx_var __devinitdata = { | |||
102 | .yres = 480, | 102 | .yres = 480, |
103 | .xres_virtual = 640, | 103 | .xres_virtual = 640, |
104 | .yres_virtual = 1024, | 104 | .yres_virtual = 1024, |
105 | .bits_per_pixel =8, | 105 | .bits_per_pixel = 8, |
106 | .red = {0, 8, 0}, | 106 | .red = {0, 8, 0}, |
107 | .blue = {0, 8, 0}, | 107 | .blue = {0, 8, 0}, |
108 | .green = {0, 8, 0}, | 108 | .green = {0, 8, 0}, |
@@ -142,103 +142,79 @@ static struct pci_device_id tdfxfb_id_table[] = { | |||
142 | 142 | ||
143 | static struct pci_driver tdfxfb_driver = { | 143 | static struct pci_driver tdfxfb_driver = { |
144 | .name = "tdfxfb", | 144 | .name = "tdfxfb", |
145 | .id_table = tdfxfb_id_table, | 145 | .id_table = tdfxfb_id_table, |
146 | .probe = tdfxfb_probe, | 146 | .probe = tdfxfb_probe, |
147 | .remove = __devexit_p(tdfxfb_remove), | 147 | .remove = __devexit_p(tdfxfb_remove), |
148 | }; | 148 | }; |
149 | 149 | ||
150 | MODULE_DEVICE_TABLE(pci, tdfxfb_id_table); | 150 | MODULE_DEVICE_TABLE(pci, tdfxfb_id_table); |
151 | 151 | ||
152 | /* | 152 | /* |
153 | * Frame buffer device API | 153 | * Driver data |
154 | */ | ||
155 | static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb); | ||
156 | static int tdfxfb_set_par(struct fb_info *info); | ||
157 | static int tdfxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
158 | u_int transp, struct fb_info *info); | ||
159 | static int tdfxfb_blank(int blank, struct fb_info *info); | ||
160 | static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); | ||
161 | static int banshee_wait_idle(struct fb_info *info); | ||
162 | #ifdef CONFIG_FB_3DFX_ACCEL | ||
163 | static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); | ||
164 | static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); | ||
165 | static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image); | ||
166 | #endif /* CONFIG_FB_3DFX_ACCEL */ | ||
167 | |||
168 | static struct fb_ops tdfxfb_ops = { | ||
169 | .owner = THIS_MODULE, | ||
170 | .fb_check_var = tdfxfb_check_var, | ||
171 | .fb_set_par = tdfxfb_set_par, | ||
172 | .fb_setcolreg = tdfxfb_setcolreg, | ||
173 | .fb_blank = tdfxfb_blank, | ||
174 | .fb_pan_display = tdfxfb_pan_display, | ||
175 | .fb_sync = banshee_wait_idle, | ||
176 | #ifdef CONFIG_FB_3DFX_ACCEL | ||
177 | .fb_fillrect = tdfxfb_fillrect, | ||
178 | .fb_copyarea = tdfxfb_copyarea, | ||
179 | .fb_imageblit = tdfxfb_imageblit, | ||
180 | #else | ||
181 | .fb_fillrect = cfb_fillrect, | ||
182 | .fb_copyarea = cfb_copyarea, | ||
183 | .fb_imageblit = cfb_imageblit, | ||
184 | #endif | ||
185 | }; | ||
186 | |||
187 | /* | ||
188 | * do_xxx: Hardware-specific functions | ||
189 | */ | ||
190 | static u32 do_calc_pll(int freq, int *freq_out); | ||
191 | static void do_write_regs(struct fb_info *info, struct banshee_reg *reg); | ||
192 | static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short); | ||
193 | |||
194 | /* | ||
195 | * Driver data | ||
196 | */ | 154 | */ |
197 | static int nopan = 0; | 155 | static int nopan = 0; |
198 | static int nowrap = 1; // not implemented (yet) | 156 | static int nowrap = 1; // not implemented (yet) |
199 | static char *mode_option __devinitdata = NULL; | 157 | static char *mode_option __devinitdata = NULL; |
200 | 158 | ||
201 | /* ------------------------------------------------------------------------- | 159 | /* ------------------------------------------------------------------------- |
202 | * Hardware-specific funcions | 160 | * Hardware-specific funcions |
203 | * ------------------------------------------------------------------------- */ | 161 | * ------------------------------------------------------------------------- */ |
204 | 162 | ||
205 | #ifdef VGA_REG_IO | 163 | #ifdef VGA_REG_IO |
206 | static inline u8 vga_inb(struct tdfx_par *par, u32 reg) { return inb(reg); } | 164 | static inline u8 vga_inb(struct tdfx_par *par, u32 reg) |
165 | { | ||
166 | return inb(reg); | ||
167 | } | ||
207 | 168 | ||
208 | static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val) { outb(val, reg); } | 169 | static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val) |
170 | { | ||
171 | outb(val, reg); | ||
172 | } | ||
209 | #else | 173 | #else |
210 | static inline u8 vga_inb(struct tdfx_par *par, u32 reg) { | 174 | static inline u8 vga_inb(struct tdfx_par *par, u32 reg) |
211 | return inb(par->iobase + reg - 0x300); | 175 | { |
176 | return inb(par->iobase + reg - 0x300); | ||
212 | } | 177 | } |
213 | static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val) { | 178 | static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val) |
214 | outb(val, par->iobase + reg - 0x300); | 179 | { |
180 | outb(val, par->iobase + reg - 0x300); | ||
215 | } | 181 | } |
216 | #endif | 182 | #endif |
217 | 183 | ||
218 | static inline void gra_outb(struct tdfx_par *par, u32 idx, u8 val) { | 184 | static inline void gra_outb(struct tdfx_par *par, u32 idx, u8 val) |
219 | vga_outb(par, GRA_I, idx); vga_outb(par, GRA_D, val); | 185 | { |
186 | vga_outb(par, GRA_I, idx); | ||
187 | vga_outb(par, GRA_D, val); | ||
220 | } | 188 | } |
221 | 189 | ||
222 | static inline void seq_outb(struct tdfx_par *par, u32 idx, u8 val) { | 190 | static inline void seq_outb(struct tdfx_par *par, u32 idx, u8 val) |
223 | vga_outb(par, SEQ_I, idx); vga_outb(par, SEQ_D, val); | 191 | { |
192 | vga_outb(par, SEQ_I, idx); | ||
193 | vga_outb(par, SEQ_D, val); | ||
224 | } | 194 | } |
225 | 195 | ||
226 | static inline u8 seq_inb(struct tdfx_par *par, u32 idx) { | 196 | static inline u8 seq_inb(struct tdfx_par *par, u32 idx) |
227 | vga_outb(par, SEQ_I, idx); return vga_inb(par, SEQ_D); | 197 | { |
198 | vga_outb(par, SEQ_I, idx); | ||
199 | return vga_inb(par, SEQ_D); | ||
228 | } | 200 | } |
229 | 201 | ||
230 | static inline void crt_outb(struct tdfx_par *par, u32 idx, u8 val) { | 202 | static inline void crt_outb(struct tdfx_par *par, u32 idx, u8 val) |
231 | vga_outb(par, CRT_I, idx); vga_outb(par, CRT_D, val); | 203 | { |
204 | vga_outb(par, CRT_I, idx); | ||
205 | vga_outb(par, CRT_D, val); | ||
232 | } | 206 | } |
233 | 207 | ||
234 | static inline u8 crt_inb(struct tdfx_par *par, u32 idx) { | 208 | static inline u8 crt_inb(struct tdfx_par *par, u32 idx) |
235 | vga_outb(par, CRT_I, idx); return vga_inb(par, CRT_D); | 209 | { |
210 | vga_outb(par, CRT_I, idx); | ||
211 | return vga_inb(par, CRT_D); | ||
236 | } | 212 | } |
237 | 213 | ||
238 | static inline void att_outb(struct tdfx_par *par, u32 idx, u8 val) | 214 | static inline void att_outb(struct tdfx_par *par, u32 idx, u8 val) |
239 | { | 215 | { |
240 | unsigned char tmp; | 216 | unsigned char tmp; |
241 | 217 | ||
242 | tmp = vga_inb(par, IS1_R); | 218 | tmp = vga_inb(par, IS1_R); |
243 | vga_outb(par, ATT_IW, idx); | 219 | vga_outb(par, ATT_IW, idx); |
244 | vga_outb(par, ATT_IW, val); | 220 | vga_outb(par, ATT_IW, val); |
@@ -270,7 +246,7 @@ static inline void vga_enable_palette(struct tdfx_par *par) | |||
270 | vga_outb(par, ATT_IW, 0x20); | 246 | vga_outb(par, ATT_IW, 0x20); |
271 | } | 247 | } |
272 | 248 | ||
273 | static inline u32 tdfx_inl(struct tdfx_par *par, unsigned int reg) | 249 | static inline u32 tdfx_inl(struct tdfx_par *par, unsigned int reg) |
274 | { | 250 | { |
275 | return readl(par->regbase_virt + reg); | 251 | return readl(par->regbase_virt + reg); |
276 | } | 252 | } |
@@ -284,7 +260,7 @@ static inline void banshee_make_room(struct tdfx_par *par, int size) | |||
284 | { | 260 | { |
285 | /* Note: The Voodoo3's onboard FIFO has 32 slots. This loop | 261 | /* Note: The Voodoo3's onboard FIFO has 32 slots. This loop |
286 | * won't quit if you ask for more. */ | 262 | * won't quit if you ask for more. */ |
287 | while((tdfx_inl(par, STATUS) & 0x1f) < size-1); | 263 | while ((tdfx_inl(par, STATUS) & 0x1f) < size - 1) ; |
288 | } | 264 | } |
289 | 265 | ||
290 | static int banshee_wait_idle(struct fb_info *info) | 266 | static int banshee_wait_idle(struct fb_info *info) |
@@ -295,15 +271,16 @@ static int banshee_wait_idle(struct fb_info *info) | |||
295 | banshee_make_room(par, 1); | 271 | banshee_make_room(par, 1); |
296 | tdfx_outl(par, COMMAND_3D, COMMAND_3D_NOP); | 272 | tdfx_outl(par, COMMAND_3D, COMMAND_3D_NOP); |
297 | 273 | ||
298 | while(1) { | 274 | while (1) { |
299 | i = (tdfx_inl(par, STATUS) & STATUS_BUSY) ? 0 : i + 1; | 275 | i = (tdfx_inl(par, STATUS) & STATUS_BUSY) ? 0 : i + 1; |
300 | if(i == 3) break; | 276 | if (i == 3) |
277 | break; | ||
301 | } | 278 | } |
302 | return 0; | 279 | return 0; |
303 | } | 280 | } |
304 | 281 | ||
305 | /* | 282 | /* |
306 | * Set the color of a palette entry in 8bpp mode | 283 | * Set the color of a palette entry in 8bpp mode |
307 | */ | 284 | */ |
308 | static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c) | 285 | static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c) |
309 | { | 286 | { |
@@ -312,11 +289,11 @@ static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c) | |||
312 | tdfx_outl(par, DACDATA, c); | 289 | tdfx_outl(par, DACDATA, c); |
313 | } | 290 | } |
314 | 291 | ||
315 | static u32 do_calc_pll(int freq, int* freq_out) | 292 | static u32 do_calc_pll(int freq, int *freq_out) |
316 | { | 293 | { |
317 | int m, n, k, best_m, best_n, best_k, best_error; | 294 | int m, n, k, best_m, best_n, best_k, best_error; |
318 | int fref = 14318; | 295 | int fref = 14318; |
319 | 296 | ||
320 | best_error = freq; | 297 | best_error = freq; |
321 | best_n = best_m = best_k = 0; | 298 | best_n = best_m = best_k = 0; |
322 | 299 | ||
@@ -336,17 +313,17 @@ static u32 do_calc_pll(int freq, int* freq_out) | |||
336 | * estimated n | 313 | * estimated n |
337 | */ | 314 | */ |
338 | int f = fref * (n + 2) / (m + 2) / (1 << k); | 315 | int f = fref * (n + 2) / (m + 2) / (1 << k); |
339 | int error = abs (f - freq); | 316 | int error = abs(f - freq); |
340 | 317 | ||
341 | /* | 318 | /* |
342 | * If this is the closest we've come to the | 319 | * If this is the closest we've come to the |
343 | * target frequency then remember n, m and k | 320 | * target frequency then remember n, m and k |
344 | */ | 321 | */ |
345 | if (error < best_error) { | 322 | if (error < best_error) { |
346 | best_error = error; | 323 | best_error = error; |
347 | best_n = n; | 324 | best_n = n; |
348 | best_m = m; | 325 | best_m = m; |
349 | best_k = k; | 326 | best_k = k; |
350 | } | 327 | } |
351 | } | 328 | } |
352 | } | 329 | } |
@@ -355,12 +332,12 @@ static u32 do_calc_pll(int freq, int* freq_out) | |||
355 | n = best_n; | 332 | n = best_n; |
356 | m = best_m; | 333 | m = best_m; |
357 | k = best_k; | 334 | k = best_k; |
358 | *freq_out = fref*(n + 2)/(m + 2)/(1 << k); | 335 | *freq_out = fref * (n + 2) / (m + 2) / (1 << k); |
359 | 336 | ||
360 | return (n << 8) | (m << 2) | k; | 337 | return (n << 8) | (m << 2) | k; |
361 | } | 338 | } |
362 | 339 | ||
363 | static void do_write_regs(struct fb_info *info, struct banshee_reg* reg) | 340 | static void do_write_regs(struct fb_info *info, struct banshee_reg *reg) |
364 | { | 341 | { |
365 | struct tdfx_par *par = info->par; | 342 | struct tdfx_par *par = info->par; |
366 | int i; | 343 | int i; |
@@ -372,13 +349,13 @@ static void do_write_regs(struct fb_info *info, struct banshee_reg* reg) | |||
372 | crt_outb(par, 0x11, crt_inb(par, 0x11) & 0x7f); /* CRT unprotect */ | 349 | crt_outb(par, 0x11, crt_inb(par, 0x11) & 0x7f); /* CRT unprotect */ |
373 | 350 | ||
374 | banshee_make_room(par, 3); | 351 | banshee_make_room(par, 3); |
375 | tdfx_outl(par, VGAINIT1, reg->vgainit1 & 0x001FFFFF); | 352 | tdfx_outl(par, VGAINIT1, reg->vgainit1 & 0x001FFFFF); |
376 | tdfx_outl(par, VIDPROCCFG, reg->vidcfg & ~0x00000001); | 353 | tdfx_outl(par, VIDPROCCFG, reg->vidcfg & ~0x00000001); |
377 | #if 0 | 354 | #if 0 |
378 | tdfx_outl(par, PLLCTRL1, reg->mempll); | 355 | tdfx_outl(par, PLLCTRL1, reg->mempll); |
379 | tdfx_outl(par, PLLCTRL2, reg->gfxpll); | 356 | tdfx_outl(par, PLLCTRL2, reg->gfxpll); |
380 | #endif | 357 | #endif |
381 | tdfx_outl(par, PLLCTRL0, reg->vidpll); | 358 | tdfx_outl(par, PLLCTRL0, reg->vidpll); |
382 | 359 | ||
383 | vga_outb(par, MISC_W, reg->misc[0x00] | 0x01); | 360 | vga_outb(par, MISC_W, reg->misc[0x00] | 0x01); |
384 | 361 | ||
@@ -401,31 +378,31 @@ static void do_write_regs(struct fb_info *info, struct banshee_reg* reg) | |||
401 | vga_enable_video(par); | 378 | vga_enable_video(par); |
402 | 379 | ||
403 | banshee_make_room(par, 11); | 380 | banshee_make_room(par, 11); |
404 | tdfx_outl(par, VGAINIT0, reg->vgainit0); | 381 | tdfx_outl(par, VGAINIT0, reg->vgainit0); |
405 | tdfx_outl(par, DACMODE, reg->dacmode); | 382 | tdfx_outl(par, DACMODE, reg->dacmode); |
406 | tdfx_outl(par, VIDDESKSTRIDE, reg->stride); | 383 | tdfx_outl(par, VIDDESKSTRIDE, reg->stride); |
407 | tdfx_outl(par, HWCURPATADDR, 0); | 384 | tdfx_outl(par, HWCURPATADDR, 0); |
408 | 385 | ||
409 | tdfx_outl(par, VIDSCREENSIZE,reg->screensize); | 386 | tdfx_outl(par, VIDSCREENSIZE, reg->screensize); |
410 | tdfx_outl(par, VIDDESKSTART, reg->startaddr); | 387 | tdfx_outl(par, VIDDESKSTART, reg->startaddr); |
411 | tdfx_outl(par, VIDPROCCFG, reg->vidcfg); | 388 | tdfx_outl(par, VIDPROCCFG, reg->vidcfg); |
412 | tdfx_outl(par, VGAINIT1, reg->vgainit1); | 389 | tdfx_outl(par, VGAINIT1, reg->vgainit1); |
413 | tdfx_outl(par, MISCINIT0, reg->miscinit0); | 390 | tdfx_outl(par, MISCINIT0, reg->miscinit0); |
414 | 391 | ||
415 | banshee_make_room(par, 8); | 392 | banshee_make_room(par, 8); |
416 | tdfx_outl(par, SRCBASE, reg->srcbase); | 393 | tdfx_outl(par, SRCBASE, reg->srcbase); |
417 | tdfx_outl(par, DSTBASE, reg->dstbase); | 394 | tdfx_outl(par, DSTBASE, reg->dstbase); |
418 | tdfx_outl(par, COMMANDEXTRA_2D, 0); | 395 | tdfx_outl(par, COMMANDEXTRA_2D, 0); |
419 | tdfx_outl(par, CLIP0MIN, 0); | 396 | tdfx_outl(par, CLIP0MIN, 0); |
420 | tdfx_outl(par, CLIP0MAX, 0x0fff0fff); | 397 | tdfx_outl(par, CLIP0MAX, 0x0fff0fff); |
421 | tdfx_outl(par, CLIP1MIN, 0); | 398 | tdfx_outl(par, CLIP1MIN, 0); |
422 | tdfx_outl(par, CLIP1MAX, 0x0fff0fff); | 399 | tdfx_outl(par, CLIP1MAX, 0x0fff0fff); |
423 | tdfx_outl(par, SRCXY, 0); | 400 | tdfx_outl(par, SRCXY, 0); |
424 | 401 | ||
425 | banshee_wait_idle(info); | 402 | banshee_wait_idle(info); |
426 | } | 403 | } |
427 | 404 | ||
428 | static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) | 405 | static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) |
429 | { | 406 | { |
430 | u32 draminit0; | 407 | u32 draminit0; |
431 | u32 draminit1; | 408 | u32 draminit1; |
@@ -436,16 +413,17 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) | |||
436 | u32 lfbsize; | 413 | u32 lfbsize; |
437 | int has_sgram; | 414 | int has_sgram; |
438 | 415 | ||
439 | draminit0 = tdfx_inl(par, DRAMINIT0); | 416 | draminit0 = tdfx_inl(par, DRAMINIT0); |
440 | draminit1 = tdfx_inl(par, DRAMINIT1); | 417 | draminit1 = tdfx_inl(par, DRAMINIT1); |
441 | 418 | ||
442 | num_chips = (draminit0 & DRAMINIT0_SGRAM_NUM) ? 8 : 4; | 419 | num_chips = (draminit0 & DRAMINIT0_SGRAM_NUM) ? 8 : 4; |
443 | 420 | ||
444 | if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) { | 421 | if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) { |
445 | /* Banshee/Voodoo3 */ | 422 | /* Banshee/Voodoo3 */ |
446 | has_sgram = draminit1 & DRAMINIT1_MEM_SDRAM; | 423 | has_sgram = draminit1 & DRAMINIT1_MEM_SDRAM; |
447 | chip_size = has_sgram ? ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 2 : 1) | 424 | chip_size = 2; |
448 | : 2; | 425 | if (has_sgram) |
426 | chip_size = (draminit0 & DRAMINIT0_SGRAM_TYPE) ? 2 : 1; | ||
449 | } else { | 427 | } else { |
450 | /* Voodoo4/5 */ | 428 | /* Voodoo4/5 */ |
451 | has_sgram = 0; | 429 | has_sgram = 0; |
@@ -458,14 +436,14 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) | |||
458 | miscinit1 |= has_sgram ? 0 : MISCINIT1_2DBLOCK_DIS; | 436 | miscinit1 |= has_sgram ? 0 : MISCINIT1_2DBLOCK_DIS; |
459 | miscinit1 |= MISCINIT1_CLUT_INV; | 437 | miscinit1 |= MISCINIT1_CLUT_INV; |
460 | 438 | ||
461 | banshee_make_room(par, 1); | 439 | banshee_make_room(par, 1); |
462 | tdfx_outl(par, MISCINIT1, miscinit1); | 440 | tdfx_outl(par, MISCINIT1, miscinit1); |
463 | return lfbsize; | 441 | return lfbsize; |
464 | } | 442 | } |
465 | 443 | ||
466 | /* ------------------------------------------------------------------------- */ | 444 | /* ------------------------------------------------------------------------- */ |
467 | 445 | ||
468 | static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info) | 446 | static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
469 | { | 447 | { |
470 | struct tdfx_par *par = info->par; | 448 | struct tdfx_par *par = info->par; |
471 | u32 lpitch; | 449 | u32 lpitch; |
@@ -490,67 +468,66 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info) | |||
490 | /* Banshee doesn't support interlace, but Voodoo4/5 and probably Voodoo3 do. */ | 468 | /* Banshee doesn't support interlace, but Voodoo4/5 and probably Voodoo3 do. */ |
491 | /* no direct information about device id now? use max_pixclock for this... */ | 469 | /* no direct information about device id now? use max_pixclock for this... */ |
492 | if (((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) && | 470 | if (((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) && |
493 | (par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) { | 471 | (par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) { |
494 | DPRINTK("interlace not supported\n"); | 472 | DPRINTK("interlace not supported\n"); |
495 | return -EINVAL; | 473 | return -EINVAL; |
496 | } | 474 | } |
497 | 475 | ||
498 | var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */ | 476 | var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */ |
499 | lpitch = var->xres * ((var->bits_per_pixel + 7)>>3); | 477 | lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3); |
500 | 478 | ||
501 | if (var->xres < 320 || var->xres > 2048) { | 479 | if (var->xres < 320 || var->xres > 2048) { |
502 | DPRINTK("width not supported: %u\n", var->xres); | 480 | DPRINTK("width not supported: %u\n", var->xres); |
503 | return -EINVAL; | 481 | return -EINVAL; |
504 | } | 482 | } |
505 | 483 | ||
506 | if (var->yres < 200 || var->yres > 2048) { | 484 | if (var->yres < 200 || var->yres > 2048) { |
507 | DPRINTK("height not supported: %u\n", var->yres); | 485 | DPRINTK("height not supported: %u\n", var->yres); |
508 | return -EINVAL; | 486 | return -EINVAL; |
509 | } | 487 | } |
510 | 488 | ||
511 | if (lpitch * var->yres_virtual > info->fix.smem_len) { | 489 | if (lpitch * var->yres_virtual > info->fix.smem_len) { |
512 | var->yres_virtual = info->fix.smem_len/lpitch; | 490 | var->yres_virtual = info->fix.smem_len / lpitch; |
513 | if (var->yres_virtual < var->yres) { | 491 | if (var->yres_virtual < var->yres) { |
514 | DPRINTK("no memory for screen (%ux%ux%u)\n", | 492 | DPRINTK("no memory for screen (%ux%ux%u)\n", |
515 | var->xres, var->yres_virtual, var->bits_per_pixel); | 493 | var->xres, var->yres_virtual, |
494 | var->bits_per_pixel); | ||
516 | return -EINVAL; | 495 | return -EINVAL; |
517 | } | 496 | } |
518 | } | 497 | } |
519 | 498 | ||
520 | if (PICOS2KHZ(var->pixclock) > par->max_pixclock) { | 499 | if (PICOS2KHZ(var->pixclock) > par->max_pixclock) { |
521 | DPRINTK("pixclock too high (%ldKHz)\n",PICOS2KHZ(var->pixclock)); | 500 | DPRINTK("pixclock too high (%ldKHz)\n", |
501 | PICOS2KHZ(var->pixclock)); | ||
522 | return -EINVAL; | 502 | return -EINVAL; |
523 | } | 503 | } |
524 | 504 | ||
525 | switch(var->bits_per_pixel) { | 505 | switch (var->bits_per_pixel) { |
526 | case 8: | 506 | case 8: |
527 | var->red.length = var->green.length = var->blue.length = 8; | 507 | var->red.length = var->green.length = var->blue.length = 8; |
528 | break; | 508 | break; |
529 | case 16: | 509 | case 16: |
530 | var->red.offset = 11; | 510 | var->red.offset = 11; |
531 | var->red.length = 5; | 511 | var->red.length = 5; |
532 | var->green.offset = 5; | 512 | var->green.offset = 5; |
533 | var->green.length = 6; | 513 | var->green.length = 6; |
534 | var->blue.offset = 0; | 514 | var->blue.offset = 0; |
535 | var->blue.length = 5; | 515 | var->blue.length = 5; |
536 | break; | 516 | break; |
537 | case 24: | 517 | case 32: |
538 | var->red.offset=16; | 518 | case 24: |
539 | var->green.offset=8; | 519 | var->red.offset=16; |
540 | var->blue.offset=0; | 520 | var->green.offset=8; |
541 | var->red.length = var->green.length = var->blue.length = 8; | 521 | var->blue.offset=0; |
542 | case 32: | 522 | var->red.length = var->green.length = var->blue.length = 8; |
543 | var->red.offset = 16; | 523 | break; |
544 | var->green.offset = 8; | ||
545 | var->blue.offset = 0; | ||
546 | var->red.length = var->green.length = var->blue.length = 8; | ||
547 | break; | ||
548 | } | 524 | } |
549 | var->height = var->width = -1; | 525 | var->height = var->width = -1; |
550 | 526 | ||
551 | var->accel_flags = FB_ACCELF_TEXT; | 527 | var->accel_flags = FB_ACCELF_TEXT; |
552 | 528 | ||
553 | DPRINTK("Checking graphics mode at %dx%d depth %d\n", var->xres, var->yres, var->bits_per_pixel); | 529 | DPRINTK("Checking graphics mode at %dx%d depth %d\n", |
530 | var->xres, var->yres, var->bits_per_pixel); | ||
554 | return 0; | 531 | return 0; |
555 | } | 532 | } |
556 | 533 | ||
@@ -563,26 +540,29 @@ static int tdfxfb_set_par(struct fb_info *info) | |||
563 | struct banshee_reg reg; | 540 | struct banshee_reg reg; |
564 | int fout, freq; | 541 | int fout, freq; |
565 | u32 wd, cpp; | 542 | u32 wd, cpp; |
566 | 543 | ||
567 | par->baseline = 0; | 544 | par->baseline = 0; |
568 | 545 | ||
569 | memset(®, 0, sizeof(reg)); | 546 | memset(®, 0, sizeof(reg)); |
570 | cpp = (info->var.bits_per_pixel + 7)/8; | 547 | cpp = (info->var.bits_per_pixel + 7) / 8; |
571 | 548 | ||
572 | reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE | VIDCFG_CURS_X11 | ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) | (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0); | 549 | reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE | |
550 | VIDCFG_CURS_X11 | | ||
551 | ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) | | ||
552 | (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0); | ||
573 | 553 | ||
574 | /* PLL settings */ | 554 | /* PLL settings */ |
575 | freq = PICOS2KHZ(info->var.pixclock); | 555 | freq = PICOS2KHZ(info->var.pixclock); |
576 | 556 | ||
577 | reg.dacmode = 0; | 557 | reg.dacmode = 0; |
578 | reg.vidcfg &= ~VIDCFG_2X; | 558 | reg.vidcfg &= ~VIDCFG_2X; |
579 | 559 | ||
580 | hdispend = info->var.xres; | 560 | hdispend = info->var.xres; |
581 | hsyncsta = hdispend + info->var.right_margin; | 561 | hsyncsta = hdispend + info->var.right_margin; |
582 | hsyncend = hsyncsta + info->var.hsync_len; | 562 | hsyncend = hsyncsta + info->var.hsync_len; |
583 | htotal = hsyncend + info->var.left_margin; | 563 | htotal = hsyncend + info->var.left_margin; |
584 | 564 | ||
585 | if (freq > par->max_pixclock/2) { | 565 | if (freq > par->max_pixclock / 2) { |
586 | freq = freq > par->max_pixclock ? par->max_pixclock : freq; | 566 | freq = freq > par->max_pixclock ? par->max_pixclock : freq; |
587 | reg.dacmode |= DACMODE_2X; | 567 | reg.dacmode |= DACMODE_2X; |
588 | reg.vidcfg |= VIDCFG_2X; | 568 | reg.vidcfg |= VIDCFG_2X; |
@@ -591,7 +571,7 @@ static int tdfxfb_set_par(struct fb_info *info) | |||
591 | hsyncend >>= 1; | 571 | hsyncend >>= 1; |
592 | htotal >>= 1; | 572 | htotal >>= 1; |
593 | } | 573 | } |
594 | 574 | ||
595 | hd = wd = (hdispend >> 3) - 1; | 575 | hd = wd = (hdispend >> 3) - 1; |
596 | hs = (hsyncsta >> 3) - 1; | 576 | hs = (hsyncsta >> 3) - 1; |
597 | he = (hsyncend >> 3) - 1; | 577 | he = (hsyncend >> 3) - 1; |
@@ -610,13 +590,13 @@ static int tdfxfb_set_par(struct fb_info *info) | |||
610 | ve = vs + info->var.vsync_len; | 590 | ve = vs + info->var.vsync_len; |
611 | vbe = vt = ve + info->var.upper_margin - 1; | 591 | vbe = vt = ve + info->var.upper_margin - 1; |
612 | } | 592 | } |
613 | 593 | ||
614 | /* this is all pretty standard VGA register stuffing */ | 594 | /* this is all pretty standard VGA register stuffing */ |
615 | reg.misc[0x00] = 0x0f | | 595 | reg.misc[0x00] = 0x0f | |
616 | (info->var.xres < 400 ? 0xa0 : | 596 | (info->var.xres < 400 ? 0xa0 : |
617 | info->var.xres < 480 ? 0x60 : | 597 | info->var.xres < 480 ? 0x60 : |
618 | info->var.xres < 768 ? 0xe0 : 0x20); | 598 | info->var.xres < 768 ? 0xe0 : 0x20); |
619 | 599 | ||
620 | reg.gra[0x00] = 0x00; | 600 | reg.gra[0x00] = 0x00; |
621 | reg.gra[0x01] = 0x00; | 601 | reg.gra[0x01] = 0x00; |
622 | reg.gra[0x02] = 0x00; | 602 | reg.gra[0x02] = 0x00; |
@@ -660,17 +640,17 @@ static int tdfxfb_set_par(struct fb_info *info) | |||
660 | reg.crt[0x02] = hbs; | 640 | reg.crt[0x02] = hbs; |
661 | reg.crt[0x03] = 0x80 | (hbe & 0x1f); | 641 | reg.crt[0x03] = 0x80 | (hbe & 0x1f); |
662 | reg.crt[0x04] = hs; | 642 | reg.crt[0x04] = hs; |
663 | reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f); | 643 | reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f); |
664 | reg.crt[0x06] = vt; | 644 | reg.crt[0x06] = vt; |
665 | reg.crt[0x07] = ((vs & 0x200) >> 2) | | 645 | reg.crt[0x07] = ((vs & 0x200) >> 2) | |
666 | ((vd & 0x200) >> 3) | | 646 | ((vd & 0x200) >> 3) | |
667 | ((vt & 0x200) >> 4) | 0x10 | | 647 | ((vt & 0x200) >> 4) | 0x10 | |
668 | ((vbs & 0x100) >> 5) | | 648 | ((vbs & 0x100) >> 5) | |
669 | ((vs & 0x100) >> 6) | | 649 | ((vs & 0x100) >> 6) | |
670 | ((vd & 0x100) >> 7) | | 650 | ((vd & 0x100) >> 7) | |
671 | ((vt & 0x100) >> 8); | 651 | ((vt & 0x100) >> 8); |
672 | reg.crt[0x08] = 0x00; | 652 | reg.crt[0x08] = 0x00; |
673 | reg.crt[0x09] = 0x40 | ((vbs & 0x200) >> 4); | 653 | reg.crt[0x09] = 0x40 | ((vbs & 0x200) >> 4); |
674 | reg.crt[0x0a] = 0x00; | 654 | reg.crt[0x0a] = 0x00; |
675 | reg.crt[0x0b] = 0x00; | 655 | reg.crt[0x0b] = 0x00; |
676 | reg.crt[0x0c] = 0x00; | 656 | reg.crt[0x0c] = 0x00; |
@@ -678,28 +658,28 @@ static int tdfxfb_set_par(struct fb_info *info) | |||
678 | reg.crt[0x0e] = 0x00; | 658 | reg.crt[0x0e] = 0x00; |
679 | reg.crt[0x0f] = 0x00; | 659 | reg.crt[0x0f] = 0x00; |
680 | reg.crt[0x10] = vs; | 660 | reg.crt[0x10] = vs; |
681 | reg.crt[0x11] = (ve & 0x0f) | 0x20; | 661 | reg.crt[0x11] = (ve & 0x0f) | 0x20; |
682 | reg.crt[0x12] = vd; | 662 | reg.crt[0x12] = vd; |
683 | reg.crt[0x13] = wd; | 663 | reg.crt[0x13] = wd; |
684 | reg.crt[0x14] = 0x00; | 664 | reg.crt[0x14] = 0x00; |
685 | reg.crt[0x15] = vbs; | 665 | reg.crt[0x15] = vbs; |
686 | reg.crt[0x16] = vbe + 1; | 666 | reg.crt[0x16] = vbe + 1; |
687 | reg.crt[0x17] = 0xc3; | 667 | reg.crt[0x17] = 0xc3; |
688 | reg.crt[0x18] = 0xff; | 668 | reg.crt[0x18] = 0xff; |
689 | 669 | ||
690 | /* Banshee's nonvga stuff */ | 670 | /* Banshee's nonvga stuff */ |
691 | reg.ext[0x00] = (((ht & 0x100) >> 8) | | 671 | reg.ext[0x00] = (((ht & 0x100) >> 8) | |
692 | ((hd & 0x100) >> 6) | | 672 | ((hd & 0x100) >> 6) | |
693 | ((hbs & 0x100) >> 4) | | 673 | ((hbs & 0x100) >> 4) | |
694 | ((hbe & 0x40) >> 1) | | 674 | ((hbe & 0x40) >> 1) | |
695 | ((hs & 0x100) >> 2) | | 675 | ((hs & 0x100) >> 2) | |
696 | ((he & 0x20) << 2)); | 676 | ((he & 0x20) << 2)); |
697 | reg.ext[0x01] = (((vt & 0x400) >> 10) | | 677 | reg.ext[0x01] = (((vt & 0x400) >> 10) | |
698 | ((vd & 0x400) >> 8) | | 678 | ((vd & 0x400) >> 8) | |
699 | ((vbs & 0x400) >> 6) | | 679 | ((vbs & 0x400) >> 6) | |
700 | ((vbe & 0x400) >> 4)); | 680 | ((vbe & 0x400) >> 4)); |
701 | 681 | ||
702 | reg.vgainit0 = VGAINIT0_8BIT_DAC | | 682 | reg.vgainit0 = VGAINIT0_8BIT_DAC | |
703 | VGAINIT0_EXT_ENABLE | | 683 | VGAINIT0_EXT_ENABLE | |
704 | VGAINIT0_WAKEUP_3C3 | | 684 | VGAINIT0_WAKEUP_3C3 | |
705 | VGAINIT0_ALT_READBACK | | 685 | VGAINIT0_ALT_READBACK | |
@@ -707,10 +687,10 @@ static int tdfxfb_set_par(struct fb_info *info) | |||
707 | reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff; | 687 | reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff; |
708 | 688 | ||
709 | reg.cursloc = 0; | 689 | reg.cursloc = 0; |
710 | 690 | ||
711 | reg.cursc0 = 0; | 691 | reg.cursc0 = 0; |
712 | reg.cursc1 = 0xffffff; | 692 | reg.cursc1 = 0xffffff; |
713 | 693 | ||
714 | reg.stride = info->var.xres * cpp; | 694 | reg.stride = info->var.xres * cpp; |
715 | reg.startaddr = par->baseline * reg.stride; | 695 | reg.startaddr = par->baseline * reg.stride; |
716 | reg.srcbase = reg.startaddr; | 696 | reg.srcbase = reg.startaddr; |
@@ -721,7 +701,7 @@ static int tdfxfb_set_par(struct fb_info *info) | |||
721 | 701 | ||
722 | reg.dacmode &= ~DACMODE_2X; | 702 | reg.dacmode &= ~DACMODE_2X; |
723 | reg.vidcfg &= ~VIDCFG_2X; | 703 | reg.vidcfg &= ~VIDCFG_2X; |
724 | if (freq > par->max_pixclock/2) { | 704 | if (freq > par->max_pixclock / 2) { |
725 | freq = freq > par->max_pixclock ? par->max_pixclock : freq; | 705 | freq = freq > par->max_pixclock ? par->max_pixclock : freq; |
726 | reg.dacmode |= DACMODE_2X; | 706 | reg.dacmode |= DACMODE_2X; |
727 | reg.vidcfg |= VIDCFG_2X; | 707 | reg.vidcfg |= VIDCFG_2X; |
@@ -746,43 +726,47 @@ static int tdfxfb_set_par(struct fb_info *info) | |||
746 | 726 | ||
747 | #if defined(__BIG_ENDIAN) | 727 | #if defined(__BIG_ENDIAN) |
748 | switch (info->var.bits_per_pixel) { | 728 | switch (info->var.bits_per_pixel) { |
749 | case 8: | 729 | case 8: |
750 | case 24: | 730 | case 24: |
751 | reg.miscinit0 &= ~(1 << 30); | 731 | reg.miscinit0 &= ~(1 << 30); |
752 | reg.miscinit0 &= ~(1 << 31); | 732 | reg.miscinit0 &= ~(1 << 31); |
753 | break; | 733 | break; |
754 | case 16: | 734 | case 16: |
755 | reg.miscinit0 |= (1 << 30); | 735 | reg.miscinit0 |= (1 << 30); |
756 | reg.miscinit0 |= (1 << 31); | 736 | reg.miscinit0 |= (1 << 31); |
757 | break; | 737 | break; |
758 | case 32: | 738 | case 32: |
759 | reg.miscinit0 |= (1 << 30); | 739 | reg.miscinit0 |= (1 << 30); |
760 | reg.miscinit0 &= ~(1 << 31); | 740 | reg.miscinit0 &= ~(1 << 31); |
761 | break; | 741 | break; |
762 | } | 742 | } |
763 | #endif | 743 | #endif |
764 | do_write_regs(info, ®); | 744 | do_write_regs(info, ®); |
765 | 745 | ||
766 | /* Now change fb_fix_screeninfo according to changes in par */ | 746 | /* Now change fb_fix_screeninfo according to changes in par */ |
767 | info->fix.line_length = info->var.xres * ((info->var.bits_per_pixel + 7)>>3); | 747 | info->fix.line_length = |
768 | info->fix.visual = (info->var.bits_per_pixel == 8) | 748 | info->var.xres * ((info->var.bits_per_pixel + 7) >> 3); |
749 | info->fix.visual = (info->var.bits_per_pixel == 8) | ||
769 | ? FB_VISUAL_PSEUDOCOLOR | 750 | ? FB_VISUAL_PSEUDOCOLOR |
770 | : FB_VISUAL_TRUECOLOR; | 751 | : FB_VISUAL_TRUECOLOR; |
771 | DPRINTK("Graphics mode is now set at %dx%d depth %d\n", info->var.xres, info->var.yres, info->var.bits_per_pixel); | 752 | DPRINTK("Graphics mode is now set at %dx%d depth %d\n", |
772 | return 0; | 753 | info->var.xres, info->var.yres, info->var.bits_per_pixel); |
754 | return 0; | ||
773 | } | 755 | } |
774 | 756 | ||
775 | /* A handy macro shamelessly pinched from matroxfb */ | 757 | /* A handy macro shamelessly pinched from matroxfb */ |
776 | #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) | 758 | #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16) |
777 | 759 | ||
778 | static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, | 760 | static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, |
779 | unsigned blue,unsigned transp,struct fb_info *info) | 761 | unsigned blue, unsigned transp, |
762 | struct fb_info *info) | ||
780 | { | 763 | { |
781 | struct tdfx_par *par = info->par; | 764 | struct tdfx_par *par = info->par; |
782 | u32 rgbcol; | 765 | u32 rgbcol; |
783 | 766 | ||
784 | if (regno >= info->cmap.len || regno > 255) return 1; | 767 | if (regno >= info->cmap.len || regno > 255) |
785 | 768 | return 1; | |
769 | |||
786 | switch (info->fix.visual) { | 770 | switch (info->fix.visual) { |
787 | case FB_VISUAL_PSEUDOCOLOR: | 771 | case FB_VISUAL_PSEUDOCOLOR: |
788 | rgbcol =(((u32)red & 0xff00) << 8) | | 772 | rgbcol =(((u32)red & 0xff00) << 8) | |
@@ -793,13 +777,13 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
793 | /* Truecolor has no hardware color palettes. */ | 777 | /* Truecolor has no hardware color palettes. */ |
794 | case FB_VISUAL_TRUECOLOR: | 778 | case FB_VISUAL_TRUECOLOR: |
795 | if (regno < 16) { | 779 | if (regno < 16) { |
796 | rgbcol = (CNVT_TOHW( red, info->var.red.length) << | 780 | rgbcol = (CNVT_TOHW(red, info->var.red.length) << |
797 | info->var.red.offset) | | 781 | info->var.red.offset) | |
798 | (CNVT_TOHW( green, info->var.green.length) << | 782 | (CNVT_TOHW(green, info->var.green.length) << |
799 | info->var.green.offset) | | 783 | info->var.green.offset) | |
800 | (CNVT_TOHW( blue, info->var.blue.length) << | 784 | (CNVT_TOHW(blue, info->var.blue.length) << |
801 | info->var.blue.offset) | | 785 | info->var.blue.offset) | |
802 | (CNVT_TOHW( transp, info->var.transp.length) << | 786 | (CNVT_TOHW(transp, info->var.transp.length) << |
803 | info->var.transp.offset); | 787 | info->var.transp.offset); |
804 | par->palette[regno] = rgbcol; | 788 | par->palette[regno] = rgbcol; |
805 | } | 789 | } |
@@ -815,54 +799,54 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
815 | 799 | ||
816 | /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ | 800 | /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ |
817 | static int tdfxfb_blank(int blank, struct fb_info *info) | 801 | static int tdfxfb_blank(int blank, struct fb_info *info) |
818 | { | 802 | { |
819 | struct tdfx_par *par = info->par; | 803 | struct tdfx_par *par = info->par; |
820 | u32 dacmode, state = 0, vgablank = 0; | 804 | u32 dacmode, state = 0, vgablank = 0; |
821 | 805 | ||
822 | dacmode = tdfx_inl(par, DACMODE); | 806 | dacmode = tdfx_inl(par, DACMODE); |
823 | 807 | ||
824 | switch (blank) { | 808 | switch (blank) { |
825 | case FB_BLANK_UNBLANK: /* Screen: On; HSync: On, VSync: On */ | 809 | case FB_BLANK_UNBLANK: /* Screen: On; HSync: On, VSync: On */ |
826 | state = 0; | 810 | state = 0; |
827 | vgablank = 0; | 811 | vgablank = 0; |
828 | break; | 812 | break; |
829 | case FB_BLANK_NORMAL: /* Screen: Off; HSync: On, VSync: On */ | 813 | case FB_BLANK_NORMAL: /* Screen: Off; HSync: On, VSync: On */ |
830 | state = 0; | 814 | state = 0; |
831 | vgablank = 1; | 815 | vgablank = 1; |
832 | break; | 816 | break; |
833 | case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off; HSync: On, VSync: Off */ | 817 | case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off; HSync: On, VSync: Off */ |
834 | state = BIT(3); | 818 | state = BIT(3); |
835 | vgablank = 1; | 819 | vgablank = 1; |
836 | break; | 820 | break; |
837 | case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off; HSync: Off, VSync: On */ | 821 | case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off; HSync: Off, VSync: On */ |
838 | state = BIT(1); | 822 | state = BIT(1); |
839 | vgablank = 1; | 823 | vgablank = 1; |
840 | break; | 824 | break; |
841 | case FB_BLANK_POWERDOWN: /* Screen: Off; HSync: Off, VSync: Off */ | 825 | case FB_BLANK_POWERDOWN: /* Screen: Off; HSync: Off, VSync: Off */ |
842 | state = BIT(1) | BIT(3); | 826 | state = BIT(1) | BIT(3); |
843 | vgablank = 1; | 827 | vgablank = 1; |
844 | break; | 828 | break; |
845 | } | 829 | } |
846 | 830 | ||
847 | dacmode &= ~(BIT(1) | BIT(3)); | 831 | dacmode &= ~(BIT(1) | BIT(3)); |
848 | dacmode |= state; | 832 | dacmode |= state; |
849 | banshee_make_room(par, 1); | 833 | banshee_make_room(par, 1); |
850 | tdfx_outl(par, DACMODE, dacmode); | 834 | tdfx_outl(par, DACMODE, dacmode); |
851 | if (vgablank) | 835 | if (vgablank) |
852 | vga_disable_video(par); | 836 | vga_disable_video(par); |
853 | else | 837 | else |
854 | vga_enable_video(par); | 838 | vga_enable_video(par); |
855 | return 0; | 839 | return 0; |
856 | } | 840 | } |
857 | 841 | ||
858 | /* | 842 | /* |
859 | * Set the starting position of the visible screen to var->yoffset | 843 | * Set the starting position of the visible screen to var->yoffset |
860 | */ | 844 | */ |
861 | static int tdfxfb_pan_display(struct fb_var_screeninfo *var, | 845 | static int tdfxfb_pan_display(struct fb_var_screeninfo *var, |
862 | struct fb_info *info) | 846 | struct fb_info *info) |
863 | { | 847 | { |
864 | struct tdfx_par *par = info->par; | 848 | struct tdfx_par *par = info->par; |
865 | u32 addr; | 849 | u32 addr; |
866 | 850 | ||
867 | if (nopan || var->xoffset || (var->yoffset > var->yres_virtual)) | 851 | if (nopan || var->xoffset || (var->yoffset > var->yres_virtual)) |
868 | return -EINVAL; | 852 | return -EINVAL; |
@@ -872,84 +856,86 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var, | |||
872 | addr = var->yoffset * info->fix.line_length; | 856 | addr = var->yoffset * info->fix.line_length; |
873 | banshee_make_room(par, 1); | 857 | banshee_make_room(par, 1); |
874 | tdfx_outl(par, VIDDESKSTART, addr); | 858 | tdfx_outl(par, VIDDESKSTART, addr); |
875 | 859 | ||
876 | info->var.xoffset = var->xoffset; | 860 | info->var.xoffset = var->xoffset; |
877 | info->var.yoffset = var->yoffset; | 861 | info->var.yoffset = var->yoffset; |
878 | return 0; | 862 | return 0; |
879 | } | 863 | } |
880 | 864 | ||
881 | #ifdef CONFIG_FB_3DFX_ACCEL | 865 | #ifdef CONFIG_FB_3DFX_ACCEL |
882 | /* | 866 | /* |
883 | * FillRect 2D command (solidfill or invert (via ROP_XOR)) | 867 | * FillRect 2D command (solidfill or invert (via ROP_XOR)) |
884 | */ | 868 | */ |
885 | static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | 869 | static void tdfxfb_fillrect(struct fb_info *info, |
870 | const struct fb_fillrect *rect) | ||
886 | { | 871 | { |
887 | struct tdfx_par *par = info->par; | 872 | struct tdfx_par *par = info->par; |
888 | u32 bpp = info->var.bits_per_pixel; | 873 | u32 bpp = info->var.bits_per_pixel; |
889 | u32 stride = info->fix.line_length; | 874 | u32 stride = info->fix.line_length; |
890 | u32 fmt= stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); | 875 | u32 fmt= stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13); |
891 | int tdfx_rop; | 876 | int tdfx_rop; |
892 | 877 | ||
893 | if (rect->rop == ROP_COPY) | 878 | if (rect->rop == ROP_COPY) |
894 | tdfx_rop = TDFX_ROP_COPY; | 879 | tdfx_rop = TDFX_ROP_COPY; |
895 | else | 880 | else |
896 | tdfx_rop = TDFX_ROP_XOR; | 881 | tdfx_rop = TDFX_ROP_XOR; |
897 | 882 | ||
898 | banshee_make_room(par, 5); | 883 | banshee_make_room(par, 5); |
899 | tdfx_outl(par, DSTFORMAT, fmt); | 884 | tdfx_outl(par, DSTFORMAT, fmt); |
900 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { | 885 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { |
901 | tdfx_outl(par, COLORFORE, rect->color); | 886 | tdfx_outl(par, COLORFORE, rect->color); |
902 | } else { /* FB_VISUAL_TRUECOLOR */ | 887 | } else { /* FB_VISUAL_TRUECOLOR */ |
903 | tdfx_outl(par, COLORFORE, par->palette[rect->color]); | 888 | tdfx_outl(par, COLORFORE, par->palette[rect->color]); |
904 | } | 889 | } |
905 | tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24)); | 890 | tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24)); |
906 | tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16)); | 891 | tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16)); |
907 | tdfx_outl(par, LAUNCH_2D, rect->dx | (rect->dy << 16)); | 892 | tdfx_outl(par, LAUNCH_2D, rect->dx | (rect->dy << 16)); |
908 | } | 893 | } |
909 | 894 | ||
910 | /* | 895 | /* |
911 | * Screen-to-Screen BitBlt 2D command (for the bmove fb op.) | 896 | * Screen-to-Screen BitBlt 2D command (for the bmove fb op.) |
912 | */ | 897 | */ |
913 | static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | 898 | static void tdfxfb_copyarea(struct fb_info *info, |
899 | const struct fb_copyarea *area) | ||
914 | { | 900 | { |
915 | struct tdfx_par *par = info->par; | 901 | struct tdfx_par *par = info->par; |
916 | u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy; | 902 | u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy; |
917 | u32 bpp = info->var.bits_per_pixel; | 903 | u32 bpp = info->var.bits_per_pixel; |
918 | u32 stride = info->fix.line_length; | 904 | u32 stride = info->fix.line_length; |
919 | u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24); | 905 | u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24); |
920 | u32 fmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); | 906 | u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13); |
921 | 907 | ||
922 | if (area->sx <= area->dx) { | 908 | if (area->sx <= area->dx) { |
923 | //-X | 909 | //-X |
924 | blitcmd |= BIT(14); | 910 | blitcmd |= BIT(14); |
925 | sx += area->width - 1; | 911 | sx += area->width - 1; |
926 | dx += area->width - 1; | 912 | dx += area->width - 1; |
927 | } | 913 | } |
928 | if (area->sy <= area->dy) { | 914 | if (area->sy <= area->dy) { |
929 | //-Y | 915 | //-Y |
930 | blitcmd |= BIT(15); | 916 | blitcmd |= BIT(15); |
931 | sy += area->height - 1; | 917 | sy += area->height - 1; |
932 | dy += area->height - 1; | 918 | dy += area->height - 1; |
933 | } | 919 | } |
934 | 920 | ||
935 | banshee_make_room(par, 6); | 921 | banshee_make_room(par, 6); |
936 | 922 | ||
937 | tdfx_outl(par, SRCFORMAT, fmt); | 923 | tdfx_outl(par, SRCFORMAT, fmt); |
938 | tdfx_outl(par, DSTFORMAT, fmt); | 924 | tdfx_outl(par, DSTFORMAT, fmt); |
939 | tdfx_outl(par, COMMAND_2D, blitcmd); | 925 | tdfx_outl(par, COMMAND_2D, blitcmd); |
940 | tdfx_outl(par, DSTSIZE, area->width | (area->height << 16)); | 926 | tdfx_outl(par, DSTSIZE, area->width | (area->height << 16)); |
941 | tdfx_outl(par, DSTXY, dx | (dy << 16)); | 927 | tdfx_outl(par, DSTXY, dx | (dy << 16)); |
942 | tdfx_outl(par, LAUNCH_2D, sx | (sy << 16)); | 928 | tdfx_outl(par, LAUNCH_2D, sx | (sy << 16)); |
943 | } | 929 | } |
944 | 930 | ||
945 | static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) | 931 | static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) |
946 | { | 932 | { |
947 | struct tdfx_par *par = info->par; | 933 | struct tdfx_par *par = info->par; |
948 | int size = image->height * ((image->width * image->depth + 7)>>3); | 934 | int size = image->height * ((image->width * image->depth + 7) >> 3); |
949 | int fifo_free; | 935 | int fifo_free; |
950 | int i, stride = info->fix.line_length; | 936 | int i, stride = info->fix.line_length; |
951 | u32 bpp = info->var.bits_per_pixel; | 937 | u32 bpp = info->var.bits_per_pixel; |
952 | u32 dstfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); | 938 | u32 dstfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13); |
953 | u8 *chardata = (u8 *) image->data; | 939 | u8 *chardata = (u8 *) image->data; |
954 | u32 srcfmt; | 940 | u32 srcfmt; |
955 | 941 | ||
@@ -961,53 +947,61 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
961 | } else { | 947 | } else { |
962 | banshee_make_room(par, 8); | 948 | banshee_make_room(par, 8); |
963 | switch (info->fix.visual) { | 949 | switch (info->fix.visual) { |
964 | case FB_VISUAL_PSEUDOCOLOR: | 950 | case FB_VISUAL_PSEUDOCOLOR: |
965 | tdfx_outl(par, COLORFORE, image->fg_color); | 951 | tdfx_outl(par, COLORFORE, image->fg_color); |
966 | tdfx_outl(par, COLORBACK, image->bg_color); | 952 | tdfx_outl(par, COLORBACK, image->bg_color); |
967 | break; | 953 | break; |
968 | case FB_VISUAL_TRUECOLOR: | 954 | case FB_VISUAL_TRUECOLOR: |
969 | default: | 955 | default: |
970 | tdfx_outl(par, COLORFORE, | 956 | tdfx_outl(par, COLORFORE, |
971 | par->palette[image->fg_color]); | 957 | par->palette[image->fg_color]); |
972 | tdfx_outl(par, COLORBACK, | 958 | tdfx_outl(par, COLORBACK, |
973 | par->palette[image->bg_color]); | 959 | par->palette[image->bg_color]); |
974 | } | 960 | } |
975 | #ifdef __BIG_ENDIAN | 961 | #ifdef __BIG_ENDIAN |
976 | srcfmt = 0x400000 | BIT(20); | 962 | srcfmt = 0x400000 | BIT(20); |
977 | #else | 963 | #else |
978 | srcfmt = 0x400000; | 964 | srcfmt = 0x400000; |
979 | #endif | 965 | #endif |
980 | } | 966 | } |
981 | 967 | ||
982 | tdfx_outl(par, SRCXY, 0); | 968 | tdfx_outl(par, SRCXY, 0); |
983 | tdfx_outl(par, DSTXY, image->dx | (image->dy << 16)); | 969 | tdfx_outl(par, DSTXY, image->dx | (image->dy << 16)); |
984 | tdfx_outl(par, COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24)); | 970 | tdfx_outl(par, COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24)); |
985 | tdfx_outl(par, SRCFORMAT, srcfmt); | 971 | tdfx_outl(par, SRCFORMAT, srcfmt); |
986 | tdfx_outl(par, DSTFORMAT, dstfmt); | 972 | tdfx_outl(par, DSTFORMAT, dstfmt); |
987 | tdfx_outl(par, DSTSIZE, image->width | (image->height << 16)); | 973 | tdfx_outl(par, DSTSIZE, image->width | (image->height << 16)); |
988 | 974 | ||
989 | /* A count of how many free FIFO entries we've requested. | 975 | /* A count of how many free FIFO entries we've requested. |
990 | * When this goes negative, we need to request more. */ | 976 | * When this goes negative, we need to request more. */ |
991 | fifo_free = 0; | 977 | fifo_free = 0; |
992 | 978 | ||
993 | /* Send four bytes at a time of data */ | 979 | /* Send four bytes at a time of data */ |
994 | for (i = (size >> 2) ; i > 0; i--) { | 980 | for (i = (size >> 2); i > 0; i--) { |
995 | if(--fifo_free < 0) { | 981 | if (--fifo_free < 0) { |
996 | fifo_free=31; | 982 | fifo_free = 31; |
997 | banshee_make_room(par,fifo_free); | 983 | banshee_make_room(par, fifo_free); |
998 | } | 984 | } |
999 | tdfx_outl(par, LAUNCH_2D,*(u32*)chardata); | 985 | tdfx_outl(par, LAUNCH_2D, *(u32*)chardata); |
1000 | chardata += 4; | 986 | chardata += 4; |
1001 | } | 987 | } |
1002 | 988 | ||
1003 | /* Send the leftovers now */ | 989 | /* Send the leftovers now */ |
1004 | banshee_make_room(par,3); | 990 | banshee_make_room(par, 3); |
1005 | i = size%4; | 991 | i = size % 4; |
1006 | switch (i) { | 992 | switch (i) { |
1007 | case 0: break; | 993 | case 0: |
1008 | case 1: tdfx_outl(par, LAUNCH_2D,*chardata); break; | 994 | break; |
1009 | case 2: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata); break; | 995 | case 1: |
1010 | case 3: tdfx_outl(par, LAUNCH_2D,*(u16*)chardata | ((chardata[3]) << 24)); break; | 996 | tdfx_outl(par, LAUNCH_2D, *chardata); |
997 | break; | ||
998 | case 2: | ||
999 | tdfx_outl(par, LAUNCH_2D, *(u16*)chardata); | ||
1000 | break; | ||
1001 | case 3: | ||
1002 | tdfx_outl(par, LAUNCH_2D, | ||
1003 | *(u16*)chardata | ((chardata[3]) << 24)); | ||
1004 | break; | ||
1011 | } | 1005 | } |
1012 | } | 1006 | } |
1013 | #endif /* CONFIG_FB_3DFX_ACCEL */ | 1007 | #endif /* CONFIG_FB_3DFX_ACCEL */ |
@@ -1019,19 +1013,20 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1019 | unsigned long flags; | 1013 | unsigned long flags; |
1020 | 1014 | ||
1021 | /* | 1015 | /* |
1022 | * If the cursor is not be changed this means either we want the | 1016 | * If the cursor is not be changed this means either we want the |
1023 | * current cursor state (if enable is set) or we want to query what | 1017 | * current cursor state (if enable is set) or we want to query what |
1024 | * we can do with the cursor (if enable is not set) | 1018 | * we can do with the cursor (if enable is not set) |
1025 | */ | 1019 | */ |
1026 | if (!cursor->set) return 0; | 1020 | if (!cursor->set) |
1021 | return 0; | ||
1027 | 1022 | ||
1028 | /* Too large of a cursor :-( */ | 1023 | /* Too large of a cursor :-( */ |
1029 | if (cursor->image.width > 64 || cursor->image.height > 64) | 1024 | if (cursor->image.width > 64 || cursor->image.height > 64) |
1030 | return -ENXIO; | 1025 | return -ENXIO; |
1031 | 1026 | ||
1032 | /* | 1027 | /* |
1033 | * If we are going to be changing things we should disable | 1028 | * If we are going to be changing things we should disable |
1034 | * the cursor first | 1029 | * the cursor first |
1035 | */ | 1030 | */ |
1036 | if (info->cursor.enable) { | 1031 | if (info->cursor.enable) { |
1037 | spin_lock_irqsave(&par->DAClock, flags); | 1032 | spin_lock_irqsave(&par->DAClock, flags); |
@@ -1052,11 +1047,11 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1052 | 1047 | ||
1053 | cmap.len = 2; /* Voodoo 3+ only support 2 color cursors */ | 1048 | cmap.len = 2; /* Voodoo 3+ only support 2 color cursors */ |
1054 | fg_color = ((cmap.red[cmap.start] << 16) | | 1049 | fg_color = ((cmap.red[cmap.start] << 16) | |
1055 | (cmap.green[cmap.start] << 8) | | 1050 | (cmap.green[cmap.start] << 8) | |
1056 | (cmap.blue[cmap.start])); | 1051 | (cmap.blue[cmap.start])); |
1057 | bg_color = ((cmap.red[cmap.start+1] << 16) | | 1052 | bg_color = ((cmap.red[cmap.start + 1] << 16) | |
1058 | (cmap.green[cmap.start+1] << 8) | | 1053 | (cmap.green[cmap.start + 1] << 8) | |
1059 | (cmap.blue[cmap.start+1])); | 1054 | (cmap.blue[cmap.start + 1])); |
1060 | fb_copy_cmap(&cmap, &info->cursor.image.cmap); | 1055 | fb_copy_cmap(&cmap, &info->cursor.image.cmap); |
1061 | spin_lock_irqsave(&par->DAClock, flags); | 1056 | spin_lock_irqsave(&par->DAClock, flags); |
1062 | banshee_make_room(par, 2); | 1057 | banshee_make_room(par, 2); |
@@ -1089,7 +1084,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1089 | 1084 | ||
1090 | if (cursor->set && FB_CUR_SETSHAPE) { | 1085 | if (cursor->set && FB_CUR_SETSHAPE) { |
1091 | /* | 1086 | /* |
1092 | * Voodoo 3 and above cards use 2 monochrome cursor patterns. | 1087 | * Voodoo 3 and above cards use 2 monochrome cursor patterns. |
1093 | * The reason is so the card can fetch 8 words at a time | 1088 | * The reason is so the card can fetch 8 words at a time |
1094 | * and are stored on chip for use for the next 8 scanlines. | 1089 | * and are stored on chip for use for the next 8 scanlines. |
1095 | * This reduces the number of times for access to draw the | 1090 | * This reduces the number of times for access to draw the |
@@ -1106,9 +1101,9 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1106 | * (128 bits) which is the maximum cursor width times two for | 1101 | * (128 bits) which is the maximum cursor width times two for |
1107 | * the two monochrome patterns. | 1102 | * the two monochrome patterns. |
1108 | */ | 1103 | */ |
1109 | u8 *cursorbase = (u8 *) info->cursor.image.data; | 1104 | u8 *cursorbase = (u8 *)info->cursor.image.data; |
1110 | char *bitmap = (char *)cursor->image.data; | 1105 | char *bitmap = (char *)cursor->image.data; |
1111 | char *mask = (char *) cursor->mask; | 1106 | char *mask = (char *)cursor->mask; |
1112 | int i, j, k, h = 0; | 1107 | int i, j, k, h = 0; |
1113 | 1108 | ||
1114 | for (i = 0; i < 64; i++) { | 1109 | for (i = 0; i < 64; i++) { |
@@ -1116,16 +1111,16 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1116 | j = (cursor->image.width + 7) >> 3; | 1111 | j = (cursor->image.width + 7) >> 3; |
1117 | k = 8 - j; | 1112 | k = 8 - j; |
1118 | 1113 | ||
1119 | for (;j > 0; j--) { | 1114 | for (; j > 0; j--) { |
1120 | /* Pattern 0. Copy the cursor bitmap to it */ | 1115 | /* Pattern 0. Copy the cursor bitmap to it */ |
1121 | fb_writeb(*bitmap, cursorbase + h); | 1116 | fb_writeb(*bitmap, cursorbase + h); |
1122 | bitmap++; | 1117 | bitmap++; |
1123 | /* Pattern 1. Copy the cursor mask to it */ | 1118 | /* Pattern 1. Copy the cursor mask to it */ |
1124 | fb_writeb(*mask, cursorbase + h + 8); | 1119 | fb_writeb(*mask, cursorbase + h + 8); |
1125 | mask++; | 1120 | mask++; |
1126 | h++; | 1121 | h++; |
1127 | } | 1122 | } |
1128 | for (;k > 0; k--) { | 1123 | for (; k > 0; k--) { |
1129 | fb_writeb(0, cursorbase + h); | 1124 | fb_writeb(0, cursorbase + h); |
1130 | fb_writeb(~0, cursorbase + h + 8); | 1125 | fb_writeb(~0, cursorbase + h + 8); |
1131 | h++; | 1126 | h++; |
@@ -1142,7 +1137,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1142 | /* Turn the cursor on */ | 1137 | /* Turn the cursor on */ |
1143 | cursor->enable = 1; | 1138 | cursor->enable = 1; |
1144 | info->cursor = *cursor; | 1139 | info->cursor = *cursor; |
1145 | mod_timer(&par->hwcursor.timer, jiffies+HZ/2); | 1140 | mod_timer(&par->hwcursor.timer, jiffies + HZ / 2); |
1146 | spin_lock_irqsave(&par->DAClock, flags); | 1141 | spin_lock_irqsave(&par->DAClock, flags); |
1147 | banshee_make_room(par, 1); | 1142 | banshee_make_room(par, 1); |
1148 | tdfx_outl(par, VIDPROCCFG, par->hwcursor.enable); | 1143 | tdfx_outl(par, VIDPROCCFG, par->hwcursor.enable); |
@@ -1151,6 +1146,25 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1151 | } | 1146 | } |
1152 | #endif | 1147 | #endif |
1153 | 1148 | ||
1149 | static struct fb_ops tdfxfb_ops = { | ||
1150 | .owner = THIS_MODULE, | ||
1151 | .fb_check_var = tdfxfb_check_var, | ||
1152 | .fb_set_par = tdfxfb_set_par, | ||
1153 | .fb_setcolreg = tdfxfb_setcolreg, | ||
1154 | .fb_blank = tdfxfb_blank, | ||
1155 | .fb_pan_display = tdfxfb_pan_display, | ||
1156 | .fb_sync = banshee_wait_idle, | ||
1157 | #ifdef CONFIG_FB_3DFX_ACCEL | ||
1158 | .fb_fillrect = tdfxfb_fillrect, | ||
1159 | .fb_copyarea = tdfxfb_copyarea, | ||
1160 | .fb_imageblit = tdfxfb_imageblit, | ||
1161 | #else | ||
1162 | .fb_fillrect = cfb_fillrect, | ||
1163 | .fb_copyarea = cfb_copyarea, | ||
1164 | .fb_imageblit = cfb_imageblit, | ||
1165 | #endif | ||
1166 | }; | ||
1167 | |||
1154 | /** | 1168 | /** |
1155 | * tdfxfb_probe - Device Initializiation | 1169 | * tdfxfb_probe - Device Initializiation |
1156 | * | 1170 | * |
@@ -1161,7 +1175,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1161 | * | 1175 | * |
1162 | */ | 1176 | */ |
1163 | static int __devinit tdfxfb_probe(struct pci_dev *pdev, | 1177 | static int __devinit tdfxfb_probe(struct pci_dev *pdev, |
1164 | const struct pci_device_id *id) | 1178 | const struct pci_device_id *id) |
1165 | { | 1179 | { |
1166 | struct tdfx_par *default_par; | 1180 | struct tdfx_par *default_par; |
1167 | struct fb_info *info; | 1181 | struct fb_info *info; |
@@ -1176,56 +1190,57 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, | |||
1176 | 1190 | ||
1177 | if (!info) | 1191 | if (!info) |
1178 | return -ENOMEM; | 1192 | return -ENOMEM; |
1179 | 1193 | ||
1180 | default_par = info->par; | 1194 | default_par = info->par; |
1181 | 1195 | ||
1182 | /* Configure the default fb_fix_screeninfo first */ | 1196 | /* Configure the default fb_fix_screeninfo first */ |
1183 | switch (pdev->device) { | 1197 | switch (pdev->device) { |
1184 | case PCI_DEVICE_ID_3DFX_BANSHEE: | 1198 | case PCI_DEVICE_ID_3DFX_BANSHEE: |
1185 | strcat(tdfx_fix.id, " Banshee"); | 1199 | strcat(tdfx_fix.id, " Banshee"); |
1186 | default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK; | 1200 | default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK; |
1187 | break; | 1201 | break; |
1188 | case PCI_DEVICE_ID_3DFX_VOODOO3: | 1202 | case PCI_DEVICE_ID_3DFX_VOODOO3: |
1189 | strcat(tdfx_fix.id, " Voodoo3"); | 1203 | strcat(tdfx_fix.id, " Voodoo3"); |
1190 | default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK; | 1204 | default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK; |
1191 | break; | 1205 | break; |
1192 | case PCI_DEVICE_ID_3DFX_VOODOO5: | 1206 | case PCI_DEVICE_ID_3DFX_VOODOO5: |
1193 | strcat(tdfx_fix.id, " Voodoo5"); | 1207 | strcat(tdfx_fix.id, " Voodoo5"); |
1194 | default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK; | 1208 | default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK; |
1195 | break; | 1209 | break; |
1196 | } | 1210 | } |
1197 | 1211 | ||
1198 | tdfx_fix.mmio_start = pci_resource_start(pdev, 0); | 1212 | tdfx_fix.mmio_start = pci_resource_start(pdev, 0); |
1199 | tdfx_fix.mmio_len = pci_resource_len(pdev, 0); | 1213 | tdfx_fix.mmio_len = pci_resource_len(pdev, 0); |
1200 | default_par->regbase_virt = ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len); | 1214 | default_par->regbase_virt = |
1215 | ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len); | ||
1201 | if (!default_par->regbase_virt) { | 1216 | if (!default_par->regbase_virt) { |
1202 | printk("fb: Can't remap %s register area.\n", tdfx_fix.id); | 1217 | printk("fb: Can't remap %s register area.\n", tdfx_fix.id); |
1203 | goto out_err; | 1218 | goto out_err; |
1204 | } | 1219 | } |
1205 | 1220 | ||
1206 | if (!request_mem_region(pci_resource_start(pdev, 0), | 1221 | if (!request_mem_region(pci_resource_start(pdev, 0), |
1207 | pci_resource_len(pdev, 0), "tdfx regbase")) { | 1222 | pci_resource_len(pdev, 0), "tdfx regbase")) { |
1208 | printk(KERN_WARNING "tdfxfb: Can't reserve regbase\n"); | 1223 | printk(KERN_WARNING "tdfxfb: Can't reserve regbase\n"); |
1209 | goto out_err; | 1224 | goto out_err; |
1210 | } | 1225 | } |
1211 | 1226 | ||
1212 | tdfx_fix.smem_start = pci_resource_start(pdev, 1); | 1227 | tdfx_fix.smem_start = pci_resource_start(pdev, 1); |
1213 | if (!(tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device))) { | 1228 | if (!(tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device))) { |
1214 | printk("fb: Can't count %s memory.\n", tdfx_fix.id); | 1229 | printk("fb: Can't count %s memory.\n", tdfx_fix.id); |
1215 | release_mem_region(pci_resource_start(pdev, 0), | 1230 | release_mem_region(pci_resource_start(pdev, 0), |
1216 | pci_resource_len(pdev, 0)); | 1231 | pci_resource_len(pdev, 0)); |
1217 | goto out_err; | 1232 | goto out_err; |
1218 | } | 1233 | } |
1219 | 1234 | ||
1220 | if (!request_mem_region(pci_resource_start(pdev, 1), | 1235 | if (!request_mem_region(pci_resource_start(pdev, 1), |
1221 | pci_resource_len(pdev, 1), "tdfx smem")) { | 1236 | pci_resource_len(pdev, 1), "tdfx smem")) { |
1222 | printk(KERN_WARNING "tdfxfb: Can't reserve smem\n"); | 1237 | printk(KERN_WARNING "tdfxfb: Can't reserve smem\n"); |
1223 | release_mem_region(pci_resource_start(pdev, 0), | 1238 | release_mem_region(pci_resource_start(pdev, 0), |
1224 | pci_resource_len(pdev, 0)); | 1239 | pci_resource_len(pdev, 0)); |
1225 | goto out_err; | 1240 | goto out_err; |
1226 | } | 1241 | } |
1227 | 1242 | ||
1228 | info->screen_base = ioremap_nocache(tdfx_fix.smem_start, | 1243 | info->screen_base = ioremap_nocache(tdfx_fix.smem_start, |
1229 | tdfx_fix.smem_len); | 1244 | tdfx_fix.smem_len); |
1230 | if (!info->screen_base) { | 1245 | if (!info->screen_base) { |
1231 | printk("fb: Can't remap %s framebuffer.\n", tdfx_fix.id); | 1246 | printk("fb: Can't remap %s framebuffer.\n", tdfx_fix.id); |
@@ -1237,9 +1252,9 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, | |||
1237 | } | 1252 | } |
1238 | 1253 | ||
1239 | default_par->iobase = pci_resource_start(pdev, 2); | 1254 | default_par->iobase = pci_resource_start(pdev, 2); |
1240 | 1255 | ||
1241 | if (!request_region(pci_resource_start(pdev, 2), | 1256 | if (!request_region(pci_resource_start(pdev, 2), |
1242 | pci_resource_len(pdev, 2), "tdfx iobase")) { | 1257 | pci_resource_len(pdev, 2), "tdfx iobase")) { |
1243 | printk(KERN_WARNING "tdfxfb: Can't reserve iobase\n"); | 1258 | printk(KERN_WARNING "tdfxfb: Can't reserve iobase\n"); |
1244 | release_mem_region(pci_resource_start(pdev, 1), | 1259 | release_mem_region(pci_resource_start(pdev, 1), |
1245 | pci_resource_len(pdev, 1)); | 1260 | pci_resource_len(pdev, 1)); |
@@ -1252,9 +1267,9 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, | |||
1252 | 1267 | ||
1253 | tdfx_fix.ypanstep = nopan ? 0 : 1; | 1268 | tdfx_fix.ypanstep = nopan ? 0 : 1; |
1254 | tdfx_fix.ywrapstep = nowrap ? 0 : 1; | 1269 | tdfx_fix.ywrapstep = nowrap ? 0 : 1; |
1255 | 1270 | ||
1256 | info->fbops = &tdfxfb_ops; | 1271 | info->fbops = &tdfxfb_ops; |
1257 | info->fix = tdfx_fix; | 1272 | info->fix = tdfx_fix; |
1258 | info->pseudo_palette = default_par->palette; | 1273 | info->pseudo_palette = default_par->palette; |
1259 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | 1274 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; |
1260 | #ifdef CONFIG_FB_3DFX_ACCEL | 1275 | #ifdef CONFIG_FB_3DFX_ACCEL |
@@ -1264,14 +1279,14 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, | |||
1264 | 1279 | ||
1265 | if (!mode_option) | 1280 | if (!mode_option) |
1266 | mode_option = "640x480@60"; | 1281 | mode_option = "640x480@60"; |
1267 | 1282 | ||
1268 | err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); | 1283 | err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); |
1269 | if (!err || err == 4) | 1284 | if (!err || err == 4) |
1270 | info->var = tdfx_var; | 1285 | info->var = tdfx_var; |
1271 | 1286 | ||
1272 | /* maximize virtual vertical length */ | 1287 | /* maximize virtual vertical length */ |
1273 | lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3); | 1288 | lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3); |
1274 | info->var.yres_virtual = info->fix.smem_len/lpitch; | 1289 | info->var.yres_virtual = info->fix.smem_len / lpitch; |
1275 | if (info->var.yres_virtual < info->var.yres) | 1290 | if (info->var.yres_virtual < info->var.yres) |
1276 | goto out_err; | 1291 | goto out_err; |
1277 | 1292 | ||
@@ -1299,7 +1314,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, | |||
1299 | * Our driver data | 1314 | * Our driver data |
1300 | */ | 1315 | */ |
1301 | pci_set_drvdata(pdev, info); | 1316 | pci_set_drvdata(pdev, info); |
1302 | return 0; | 1317 | return 0; |
1303 | 1318 | ||
1304 | out_err: | 1319 | out_err: |
1305 | /* | 1320 | /* |
@@ -1316,7 +1331,7 @@ out_err: | |||
1316 | #ifndef MODULE | 1331 | #ifndef MODULE |
1317 | static void tdfxfb_setup(char *options) | 1332 | static void tdfxfb_setup(char *options) |
1318 | { | 1333 | { |
1319 | char* this_opt; | 1334 | char *this_opt; |
1320 | 1335 | ||
1321 | if (!options || !*options) | 1336 | if (!options || !*options) |
1322 | return; | 1337 | return; |
@@ -1324,9 +1339,9 @@ static void tdfxfb_setup(char *options) | |||
1324 | while ((this_opt = strsep(&options, ",")) != NULL) { | 1339 | while ((this_opt = strsep(&options, ",")) != NULL) { |
1325 | if (!*this_opt) | 1340 | if (!*this_opt) |
1326 | continue; | 1341 | continue; |
1327 | if(!strcmp(this_opt, "nopan")) { | 1342 | if (!strcmp(this_opt, "nopan")) { |
1328 | nopan = 1; | 1343 | nopan = 1; |
1329 | } else if(!strcmp(this_opt, "nowrap")) { | 1344 | } else if (!strcmp(this_opt, "nowrap")) { |
1330 | nowrap = 1; | 1345 | nowrap = 1; |
1331 | } else { | 1346 | } else { |
1332 | mode_option = this_opt; | 1347 | mode_option = this_opt; |
@@ -1374,17 +1389,17 @@ static int __init tdfxfb_init(void) | |||
1374 | 1389 | ||
1375 | tdfxfb_setup(option); | 1390 | tdfxfb_setup(option); |
1376 | #endif | 1391 | #endif |
1377 | return pci_register_driver(&tdfxfb_driver); | 1392 | return pci_register_driver(&tdfxfb_driver); |
1378 | } | 1393 | } |
1379 | 1394 | ||
1380 | static void __exit tdfxfb_exit(void) | 1395 | static void __exit tdfxfb_exit(void) |
1381 | { | 1396 | { |
1382 | pci_unregister_driver(&tdfxfb_driver); | 1397 | pci_unregister_driver(&tdfxfb_driver); |
1383 | } | 1398 | } |
1384 | 1399 | ||
1385 | MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>"); | 1400 | MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>"); |
1386 | MODULE_DESCRIPTION("3Dfx framebuffer device driver"); | 1401 | MODULE_DESCRIPTION("3Dfx framebuffer device driver"); |
1387 | MODULE_LICENSE("GPL"); | 1402 | MODULE_LICENSE("GPL"); |
1388 | 1403 | ||
1389 | module_init(tdfxfb_init); | 1404 | module_init(tdfxfb_init); |
1390 | module_exit(tdfxfb_exit); | 1405 | module_exit(tdfxfb_exit); |