]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/video/cirrusfb.c
7355da09c721bc8fa7ad1fee66f51d4356abe7c3
[linux-2.6-omap-h63xx.git] / drivers / video / cirrusfb.c
1 /*
2  * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
3  *
4  * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
5  *
6  * Contributors (thanks, all!)
7  *
8  *      David Eger:
9  *      Overhaul for Linux 2.6
10  *
11  *      Jeff Rugen:
12  *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
13  *      GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
14  *
15  *      Geert Uytterhoeven:
16  *      Excellent code review.
17  *
18  *      Lars Hecking:
19  *      Amiga updates and testing.
20  *
21  * Original cirrusfb author:  Frank Neumann
22  *
23  * Based on retz3fb.c and cirrusfb.c:
24  *      Copyright (C) 1997 Jes Sorensen
25  *      Copyright (C) 1996 Frank Neumann
26  *
27  ***************************************************************
28  *
29  * Format this code with GNU indent '-kr -i8 -pcs' options.
30  *
31  * This file is subject to the terms and conditions of the GNU General Public
32  * License.  See the file COPYING in the main directory of this archive
33  * for more details.
34  *
35  */
36
37 #define CIRRUSFB_VERSION "2.0-pre2"
38
39 #include <linux/module.h>
40 #include <linux/kernel.h>
41 #include <linux/errno.h>
42 #include <linux/string.h>
43 #include <linux/mm.h>
44 #include <linux/tty.h>
45 #include <linux/slab.h>
46 #include <linux/delay.h>
47 #include <linux/fb.h>
48 #include <linux/init.h>
49 #include <linux/selection.h>
50 #include <asm/pgtable.h>
51
52 #ifdef CONFIG_ZORRO
53 #include <linux/zorro.h>
54 #endif
55 #ifdef CONFIG_PCI
56 #include <linux/pci.h>
57 #endif
58 #ifdef CONFIG_AMIGA
59 #include <asm/amigahw.h>
60 #endif
61 #ifdef CONFIG_PPC_PREP
62 #include <asm/machdep.h>
63 #define isPReP (machine_is(prep))
64 #else
65 #define isPReP 0
66 #endif
67
68 #include "video/vga.h"
69 #include "video/cirrus.h"
70
71
72 /*****************************************************************
73  *
74  * debugging and utility macros
75  *
76  */
77
78 /* enable debug output? */
79 /* #define CIRRUSFB_DEBUG 1 */
80
81 /* disable runtime assertions? */
82 /* #define CIRRUSFB_NDEBUG */
83
84 /* debug output */
85 #ifdef CIRRUSFB_DEBUG
86 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
87 #else
88 #define DPRINTK(fmt, args...)
89 #endif
90
91 /* debugging assertions */
92 #ifndef CIRRUSFB_NDEBUG
93 #define assert(expr) \
94         if(!(expr)) { \
95         printk( "Assertion failed! %s,%s,%s,line=%d\n",\
96         #expr,__FILE__,__FUNCTION__,__LINE__); \
97         }
98 #else
99 #define assert(expr)
100 #endif
101
102 #ifdef TRUE
103 #undef TRUE
104 #endif
105 #ifdef FALSE
106 #undef FALSE
107 #endif
108 #define TRUE  1
109 #define FALSE 0
110
111 #define MB_ (1024*1024)
112 #define KB_ (1024)
113
114 #define MAX_NUM_BOARDS 7
115
116
117 /*****************************************************************
118  *
119  * chipset information
120  *
121  */
122
123 /* board types */
124 typedef enum {
125         BT_NONE = 0,
126         BT_SD64,
127         BT_PICCOLO,
128         BT_PICASSO,
129         BT_SPECTRUM,
130         BT_PICASSO4,    /* GD5446 */
131         BT_ALPINE,      /* GD543x/4x */
132         BT_GD5480,
133         BT_LAGUNA,      /* GD546x */
134 } cirrusfb_board_t;
135
136
137 /*
138  * per-board-type information, used for enumerating and abstracting
139  * chip-specific information
140  * NOTE: MUST be in the same order as cirrusfb_board_t in order to
141  * use direct indexing on this array
142  * NOTE: '__initdata' cannot be used as some of this info
143  * is required at runtime.  Maybe separate into an init-only and
144  * a run-time table?
145  */
146 static const struct cirrusfb_board_info_rec {
147         char *name;             /* ASCII name of chipset */
148         long maxclock[5];               /* maximum video clock */
149         /* for  1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
150         unsigned init_sr07 : 1; /* init SR07 during init_vgachip() */
151         unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */
152         unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
153
154         /* initial SR07 value, then for each mode */
155         unsigned char sr07;
156         unsigned char sr07_1bpp;
157         unsigned char sr07_1bpp_mux;
158         unsigned char sr07_8bpp;
159         unsigned char sr07_8bpp_mux;
160
161         unsigned char sr1f;     /* SR1F VGA initial register value */
162 } cirrusfb_board_info[] = {
163         [BT_SD64] = {
164                 .name                   = "CL SD64",
165                 .maxclock               = {
166                         /* guess */
167                         /* the SD64/P4 have a higher max. videoclock */
168                         140000, 140000, 140000, 140000, 140000,
169                 },
170                 .init_sr07              = TRUE,
171                 .init_sr1f              = TRUE,
172                 .scrn_start_bit19       = TRUE,
173                 .sr07                   = 0xF0,
174                 .sr07_1bpp              = 0xF0,
175                 .sr07_8bpp              = 0xF1,
176                 .sr1f                   = 0x20
177         },
178         [BT_PICCOLO] = {
179                 .name                   = "CL Piccolo",
180                 .maxclock               = {
181                         /* guess */
182                         90000, 90000, 90000, 90000, 90000
183                 },
184                 .init_sr07              = TRUE,
185                 .init_sr1f              = TRUE,
186                 .scrn_start_bit19       = FALSE,
187                 .sr07                   = 0x80,
188                 .sr07_1bpp              = 0x80,
189                 .sr07_8bpp              = 0x81,
190                 .sr1f                   = 0x22
191         },
192         [BT_PICASSO] = {
193                 .name                   = "CL Picasso",
194                 .maxclock               = {
195                         /* guess */
196                         90000, 90000, 90000, 90000, 90000
197                 },
198                 .init_sr07              = TRUE,
199                 .init_sr1f              = TRUE,
200                 .scrn_start_bit19       = FALSE,
201                 .sr07                   = 0x20,
202                 .sr07_1bpp              = 0x20,
203                 .sr07_8bpp              = 0x21,
204                 .sr1f                   = 0x22
205         },
206         [BT_SPECTRUM] = {
207                 .name                   = "CL Spectrum",
208                 .maxclock               = {
209                         /* guess */
210                         90000, 90000, 90000, 90000, 90000
211                 },
212                 .init_sr07              = TRUE,
213                 .init_sr1f              = TRUE,
214                 .scrn_start_bit19       = FALSE,
215                 .sr07                   = 0x80,
216                 .sr07_1bpp              = 0x80,
217                 .sr07_8bpp              = 0x81,
218                 .sr1f                   = 0x22
219         },
220         [BT_PICASSO4] = {
221                 .name                   = "CL Picasso4",
222                 .maxclock               = {
223                         135100, 135100, 85500, 85500, 0
224                 },
225                 .init_sr07              = TRUE,
226                 .init_sr1f              = FALSE,
227                 .scrn_start_bit19       = TRUE,
228                 .sr07                   = 0x20,
229                 .sr07_1bpp              = 0x20,
230                 .sr07_8bpp              = 0x21,
231                 .sr1f                   = 0
232         },
233         [BT_ALPINE] = {
234                 .name                   = "CL Alpine",
235                 .maxclock               = {
236                         /* for the GD5430.  GD5446 can do more... */
237                         85500, 85500, 50000, 28500, 0
238                 },
239                 .init_sr07              = TRUE,
240                 .init_sr1f              = TRUE,
241                 .scrn_start_bit19       = TRUE,
242                 .sr07                   = 0xA0,
243                 .sr07_1bpp              = 0xA1,
244                 .sr07_1bpp_mux          = 0xA7,
245                 .sr07_8bpp              = 0xA1,
246                 .sr07_8bpp_mux          = 0xA7,
247                 .sr1f                   = 0x1C
248         },
249         [BT_GD5480] = {
250                 .name                   = "CL GD5480",
251                 .maxclock               = {
252                         135100, 200000, 200000, 135100, 135100
253                 },
254                 .init_sr07              = TRUE,
255                 .init_sr1f              = TRUE,
256                 .scrn_start_bit19       = TRUE,
257                 .sr07                   = 0x10,
258                 .sr07_1bpp              = 0x11,
259                 .sr07_8bpp              = 0x11,
260                 .sr1f                   = 0x1C
261         },
262         [BT_LAGUNA] = {
263                 .name                   = "CL Laguna",
264                 .maxclock               = {
265                         /* guess */
266                         135100, 135100, 135100, 135100, 135100,
267                 },
268                 .init_sr07              = FALSE,
269                 .init_sr1f              = FALSE,
270                 .scrn_start_bit19       = TRUE,
271         }
272 };
273
274
275 #ifdef CONFIG_PCI
276 #define CHIP(id, btype) \
277         { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
278
279 static struct pci_device_id cirrusfb_pci_table[] = {
280         CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ),
281         CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ),
282         CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ),
283         CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */
284         CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ),
285         CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ),
286         CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */
287         CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */
288         CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
289         CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
290         CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
291         { 0, }
292 };
293 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
294 #undef CHIP
295 #endif /* CONFIG_PCI */
296
297
298 #ifdef CONFIG_ZORRO
299 static const struct zorro_device_id cirrusfb_zorro_table[] = {
300         {
301                 .id             = ZORRO_PROD_HELFRICH_SD64_RAM,
302                 .driver_data    = BT_SD64,
303         }, {
304                 .id             = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
305                 .driver_data    = BT_PICCOLO,
306         }, {
307                 .id             = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
308                 .driver_data    = BT_PICASSO,
309         }, {
310                 .id             = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
311                 .driver_data    = BT_SPECTRUM,
312         }, {
313                 .id             = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
314                 .driver_data    = BT_PICASSO4,
315         },
316         { 0 }
317 };
318
319 static const struct {
320         zorro_id id2;
321         unsigned long size;
322 } cirrusfb_zorro_table2[] = {
323         [BT_SD64] = {
324                 .id2    = ZORRO_PROD_HELFRICH_SD64_REG,
325                 .size   = 0x400000
326         },
327         [BT_PICCOLO] = {
328                 .id2    = ZORRO_PROD_HELFRICH_PICCOLO_REG,
329                 .size   = 0x200000
330         },
331         [BT_PICASSO] = {
332                 .id2    = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
333                 .size   = 0x200000
334         },
335         [BT_SPECTRUM] = {
336                 .id2    = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
337                 .size   = 0x200000
338         },
339         [BT_PICASSO4] = {
340                 .id2    = 0,
341                 .size   = 0x400000
342         }
343 };
344 #endif /* CONFIG_ZORRO */
345
346
347 struct cirrusfb_regs {
348         __u32 line_length;      /* in BYTES! */
349         __u32 visual;
350         __u32 type;
351
352         long freq;
353         long nom;
354         long den;
355         long div;
356         long multiplexing;
357         long mclk;
358         long divMCLK;
359
360         long HorizRes;          /* The x resolution in pixel */
361         long HorizTotal;
362         long HorizDispEnd;
363         long HorizBlankStart;
364         long HorizBlankEnd;
365         long HorizSyncStart;
366         long HorizSyncEnd;
367
368         long VertRes;           /* the physical y resolution in scanlines */
369         long VertTotal;
370         long VertDispEnd;
371         long VertSyncStart;
372         long VertSyncEnd;
373         long VertBlankStart;
374         long VertBlankEnd;
375 };
376
377
378
379 #ifdef CIRRUSFB_DEBUG
380 typedef enum {
381         CRT,
382         SEQ
383 } cirrusfb_dbg_reg_class_t;
384 #endif                          /* CIRRUSFB_DEBUG */
385
386
387
388
389 /* info about board */
390 struct cirrusfb_info {
391         struct fb_info *info;
392
393         u8 __iomem *fbmem;
394         u8 __iomem *regbase;
395         u8 __iomem *mem;
396         unsigned long size;
397         cirrusfb_board_t btype;
398         unsigned char SFR;      /* Shadow of special function register */
399
400         unsigned long fbmem_phys;
401         unsigned long fbregs_phys;
402
403         struct cirrusfb_regs currentmode;
404         int blank_mode;
405
406         u32     pseudo_palette[16];
407         struct { u8 red, green, blue, pad; } palette[256];
408
409 #ifdef CONFIG_ZORRO
410         struct zorro_dev *zdev;
411 #endif
412 #ifdef CONFIG_PCI
413         struct pci_dev *pdev;
414 #endif
415         void (*unmap)(struct cirrusfb_info *cinfo);
416 };
417
418
419 static unsigned cirrusfb_def_mode = 1;
420 static int noaccel = 0;
421
422 /*
423  *    Predefined Video Modes
424  */
425
426 static const struct {
427         const char *name;
428         struct fb_var_screeninfo var;
429 } cirrusfb_predefined[] = {
430         {
431                 /* autodetect mode */
432                 .name   = "Autodetect",
433         }, {
434                 /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
435                 .name   = "640x480",
436                 .var    = {
437                         .xres           = 640,
438                         .yres           = 480,
439                         .xres_virtual   = 640,
440                         .yres_virtual   = 480,
441                         .bits_per_pixel = 8,
442                         .red            = { .length = 8 },
443                         .green          = { .length = 8 },
444                         .blue           = { .length = 8 },
445                         .width          = -1,
446                         .height         = -1,
447                         .pixclock       = 40000,
448                         .left_margin    = 48,
449                         .right_margin   = 16,
450                         .upper_margin   = 32,
451                         .lower_margin   = 8,
452                         .hsync_len      = 96,
453                         .vsync_len      = 4,
454                         .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
455                         .vmode          = FB_VMODE_NONINTERLACED
456                  }
457         }, {
458                 /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
459                 .name   = "800x600",
460                 .var    = {
461                         .xres           = 800,
462                         .yres           = 600,
463                         .xres_virtual   = 800,
464                         .yres_virtual   = 600,
465                         .bits_per_pixel = 8,
466                         .red            = { .length = 8 },
467                         .green          = { .length = 8 },
468                         .blue           = { .length = 8 },
469                         .width          = -1,
470                         .height         = -1,
471                         .pixclock       = 20000,
472                         .left_margin    = 128,
473                         .right_margin   = 16,
474                         .upper_margin   = 24,
475                         .lower_margin   = 2,
476                         .hsync_len      = 96,
477                         .vsync_len      = 6,
478                         .vmode          = FB_VMODE_NONINTERLACED
479                  }
480         }, {
481                 /*
482                  * Modeline from XF86Config:
483                  * Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
484                  */
485                 /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
486                 .name   = "1024x768",
487                 .var    = {
488                         .xres           = 1024,
489                         .yres           = 768,
490                         .xres_virtual   = 1024,
491                         .yres_virtual   = 768,
492                         .bits_per_pixel = 8,
493                         .red            = { .length = 8 },
494                         .green          = { .length = 8 },
495                         .blue           = { .length = 8 },
496                         .width          = -1,
497                         .height         = -1,
498                         .pixclock       = 12500,
499                         .left_margin    = 144,
500                         .right_margin   = 32,
501                         .upper_margin   = 30,
502                         .lower_margin   = 2,
503                         .hsync_len      = 192,
504                         .vsync_len      = 6,
505                         .vmode          = FB_VMODE_NONINTERLACED
506                 }
507         }
508 };
509
510 #define NUM_TOTAL_MODES    ARRAY_SIZE(cirrusfb_predefined)
511
512 /****************************************************************************/
513 /**** BEGIN PROTOTYPES ******************************************************/
514
515
516 /*--- Interface used by the world ------------------------------------------*/
517 static int cirrusfb_init (void);
518 #ifndef MODULE
519 static int cirrusfb_setup (char *options);
520 #endif
521
522 static int cirrusfb_open (struct fb_info *info, int user);
523 static int cirrusfb_release (struct fb_info *info, int user);
524 static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
525                                unsigned blue, unsigned transp,
526                                struct fb_info *info);
527 static int cirrusfb_check_var (struct fb_var_screeninfo *var,
528                                struct fb_info *info);
529 static int cirrusfb_set_par (struct fb_info *info);
530 static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
531                                  struct fb_info *info);
532 static int cirrusfb_blank (int blank_mode, struct fb_info *info);
533 static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);
534 static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
535 static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
536
537 /* function table of the above functions */
538 static struct fb_ops cirrusfb_ops = {
539         .owner          = THIS_MODULE,
540         .fb_open        = cirrusfb_open,
541         .fb_release     = cirrusfb_release,
542         .fb_setcolreg   = cirrusfb_setcolreg,
543         .fb_check_var   = cirrusfb_check_var,
544         .fb_set_par     = cirrusfb_set_par,
545         .fb_pan_display = cirrusfb_pan_display,
546         .fb_blank       = cirrusfb_blank,
547         .fb_fillrect    = cirrusfb_fillrect,
548         .fb_copyarea    = cirrusfb_copyarea,
549         .fb_imageblit   = cirrusfb_imageblit,
550 };
551
552 /*--- Hardware Specific Routines -------------------------------------------*/
553 static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
554                                 struct cirrusfb_regs *regs,
555                                 const struct fb_info *info);
556 /*--- Internal routines ----------------------------------------------------*/
557 static void init_vgachip (struct cirrusfb_info *cinfo);
558 static void switch_monitor (struct cirrusfb_info *cinfo, int on);
559 static void WGen (const struct cirrusfb_info *cinfo,
560                   int regnum, unsigned char val);
561 static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum);
562 static void AttrOn (const struct cirrusfb_info *cinfo);
563 static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val);
564 static void WSFR (struct cirrusfb_info *cinfo, unsigned char val);
565 static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val);
566 static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
567                    unsigned char green,
568                    unsigned char blue);
569 #if 0
570 static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
571                    unsigned char *green,
572                    unsigned char *blue);
573 #endif
574 static void cirrusfb_WaitBLT (u8 __iomem *regbase);
575 static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
576                              u_short curx, u_short cury,
577                              u_short destx, u_short desty,
578                              u_short width, u_short height,
579                              u_short line_length);
580 static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
581                                u_short x, u_short y,
582                                u_short width, u_short height,
583                                u_char color, u_short line_length);
584
585 static void bestclock (long freq, long *best,
586                        long *nom, long *den,
587                        long *div, long maxfreq);
588
589 #ifdef CIRRUSFB_DEBUG
590 static void cirrusfb_dump (void);
591 static void cirrusfb_dbg_reg_dump (caddr_t regbase);
592 static void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...);
593 static void cirrusfb_dbg_print_byte (const char *name, unsigned char val);
594 #endif /* CIRRUSFB_DEBUG */
595
596 /*** END   PROTOTYPES ********************************************************/
597 /*****************************************************************************/
598 /*** BEGIN Interface Used by the World ***************************************/
599
600 static int opencount = 0;
601
602 /*--- Open /dev/fbx ---------------------------------------------------------*/
603 static int cirrusfb_open (struct fb_info *info, int user)
604 {
605         if (opencount++ == 0)
606                 switch_monitor (info->par, 1);
607         return 0;
608 }
609
610 /*--- Close /dev/fbx --------------------------------------------------------*/
611 static int cirrusfb_release (struct fb_info *info, int user)
612 {
613         if (--opencount == 0)
614                 switch_monitor (info->par, 0);
615         return 0;
616 }
617
618 /**** END   Interface used by the World *************************************/
619 /****************************************************************************/
620 /**** BEGIN Hardware specific Routines **************************************/
621
622 /* Get a good MCLK value */
623 static long cirrusfb_get_mclk (long freq, int bpp, long *div)
624 {
625         long mclk;
626
627         assert (div != NULL);
628
629         /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
630          * Assume a 64-bit data path for now.  The formula is:
631          * ((B * PCLK * 2)/W) * 1.2
632          * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
633         mclk = ((bpp / 8) * freq * 2) / 4;
634         mclk = (mclk * 12) / 10;
635         if (mclk < 50000)
636                 mclk = 50000;
637         DPRINTK ("Use MCLK of %ld kHz\n", mclk);
638
639         /* Calculate value for SR1F.  Multiply by 2 so we can round up. */
640         mclk = ((mclk * 16) / 14318);
641         mclk = (mclk + 1) / 2;
642         DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);
643
644         /* Determine if we should use MCLK instead of VCLK, and if so, what we
645            * should divide it by to get VCLK */
646         switch (freq) {
647         case 24751 ... 25249:
648                 *div = 2;
649                 DPRINTK ("Using VCLK = MCLK/2\n");
650                 break;
651         case 49501 ... 50499:
652                 *div = 1;
653                 DPRINTK ("Using VCLK = MCLK\n");
654                 break;
655         default:
656                 *div = 0;
657                 break;
658         }
659
660         return mclk;
661 }
662
663 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
664                               struct fb_info *info)
665 {
666         struct cirrusfb_info *cinfo = info->par;
667         int nom, den;           /* translyting from pixels->bytes */
668         int yres, i;
669         static struct { int xres, yres; } modes[] =
670         { { 1600, 1280 },
671           { 1280, 1024 },
672           { 1024, 768 },
673           { 800, 600 },
674           { 640, 480 },
675           { -1, -1 } };
676
677         switch (var->bits_per_pixel) {
678         case 0 ... 1:
679                 var->bits_per_pixel = 1;
680                 nom = 4;
681                 den = 8;
682                 break;          /* 8 pixel per byte, only 1/4th of mem usable */
683         case 2 ... 8:
684                 var->bits_per_pixel = 8;
685                 nom = 1;
686                 den = 1;
687                 break;          /* 1 pixel == 1 byte */
688         case 9 ... 16:
689                 var->bits_per_pixel = 16;
690                 nom = 2;
691                 den = 1;
692                 break;          /* 2 bytes per pixel */
693         case 17 ... 24:
694                 var->bits_per_pixel = 24;
695                 nom = 3;
696                 den = 1;
697                 break;          /* 3 bytes per pixel */
698         case 25 ... 32:
699                 var->bits_per_pixel = 32;
700                 nom = 4;
701                 den = 1;
702                 break;          /* 4 bytes per pixel */
703         default:
704                 printk ("cirrusfb: mode %dx%dx%d rejected...color depth not supported.\n",
705                         var->xres, var->yres, var->bits_per_pixel);
706                 DPRINTK ("EXIT - EINVAL error\n");
707                 return -EINVAL;
708         }
709
710         if (var->xres * nom / den * var->yres > cinfo->size) {
711                 printk ("cirrusfb: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
712                         var->xres, var->yres, var->bits_per_pixel);
713                 DPRINTK ("EXIT - EINVAL error\n");
714                 return -EINVAL;
715         }
716
717         /* use highest possible virtual resolution */
718         if (var->xres_virtual == -1 &&
719             var->yres_virtual == -1) {
720                 printk ("cirrusfb: using maximum available virtual resolution\n");
721                 for (i = 0; modes[i].xres != -1; i++) {
722                         if (modes[i].xres * nom / den * modes[i].yres < cinfo->size / 2)
723                                 break;
724                 }
725                 if (modes[i].xres == -1) {
726                         printk ("cirrusfb: could not find a virtual resolution that fits into video memory!!\n");
727                         DPRINTK ("EXIT - EINVAL error\n");
728                         return -EINVAL;
729                 }
730                 var->xres_virtual = modes[i].xres;
731                 var->yres_virtual = modes[i].yres;
732
733                 printk ("cirrusfb: virtual resolution set to maximum of %dx%d\n",
734                         var->xres_virtual, var->yres_virtual);
735         }
736
737         if (var->xres_virtual < var->xres)
738                 var->xres_virtual = var->xres;
739         if (var->yres_virtual < var->yres)
740                 var->yres_virtual = var->yres;
741
742         if (var->xoffset < 0)
743                 var->xoffset = 0;
744         if (var->yoffset < 0)
745                 var->yoffset = 0;
746
747         /* truncate xoffset and yoffset to maximum if too high */
748         if (var->xoffset > var->xres_virtual - var->xres)
749                 var->xoffset = var->xres_virtual - var->xres - 1;
750         if (var->yoffset > var->yres_virtual - var->yres)
751                 var->yoffset = var->yres_virtual - var->yres - 1;
752
753         switch (var->bits_per_pixel) {
754         case 1:
755                 var->red.offset = 0;
756                 var->red.length = 1;
757                 var->green.offset = 0;
758                 var->green.length = 1;
759                 var->blue.offset = 0;
760                 var->blue.length = 1;
761                 break;
762
763         case 8:
764                 var->red.offset = 0;
765                 var->red.length = 6;
766                 var->green.offset = 0;
767                 var->green.length = 6;
768                 var->blue.offset = 0;
769                 var->blue.length = 6;
770                 break;
771
772         case 16:
773                 if(isPReP) {
774                         var->red.offset = 2;
775                         var->green.offset = -3;
776                         var->blue.offset = 8;
777                 } else {
778                         var->red.offset = 10;
779                         var->green.offset = 5;
780                         var->blue.offset = 0;
781                 }
782                 var->red.length = 5;
783                 var->green.length = 5;
784                 var->blue.length = 5;
785                 break;
786
787         case 24:
788                 if(isPReP) {
789                         var->red.offset = 8;
790                         var->green.offset = 16;
791                         var->blue.offset = 24;
792                 } else {
793                         var->red.offset = 16;
794                         var->green.offset = 8;
795                         var->blue.offset = 0;
796                 }
797                 var->red.length = 8;
798                 var->green.length = 8;
799                 var->blue.length = 8;
800                 break;
801
802         case 32:
803                 if(isPReP) {
804                         var->red.offset = 8;
805                         var->green.offset = 16;
806                         var->blue.offset = 24;
807                 } else {
808                         var->red.offset = 16;
809                         var->green.offset = 8;
810                         var->blue.offset = 0;
811                 }
812                 var->red.length = 8;
813                 var->green.length = 8;
814                 var->blue.length = 8;
815                 break;
816
817         default:
818                 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
819                 assert (FALSE);
820                 /* should never occur */
821                 break;
822         }
823
824         var->red.msb_right =
825             var->green.msb_right =
826             var->blue.msb_right =
827             var->transp.offset =
828             var->transp.length =
829             var->transp.msb_right = 0;
830
831         yres = var->yres;
832         if (var->vmode & FB_VMODE_DOUBLE)
833                 yres *= 2;
834         else if (var->vmode & FB_VMODE_INTERLACED)
835                 yres = (yres + 1) / 2;
836
837         if (yres >= 1280) {
838                 printk (KERN_WARNING "cirrusfb: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");
839                 DPRINTK ("EXIT - EINVAL error\n");
840                 return -EINVAL;
841         }
842
843         return 0;
844 }
845
846 static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,
847                                 struct cirrusfb_regs *regs,
848                                 const struct fb_info *info)
849 {
850         long freq;
851         long maxclock;
852         int maxclockidx = 0;
853         struct cirrusfb_info *cinfo = info->par;
854         int xres, hfront, hsync, hback;
855         int yres, vfront, vsync, vback;
856
857         switch(var->bits_per_pixel) {
858         case 1:
859                 regs->line_length = var->xres_virtual / 8;
860                 regs->visual = FB_VISUAL_MONO10;
861                 maxclockidx = 0;
862                 break;
863
864         case 8:
865                 regs->line_length = var->xres_virtual;
866                 regs->visual = FB_VISUAL_PSEUDOCOLOR;
867                 maxclockidx = 1;
868                 break;
869
870         case 16:
871                 regs->line_length = var->xres_virtual * 2;
872                 regs->visual = FB_VISUAL_DIRECTCOLOR;
873                 maxclockidx = 2;
874                 break;
875
876         case 24:
877                 regs->line_length = var->xres_virtual * 3;
878                 regs->visual = FB_VISUAL_DIRECTCOLOR;
879                 maxclockidx = 3;
880                 break;
881
882         case 32:
883                 regs->line_length = var->xres_virtual * 4;
884                 regs->visual = FB_VISUAL_DIRECTCOLOR;
885                 maxclockidx = 4;
886                 break;
887
888         default:
889                 DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);
890                 assert (FALSE);
891                 /* should never occur */
892                 break;
893         }
894
895         regs->type = FB_TYPE_PACKED_PIXELS;
896
897         /* convert from ps to kHz */
898         freq = 1000000000 / var->pixclock;
899
900         DPRINTK ("desired pixclock: %ld kHz\n", freq);
901
902         maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
903         regs->multiplexing = 0;
904
905         /* If the frequency is greater than we can support, we might be able
906          * to use multiplexing for the video mode */
907         if (freq > maxclock) {
908                 switch (cinfo->btype) {
909                 case BT_ALPINE:
910                 case BT_GD5480:
911                         regs->multiplexing = 1;
912                         break;
913
914                 default:
915                         printk (KERN_WARNING "cirrusfb: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);
916                         DPRINTK ("EXIT - return -EINVAL\n");
917                         return -EINVAL;
918                 }
919         }
920 #if 0
921         /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
922          * the VCLK is double the pixel clock. */
923         switch (var->bits_per_pixel) {
924         case 16:
925         case 32:
926                 if (regs->HorizRes <= 800)
927                         freq /= 2;      /* Xbh has this type of clock for 32-bit */
928                 break;
929         }
930 #endif
931
932         bestclock (freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
933                    maxclock);
934         regs->mclk = cirrusfb_get_mclk (freq, var->bits_per_pixel, &regs->divMCLK);
935
936         xres = var->xres;
937         hfront = var->right_margin;
938         hsync = var->hsync_len;
939         hback = var->left_margin;
940
941         yres = var->yres;
942         vfront = var->lower_margin;
943         vsync = var->vsync_len;
944         vback = var->upper_margin;
945
946         if (var->vmode & FB_VMODE_DOUBLE) {
947                 yres *= 2;
948                 vfront *= 2;
949                 vsync *= 2;
950                 vback *= 2;
951         } else if (var->vmode & FB_VMODE_INTERLACED) {
952                 yres = (yres + 1) / 2;
953                 vfront = (vfront + 1) / 2;
954                 vsync = (vsync + 1) / 2;
955                 vback = (vback + 1) / 2;
956         }
957         regs->HorizRes = xres;
958         regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
959         regs->HorizDispEnd = xres / 8 - 1;
960         regs->HorizBlankStart = xres / 8;
961         regs->HorizBlankEnd = regs->HorizTotal + 5;     /* does not count with "-5" */
962         regs->HorizSyncStart = (xres + hfront) / 8 + 1;
963         regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
964
965         regs->VertRes = yres;
966         regs->VertTotal = yres + vfront + vsync + vback - 2;
967         regs->VertDispEnd = yres - 1;
968         regs->VertBlankStart = yres;
969         regs->VertBlankEnd = regs->VertTotal;
970         regs->VertSyncStart = yres + vfront - 1;
971         regs->VertSyncEnd = yres + vfront + vsync - 1;
972
973         if (regs->VertRes >= 1024) {
974                 regs->VertTotal /= 2;
975                 regs->VertSyncStart /= 2;
976                 regs->VertSyncEnd /= 2;
977                 regs->VertDispEnd /= 2;
978         }
979         if (regs->multiplexing) {
980                 regs->HorizTotal /= 2;
981                 regs->HorizSyncStart /= 2;
982                 regs->HorizSyncEnd /= 2;
983                 regs->HorizDispEnd /= 2;
984         }
985
986         return 0;
987 }
988
989
990 static void cirrusfb_set_mclk (const struct cirrusfb_info *cinfo, int val, int div)
991 {
992         assert (cinfo != NULL);
993
994         if (div == 2) {
995                 /* VCLK = MCLK/2 */
996                 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
997                 vga_wseq (cinfo->regbase, CL_SEQR1E, old | 0x1);
998                 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
999         } else if (div == 1) {
1000                 /* VCLK = MCLK */
1001                 unsigned char old = vga_rseq (cinfo->regbase, CL_SEQR1E);
1002                 vga_wseq (cinfo->regbase, CL_SEQR1E, old & ~0x1);
1003                 vga_wseq (cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
1004         } else {
1005                 vga_wseq (cinfo->regbase, CL_SEQR1F, val & 0x3f);
1006         }
1007 }
1008
1009 /*************************************************************************
1010         cirrusfb_set_par_foo()
1011
1012         actually writes the values for a new video mode into the hardware,
1013 **************************************************************************/
1014 static int cirrusfb_set_par_foo (struct fb_info *info)
1015 {
1016         struct cirrusfb_info *cinfo = info->par;
1017         struct fb_var_screeninfo *var = &info->var;
1018         struct cirrusfb_regs regs;
1019         u8 __iomem *regbase = cinfo->regbase;
1020         unsigned char tmp;
1021         int offset = 0, err;
1022         const struct cirrusfb_board_info_rec *bi;
1023
1024         DPRINTK ("ENTER\n");
1025         DPRINTK ("Requested mode: %dx%dx%d\n",
1026                var->xres, var->yres, var->bits_per_pixel);
1027         DPRINTK ("pixclock: %d\n", var->pixclock);
1028
1029         init_vgachip (cinfo);
1030
1031         err = cirrusfb_decode_var(var, &regs, info);
1032         if(err) {
1033                 /* should never happen */
1034                 DPRINTK("mode change aborted.  invalid var.\n");
1035                 return -EINVAL;
1036         }
1037
1038         bi = &cirrusfb_board_info[cinfo->btype];
1039
1040
1041         /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
1042         vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20);  /* previously: 0x00) */
1043
1044         /* if debugging is enabled, all parameters get output before writing */
1045         DPRINTK ("CRT0: %ld\n", regs.HorizTotal);
1046         vga_wcrt (regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
1047
1048         DPRINTK ("CRT1: %ld\n", regs.HorizDispEnd);
1049         vga_wcrt (regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
1050
1051         DPRINTK ("CRT2: %ld\n", regs.HorizBlankStart);
1052         vga_wcrt (regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
1053
1054         DPRINTK ("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32);   /*  + 128: Compatible read */
1055         vga_wcrt (regbase, VGA_CRTC_H_BLANK_END, 128 + (regs.HorizBlankEnd % 32));
1056
1057         DPRINTK ("CRT4: %ld\n", regs.HorizSyncStart);
1058         vga_wcrt (regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
1059
1060         tmp = regs.HorizSyncEnd % 32;
1061         if (regs.HorizBlankEnd & 32)
1062                 tmp += 128;
1063         DPRINTK ("CRT5: %d\n", tmp);
1064         vga_wcrt (regbase, VGA_CRTC_H_SYNC_END, tmp);
1065
1066         DPRINTK ("CRT6: %ld\n", regs.VertTotal & 0xff);
1067         vga_wcrt (regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
1068
1069         tmp = 16;               /* LineCompare bit #9 */
1070         if (regs.VertTotal & 256)
1071                 tmp |= 1;
1072         if (regs.VertDispEnd & 256)
1073                 tmp |= 2;
1074         if (regs.VertSyncStart & 256)
1075                 tmp |= 4;
1076         if (regs.VertBlankStart & 256)
1077                 tmp |= 8;
1078         if (regs.VertTotal & 512)
1079                 tmp |= 32;
1080         if (regs.VertDispEnd & 512)
1081                 tmp |= 64;
1082         if (regs.VertSyncStart & 512)
1083                 tmp |= 128;
1084         DPRINTK ("CRT7: %d\n", tmp);
1085         vga_wcrt (regbase, VGA_CRTC_OVERFLOW, tmp);
1086
1087         tmp = 0x40;             /* LineCompare bit #8 */
1088         if (regs.VertBlankStart & 512)
1089                 tmp |= 0x20;
1090         if (var->vmode & FB_VMODE_DOUBLE)
1091                 tmp |= 0x80;
1092         DPRINTK ("CRT9: %d\n", tmp);
1093         vga_wcrt (regbase, VGA_CRTC_MAX_SCAN, tmp);
1094
1095         DPRINTK ("CRT10: %ld\n", regs.VertSyncStart & 0xff);
1096         vga_wcrt (regbase, VGA_CRTC_V_SYNC_START, (regs.VertSyncStart & 0xff));
1097
1098         DPRINTK ("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
1099         vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, (regs.VertSyncEnd % 16 + 64 + 32));
1100
1101         DPRINTK ("CRT12: %ld\n", regs.VertDispEnd & 0xff);
1102         vga_wcrt (regbase, VGA_CRTC_V_DISP_END, (regs.VertDispEnd & 0xff));
1103
1104         DPRINTK ("CRT15: %ld\n", regs.VertBlankStart & 0xff);
1105         vga_wcrt (regbase, VGA_CRTC_V_BLANK_START, (regs.VertBlankStart & 0xff));
1106
1107         DPRINTK ("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
1108         vga_wcrt (regbase, VGA_CRTC_V_BLANK_END, (regs.VertBlankEnd & 0xff));
1109
1110         DPRINTK ("CRT18: 0xff\n");
1111         vga_wcrt (regbase, VGA_CRTC_LINE_COMPARE, 0xff);
1112
1113         tmp = 0;
1114         if (var->vmode & FB_VMODE_INTERLACED)
1115                 tmp |= 1;
1116         if (regs.HorizBlankEnd & 64)
1117                 tmp |= 16;
1118         if (regs.HorizBlankEnd & 128)
1119                 tmp |= 32;
1120         if (regs.VertBlankEnd & 256)
1121                 tmp |= 64;
1122         if (regs.VertBlankEnd & 512)
1123                 tmp |= 128;
1124
1125         DPRINTK ("CRT1a: %d\n", tmp);
1126         vga_wcrt (regbase, CL_CRT1A, tmp);
1127
1128         /* set VCLK0 */
1129         /* hardware RefClock: 14.31818 MHz */
1130         /* formula: VClk = (OSC * N) / (D * (1+P)) */
1131         /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1132
1133         vga_wseq (regbase, CL_SEQRB, regs.nom);
1134         tmp = regs.den << 1;
1135         if (regs.div != 0)
1136                 tmp |= 1;
1137
1138         if ((cinfo->btype == BT_SD64) ||
1139             (cinfo->btype == BT_ALPINE) ||
1140             (cinfo->btype == BT_GD5480))
1141                 tmp |= 0x80;    /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1142
1143         DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp);
1144         vga_wseq (regbase, CL_SEQR1B, tmp);
1145
1146         if (regs.VertRes >= 1024)
1147                 /* 1280x1024 */
1148                 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc7);
1149         else
1150                 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
1151                  * address wrap, no compat. */
1152                 vga_wcrt (regbase, VGA_CRTC_MODE, 0xc3);
1153
1154 /* HAEH?        vga_wcrt (regbase, VGA_CRTC_V_SYNC_END, 0x20);  * previously: 0x00  unlock VGA_CRTC_H_TOTAL..CRT7 */
1155
1156         /* don't know if it would hurt to also program this if no interlaced */
1157         /* mode is used, but I feel better this way.. :-) */
1158         if (var->vmode & FB_VMODE_INTERLACED)
1159                 vga_wcrt (regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
1160         else
1161                 vga_wcrt (regbase, VGA_CRTC_REGS, 0x00);        /* interlace control */
1162
1163         vga_wseq (regbase, VGA_SEQ_CHARACTER_MAP, 0);
1164
1165         /* adjust horizontal/vertical sync type (low/high) */
1166         tmp = 0x03;             /* enable display memory & CRTC I/O address for color mode */
1167         if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1168                 tmp |= 0x40;
1169         if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1170                 tmp |= 0x80;
1171         WGen (cinfo, VGA_MIS_W, tmp);
1172
1173         vga_wcrt (regbase, VGA_CRTC_PRESET_ROW, 0);     /* Screen A Preset Row-Scan register */
1174         vga_wcrt (regbase, VGA_CRTC_CURSOR_START, 0);   /* text cursor on and start line */
1175         vga_wcrt (regbase, VGA_CRTC_CURSOR_END, 31);    /* text cursor end line */
1176
1177         /******************************************************
1178          *
1179          * 1 bpp
1180          *
1181          */
1182
1183         /* programming for different color depths */
1184         if (var->bits_per_pixel == 1) {
1185                 DPRINTK ("cirrusfb: preparing for 1 bit deep display\n");
1186                 vga_wgfx (regbase, VGA_GFX_MODE, 0);    /* mode register */
1187
1188                 /* SR07 */
1189                 switch (cinfo->btype) {
1190                 case BT_SD64:
1191                 case BT_PICCOLO:
1192                 case BT_PICASSO:
1193                 case BT_SPECTRUM:
1194                 case BT_PICASSO4:
1195                 case BT_ALPINE:
1196                 case BT_GD5480:
1197                         DPRINTK (" (for GD54xx)\n");
1198                         vga_wseq (regbase, CL_SEQR7,
1199                                   regs.multiplexing ?
1200                                         bi->sr07_1bpp_mux : bi->sr07_1bpp);
1201                         break;
1202
1203                 case BT_LAGUNA:
1204                         DPRINTK (" (for GD546x)\n");
1205                         vga_wseq (regbase, CL_SEQR7,
1206                                 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1207                         break;
1208
1209                 default:
1210                         printk (KERN_WARNING "cirrusfb: unknown Board\n");
1211                         break;
1212                 }
1213
1214                 /* Extended Sequencer Mode */
1215                 switch (cinfo->btype) {
1216                 case BT_SD64:
1217                         /* setting the SEQRF on SD64 is not necessary (only during init) */
1218                         DPRINTK ("(for SD64)\n");
1219                         vga_wseq (regbase, CL_SEQR1F, 0x1a);            /*  MCLK select */
1220                         break;
1221
1222                 case BT_PICCOLO:
1223                         DPRINTK ("(for Piccolo)\n");
1224 /* ### ueberall 0x22? */
1225                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* ##vorher 1c MCLK select */
1226                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1227                         break;
1228
1229                 case BT_PICASSO:
1230                         DPRINTK ("(for Picasso)\n");
1231                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* ##vorher 22 MCLK select */
1232                         vga_wseq (regbase, CL_SEQRF, 0xd0);     /* ## vorher d0 avoid FIFO underruns..? */
1233                         break;
1234
1235                 case BT_SPECTRUM:
1236                         DPRINTK ("(for Spectrum)\n");
1237 /* ### ueberall 0x22? */
1238                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* ##vorher 1c MCLK select */
1239                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* evtl d0? avoid FIFO underruns..? */
1240                         break;
1241
1242                 case BT_PICASSO4:
1243                 case BT_ALPINE:
1244                 case BT_GD5480:
1245                 case BT_LAGUNA:
1246                         DPRINTK (" (for GD54xx)\n");
1247                         /* do nothing */
1248                         break;
1249
1250                 default:
1251                         printk (KERN_WARNING "cirrusfb: unknown Board\n");
1252                         break;
1253                 }
1254
1255                 WGen (cinfo, VGA_PEL_MSK, 0x01);        /* pixel mask: pass-through for first plane */
1256                 if (regs.multiplexing)
1257                         WHDR (cinfo, 0x4a);     /* hidden dac reg: 1280x1024 */
1258                 else
1259                         WHDR (cinfo, 0);        /* hidden dac: nothing */
1260                 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x06);  /* memory mode: odd/even, ext. memory */
1261                 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0x01);  /* plane mask: only write to first plane */
1262                 offset = var->xres_virtual / 16;
1263         }
1264
1265         /******************************************************
1266          *
1267          * 8 bpp
1268          *
1269          */
1270
1271         else if (var->bits_per_pixel == 8) {
1272                 DPRINTK ("cirrusfb: preparing for 8 bit deep display\n");
1273                 switch (cinfo->btype) {
1274                 case BT_SD64:
1275                 case BT_PICCOLO:
1276                 case BT_PICASSO:
1277                 case BT_SPECTRUM:
1278                 case BT_PICASSO4:
1279                 case BT_ALPINE:
1280                 case BT_GD5480:
1281                         DPRINTK (" (for GD54xx)\n");
1282                         vga_wseq (regbase, CL_SEQR7,
1283                                   regs.multiplexing ?
1284                                         bi->sr07_8bpp_mux : bi->sr07_8bpp);
1285                         break;
1286
1287                 case BT_LAGUNA:
1288                         DPRINTK (" (for GD546x)\n");
1289                         vga_wseq (regbase, CL_SEQR7,
1290                                 vga_rseq (regbase, CL_SEQR7) | 0x01);
1291                         break;
1292
1293                 default:
1294                         printk (KERN_WARNING "cirrusfb: unknown Board\n");
1295                         break;
1296                 }
1297
1298                 switch (cinfo->btype) {
1299                 case BT_SD64:
1300                         vga_wseq (regbase, CL_SEQR1F, 0x1d);            /* MCLK select */
1301                         break;
1302
1303                 case BT_PICCOLO:
1304                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* ### vorher 1c MCLK select */
1305                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* Fast Page-Mode writes */
1306                         break;
1307
1308                 case BT_PICASSO:
1309                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* ### vorher 1c MCLK select */
1310                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* Fast Page-Mode writes */
1311                         break;
1312
1313                 case BT_SPECTRUM:
1314                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* ### vorher 1c MCLK select */
1315                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* Fast Page-Mode writes */
1316                         break;
1317
1318                 case BT_PICASSO4:
1319 #ifdef CONFIG_ZORRO
1320                         vga_wseq (regbase, CL_SEQRF, 0xb8);     /* ### INCOMPLETE!! */
1321 #endif
1322 /*          vga_wseq (regbase, CL_SEQR1F, 0x1c); */
1323                         break;
1324
1325                 case BT_ALPINE:
1326                         DPRINTK (" (for GD543x)\n");
1327                         cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1328                         /* We already set SRF and SR1F */
1329                         break;
1330
1331                 case BT_GD5480:
1332                 case BT_LAGUNA:
1333                         DPRINTK (" (for GD54xx)\n");
1334                         /* do nothing */
1335                         break;
1336
1337                 default:
1338                         printk (KERN_WARNING "cirrusfb: unknown Board\n");
1339                         break;
1340                 }
1341
1342                 vga_wgfx (regbase, VGA_GFX_MODE, 64);   /* mode register: 256 color mode */
1343                 WGen (cinfo, VGA_PEL_MSK, 0xff);        /* pixel mask: pass-through all planes */
1344                 if (regs.multiplexing)
1345                         WHDR (cinfo, 0x4a);     /* hidden dac reg: 1280x1024 */
1346                 else
1347                         WHDR (cinfo, 0);        /* hidden dac: nothing */
1348                 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a);  /* memory mode: chain4, ext. memory */
1349                 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff);  /* plane mask: enable writing to all 4 planes */
1350                 offset = var->xres_virtual / 8;
1351         }
1352
1353         /******************************************************
1354          *
1355          * 16 bpp
1356          *
1357          */
1358
1359         else if (var->bits_per_pixel == 16) {
1360                 DPRINTK ("cirrusfb: preparing for 16 bit deep display\n");
1361                 switch (cinfo->btype) {
1362                 case BT_SD64:
1363                         vga_wseq (regbase, CL_SEQR7, 0xf7);     /* Extended Sequencer Mode: 256c col. mode */
1364                         vga_wseq (regbase, CL_SEQR1F, 0x1e);            /* MCLK select */
1365                         break;
1366
1367                 case BT_PICCOLO:
1368                         vga_wseq (regbase, CL_SEQR7, 0x87);
1369                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* Fast Page-Mode writes */
1370                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* MCLK select */
1371                         break;
1372
1373                 case BT_PICASSO:
1374                         vga_wseq (regbase, CL_SEQR7, 0x27);
1375                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* Fast Page-Mode writes */
1376                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* MCLK select */
1377                         break;
1378
1379                 case BT_SPECTRUM:
1380                         vga_wseq (regbase, CL_SEQR7, 0x87);
1381                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* Fast Page-Mode writes */
1382                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* MCLK select */
1383                         break;
1384
1385                 case BT_PICASSO4:
1386                         vga_wseq (regbase, CL_SEQR7, 0x27);
1387 /*          vga_wseq (regbase, CL_SEQR1F, 0x1c);  */
1388                         break;
1389
1390                 case BT_ALPINE:
1391                         DPRINTK (" (for GD543x)\n");
1392                         if (regs.HorizRes >= 1024)
1393                                 vga_wseq (regbase, CL_SEQR7, 0xa7);
1394                         else
1395                                 vga_wseq (regbase, CL_SEQR7, 0xa3);
1396                         cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1397                         break;
1398
1399                 case BT_GD5480:
1400                         DPRINTK (" (for GD5480)\n");
1401                         vga_wseq (regbase, CL_SEQR7, 0x17);
1402                         /* We already set SRF and SR1F */
1403                         break;
1404
1405                 case BT_LAGUNA:
1406                         DPRINTK (" (for GD546x)\n");
1407                         vga_wseq (regbase, CL_SEQR7,
1408                                 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1409                         break;
1410
1411                 default:
1412                         printk (KERN_WARNING "CIRRUSFB: unknown Board\n");
1413                         break;
1414                 }
1415
1416                 vga_wgfx (regbase, VGA_GFX_MODE, 64);   /* mode register: 256 color mode */
1417                 WGen (cinfo, VGA_PEL_MSK, 0xff);        /* pixel mask: pass-through all planes */
1418 #ifdef CONFIG_PCI
1419                 WHDR (cinfo, 0xc0);     /* Copy Xbh */
1420 #elif defined(CONFIG_ZORRO)
1421                 /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1422                 WHDR (cinfo, 0xa0);     /* hidden dac reg: nothing special */
1423 #endif
1424                 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a);  /* memory mode: chain4, ext. memory */
1425                 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff);  /* plane mask: enable writing to all 4 planes */
1426                 offset = var->xres_virtual / 4;
1427         }
1428
1429         /******************************************************
1430          *
1431          * 32 bpp
1432          *
1433          */
1434
1435         else if (var->bits_per_pixel == 32) {
1436                 DPRINTK ("cirrusfb: preparing for 24/32 bit deep display\n");
1437                 switch (cinfo->btype) {
1438                 case BT_SD64:
1439                         vga_wseq (regbase, CL_SEQR7, 0xf9);     /* Extended Sequencer Mode: 256c col. mode */
1440                         vga_wseq (regbase, CL_SEQR1F, 0x1e);            /* MCLK select */
1441                         break;
1442
1443                 case BT_PICCOLO:
1444                         vga_wseq (regbase, CL_SEQR7, 0x85);
1445                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* Fast Page-Mode writes */
1446                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* MCLK select */
1447                         break;
1448
1449                 case BT_PICASSO:
1450                         vga_wseq (regbase, CL_SEQR7, 0x25);
1451                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* Fast Page-Mode writes */
1452                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* MCLK select */
1453                         break;
1454
1455                 case BT_SPECTRUM:
1456                         vga_wseq (regbase, CL_SEQR7, 0x85);
1457                         vga_wseq (regbase, CL_SEQRF, 0xb0);     /* Fast Page-Mode writes */
1458                         vga_wseq (regbase, CL_SEQR1F, 0x22);            /* MCLK select */
1459                         break;
1460
1461                 case BT_PICASSO4:
1462                         vga_wseq (regbase, CL_SEQR7, 0x25);
1463 /*          vga_wseq (regbase, CL_SEQR1F, 0x1c);  */
1464                         break;
1465
1466                 case BT_ALPINE:
1467                         DPRINTK (" (for GD543x)\n");
1468                         vga_wseq (regbase, CL_SEQR7, 0xa9);
1469                         cirrusfb_set_mclk (cinfo, regs.mclk, regs.divMCLK);
1470                         break;
1471
1472                 case BT_GD5480:
1473                         DPRINTK (" (for GD5480)\n");
1474                         vga_wseq (regbase, CL_SEQR7, 0x19);
1475                         /* We already set SRF and SR1F */
1476                         break;
1477
1478                 case BT_LAGUNA:
1479                         DPRINTK (" (for GD546x)\n");
1480                         vga_wseq (regbase, CL_SEQR7,
1481                                 vga_rseq (regbase, CL_SEQR7) & ~0x01);
1482                         break;
1483
1484                 default:
1485                         printk (KERN_WARNING "cirrusfb: unknown Board\n");
1486                         break;
1487                 }
1488
1489                 vga_wgfx (regbase, VGA_GFX_MODE, 64);   /* mode register: 256 color mode */
1490                 WGen (cinfo, VGA_PEL_MSK, 0xff);        /* pixel mask: pass-through all planes */
1491                 WHDR (cinfo, 0xc5);     /* hidden dac reg: 8-8-8 mode (24 or 32) */
1492                 vga_wseq (regbase, VGA_SEQ_MEMORY_MODE, 0x0a);  /* memory mode: chain4, ext. memory */
1493                 vga_wseq (regbase, VGA_SEQ_PLANE_WRITE, 0xff);  /* plane mask: enable writing to all 4 planes */
1494                 offset = var->xres_virtual / 4;
1495         }
1496
1497         /******************************************************
1498          *
1499          * unknown/unsupported bpp
1500          *
1501          */
1502
1503         else {
1504                 printk (KERN_ERR "cirrusfb: What's this?? requested color depth == %d.\n",
1505                         var->bits_per_pixel);
1506         }
1507
1508         vga_wcrt (regbase, VGA_CRTC_OFFSET, offset & 0xff);
1509         tmp = 0x22;
1510         if (offset & 0x100)
1511                 tmp |= 0x10;    /* offset overflow bit */
1512
1513         vga_wcrt (regbase, CL_CRT1B, tmp);      /* screen start addr #16-18, fastpagemode cycles */
1514
1515         if (cinfo->btype == BT_SD64 ||
1516             cinfo->btype == BT_PICASSO4 ||
1517             cinfo->btype == BT_ALPINE ||
1518             cinfo->btype == BT_GD5480)
1519                 vga_wcrt (regbase, CL_CRT1D, 0x00);     /* screen start address bit 19 */
1520
1521         vga_wcrt (regbase, VGA_CRTC_CURSOR_HI, 0);      /* text cursor location high */
1522         vga_wcrt (regbase, VGA_CRTC_CURSOR_LO, 0);      /* text cursor location low */
1523         vga_wcrt (regbase, VGA_CRTC_UNDERLINE, 0);      /* underline row scanline = at very bottom */
1524
1525         vga_wattr (regbase, VGA_ATC_MODE, 1);   /* controller mode */
1526         vga_wattr (regbase, VGA_ATC_OVERSCAN, 0);               /* overscan (border) color */
1527         vga_wattr (regbase, VGA_ATC_PLANE_ENABLE, 15);  /* color plane enable */
1528         vga_wattr (regbase, CL_AR33, 0);        /* pixel panning */
1529         vga_wattr (regbase, VGA_ATC_COLOR_PAGE, 0);     /* color select */
1530
1531         /* [ EGS: SetOffset(); ] */
1532         /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1533         AttrOn (cinfo);
1534
1535         vga_wgfx (regbase, VGA_GFX_SR_VALUE, 0);        /* set/reset register */
1536         vga_wgfx (regbase, VGA_GFX_SR_ENABLE, 0);               /* set/reset enable */
1537         vga_wgfx (regbase, VGA_GFX_COMPARE_VALUE, 0);   /* color compare */
1538         vga_wgfx (regbase, VGA_GFX_DATA_ROTATE, 0);     /* data rotate */
1539         vga_wgfx (regbase, VGA_GFX_PLANE_READ, 0);      /* read map select */
1540         vga_wgfx (regbase, VGA_GFX_MISC, 1);    /* miscellaneous register */
1541         vga_wgfx (regbase, VGA_GFX_COMPARE_MASK, 15);   /* color don't care */
1542         vga_wgfx (regbase, VGA_GFX_BIT_MASK, 255);      /* bit mask */
1543
1544         vga_wseq (regbase, CL_SEQR12, 0x0);     /* graphics cursor attributes: nothing special */
1545
1546         /* finally, turn on everything - turn off "FullBandwidth" bit */
1547         /* also, set "DotClock%2" bit where requested */
1548         tmp = 0x01;
1549
1550 /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1551     if (var->vmode & FB_VMODE_CLOCK_HALVE)
1552         tmp |= 0x08;
1553 */
1554
1555         vga_wseq (regbase, VGA_SEQ_CLOCK_MODE, tmp);
1556         DPRINTK ("CL_SEQR1: %d\n", tmp);
1557
1558         cinfo->currentmode = regs;
1559         info->fix.type = regs.type;
1560         info->fix.visual = regs.visual;
1561         info->fix.line_length = regs.line_length;
1562
1563         /* pan to requested offset */
1564         cirrusfb_pan_display (var, info);
1565
1566 #ifdef CIRRUSFB_DEBUG
1567         cirrusfb_dump ();
1568 #endif
1569
1570         DPRINTK ("EXIT\n");
1571         return 0;
1572 }
1573
1574 /* for some reason incomprehensible to me, cirrusfb requires that you write
1575  * the registers twice for the settings to take..grr. -dte */
1576 static int cirrusfb_set_par (struct fb_info *info)
1577 {
1578         cirrusfb_set_par_foo (info);
1579         return cirrusfb_set_par_foo (info);
1580 }
1581
1582 static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
1583                                unsigned blue, unsigned transp,
1584                                struct fb_info *info)
1585 {
1586         struct cirrusfb_info *cinfo = info->par;
1587
1588         if (regno > 255)
1589                 return -EINVAL;
1590
1591         if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1592                 u32 v;
1593                 red >>= (16 - info->var.red.length);
1594                 green >>= (16 - info->var.green.length);
1595                 blue >>= (16 - info->var.blue.length);
1596
1597                 if (regno>=16)
1598                         return 1;
1599                 v = (red << info->var.red.offset) |
1600                     (green << info->var.green.offset) |
1601                     (blue << info->var.blue.offset);
1602
1603                 switch (info->var.bits_per_pixel) {
1604                         case 8:
1605                                 cinfo->pseudo_palette[regno] = v;
1606                                 break;
1607                         case 16:
1608                                 cinfo->pseudo_palette[regno] = v;
1609                                 break;
1610                         case 24:
1611                         case 32:
1612                                 cinfo->pseudo_palette[regno] = v;
1613                                 break;
1614                 }
1615                 return 0;
1616         }
1617
1618         cinfo->palette[regno].red = red;
1619         cinfo->palette[regno].green = green;
1620         cinfo->palette[regno].blue = blue;
1621
1622         if (info->var.bits_per_pixel == 8) {
1623                         WClut (cinfo, regno, red >> 10, green >> 10, blue >> 10);
1624         }
1625
1626         return 0;
1627
1628 }
1629
1630 /*************************************************************************
1631         cirrusfb_pan_display()
1632
1633         performs display panning - provided hardware permits this
1634 **************************************************************************/
1635 static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
1636                                  struct fb_info *info)
1637 {
1638         int xoffset = 0;
1639         int yoffset = 0;
1640         unsigned long base;
1641         unsigned char tmp = 0, tmp2 = 0, xpix;
1642         struct cirrusfb_info *cinfo = info->par;
1643
1644         DPRINTK ("ENTER\n");
1645         DPRINTK ("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset);
1646
1647         /* no range checks for xoffset and yoffset,   */
1648         /* as fb_pan_display has already done this */
1649         if (var->vmode & FB_VMODE_YWRAP)
1650                 return -EINVAL;
1651
1652         info->var.xoffset = var->xoffset;
1653         info->var.yoffset = var->yoffset;
1654
1655         xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1656         yoffset = var->yoffset;
1657
1658         base = yoffset * cinfo->currentmode.line_length + xoffset;
1659
1660         if (info->var.bits_per_pixel == 1) {
1661                 /* base is already correct */
1662                 xpix = (unsigned char) (var->xoffset % 8);
1663         } else {
1664                 base /= 4;
1665                 xpix = (unsigned char) ((xoffset % 4) * 2);
1666         }
1667
1668         cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */
1669
1670         /* lower 8 + 8 bits of screen start address */
1671         vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
1672         vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
1673
1674         /* construct bits 16, 17 and 18 of screen start address */
1675         if (base & 0x10000)
1676                 tmp |= 0x01;
1677         if (base & 0x20000)
1678                 tmp |= 0x04;
1679         if (base & 0x40000)
1680                 tmp |= 0x08;
1681
1682         tmp2 = (vga_rcrt (cinfo->regbase, CL_CRT1B) & 0xf2) | tmp;      /* 0xf2 is %11110010, exclude tmp bits */
1683         vga_wcrt (cinfo->regbase, CL_CRT1B, tmp2);
1684
1685         /* construct bit 19 of screen start address */
1686         if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
1687                 tmp2 = 0;
1688                 if (base & 0x80000)
1689                         tmp2 = 0x80;
1690                 vga_wcrt (cinfo->regbase, CL_CRT1D, tmp2);
1691         }
1692
1693         /* write pixel panning value to AR33; this does not quite work in 8bpp */
1694         /* ### Piccolo..? Will this work? */
1695         if (info->var.bits_per_pixel == 1)
1696                 vga_wattr (cinfo->regbase, CL_AR33, xpix);
1697
1698         cirrusfb_WaitBLT (cinfo->regbase);
1699
1700         DPRINTK ("EXIT\n");
1701         return (0);
1702 }
1703
1704
1705 static int cirrusfb_blank (int blank_mode, struct fb_info *info)
1706 {
1707         /*
1708          *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1709          *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
1710          *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
1711          *  to e.g. a video mode which doesn't support it. Implements VESA suspend
1712          *  and powerdown modes on hardware that supports disabling hsync/vsync:
1713          *    blank_mode == 2: suspend vsync
1714          *    blank_mode == 3: suspend hsync
1715          *    blank_mode == 4: powerdown
1716          */
1717         unsigned char val;
1718         struct cirrusfb_info *cinfo = info->par;
1719         int current_mode = cinfo->blank_mode;
1720
1721         DPRINTK ("ENTER, blank mode = %d\n", blank_mode);
1722
1723         if (info->state != FBINFO_STATE_RUNNING ||
1724             current_mode == blank_mode) {
1725                 DPRINTK ("EXIT, returning 0\n");
1726                 return 0;
1727         }
1728
1729         /* Undo current */
1730         if (current_mode == FB_BLANK_NORMAL ||
1731             current_mode == FB_BLANK_UNBLANK) {
1732                 /* unblank the screen */
1733                 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1734                 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);      /* clear "FullBandwidth" bit */
1735                 /* and undo VESA suspend trickery */
1736                 vga_wgfx (cinfo->regbase, CL_GRE, 0x00);
1737         }
1738
1739         /* set new */
1740         if(blank_mode > FB_BLANK_NORMAL) {
1741                 /* blank the screen */
1742                 val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
1743                 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);      /* set "FullBandwidth" bit */
1744         }
1745
1746         switch (blank_mode) {
1747         case FB_BLANK_UNBLANK:
1748         case FB_BLANK_NORMAL:
1749                 break;
1750         case FB_BLANK_VSYNC_SUSPEND:
1751                 vga_wgfx (cinfo->regbase, CL_GRE, 0x04);
1752                 break;
1753         case FB_BLANK_HSYNC_SUSPEND:
1754                 vga_wgfx (cinfo->regbase, CL_GRE, 0x02);
1755                 break;
1756         case FB_BLANK_POWERDOWN:
1757                 vga_wgfx (cinfo->regbase, CL_GRE, 0x06);
1758                 break;
1759         default:
1760                 DPRINTK ("EXIT, returning 1\n");
1761                 return 1;
1762         }
1763
1764         cinfo->blank_mode = blank_mode;
1765         DPRINTK ("EXIT, returning 0\n");
1766
1767         /* Let fbcon do a soft blank for us */
1768         return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
1769 }
1770 /**** END   Hardware specific Routines **************************************/
1771 /****************************************************************************/
1772 /**** BEGIN Internal Routines ***********************************************/
1773
1774 static void init_vgachip (struct cirrusfb_info *cinfo)
1775 {
1776         const struct cirrusfb_board_info_rec *bi;
1777
1778         DPRINTK ("ENTER\n");
1779
1780         assert (cinfo != NULL);
1781
1782         bi = &cirrusfb_board_info[cinfo->btype];
1783
1784         /* reset board globally */
1785         switch (cinfo->btype) {
1786         case BT_PICCOLO:
1787                 WSFR (cinfo, 0x01);
1788                 udelay (500);
1789                 WSFR (cinfo, 0x51);
1790                 udelay (500);
1791                 break;
1792         case BT_PICASSO:
1793                 WSFR2 (cinfo, 0xff);
1794                 udelay (500);
1795                 break;
1796         case BT_SD64:
1797         case BT_SPECTRUM:
1798                 WSFR (cinfo, 0x1f);
1799                 udelay (500);
1800                 WSFR (cinfo, 0x4f);
1801                 udelay (500);
1802                 break;
1803         case BT_PICASSO4:
1804                 vga_wcrt (cinfo->regbase, CL_CRT51, 0x00);      /* disable flickerfixer */
1805                 mdelay (100);
1806                 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00);       /* from Klaus' NetBSD driver: */
1807                 vga_wgfx (cinfo->regbase, CL_GR33, 0x00);       /* put blitter into 542x compat */
1808                 vga_wgfx (cinfo->regbase, CL_GR31, 0x00);       /* mode */
1809                 break;
1810
1811         case BT_GD5480:
1812                 vga_wgfx (cinfo->regbase, CL_GR2F, 0x00);       /* from Klaus' NetBSD driver: */
1813                 break;
1814
1815         case BT_ALPINE:
1816                 /* Nothing to do to reset the board. */
1817                 break;
1818
1819         default:
1820                 printk (KERN_ERR "cirrusfb: Warning: Unknown board type\n");
1821                 break;
1822         }
1823
1824         assert (cinfo->size > 0); /* make sure RAM size set by this point */
1825
1826         /* the P4 is not fully initialized here; I rely on it having been */
1827         /* inited under AmigaOS already, which seems to work just fine    */
1828         /* (Klaus advised to do it this way)                              */
1829
1830         if (cinfo->btype != BT_PICASSO4) {
1831                 WGen (cinfo, CL_VSSM, 0x10);    /* EGS: 0x16 */
1832                 WGen (cinfo, CL_POS102, 0x01);
1833                 WGen (cinfo, CL_VSSM, 0x08);    /* EGS: 0x0e */
1834
1835                 if (cinfo->btype != BT_SD64)
1836                         WGen (cinfo, CL_VSSM2, 0x01);
1837
1838                 vga_wseq (cinfo->regbase, CL_SEQR0, 0x03);      /* reset sequencer logic */
1839
1840                 vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);    /* FullBandwidth (video off) and 8/9 dot clock */
1841                 WGen (cinfo, VGA_MIS_W, 0xc1);  /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
1842
1843 /*      vga_wgfx (cinfo->regbase, CL_GRA, 0xce);    "magic cookie" - doesn't make any sense to me.. */
1844                 vga_wseq (cinfo->regbase, CL_SEQR6, 0x12);      /* unlock all extension registers */
1845
1846                 vga_wgfx (cinfo->regbase, CL_GR31, 0x04);       /* reset blitter */
1847
1848                 switch (cinfo->btype) {
1849                 case BT_GD5480:
1850                         vga_wseq (cinfo->regbase, CL_SEQRF, 0x98);
1851                         break;
1852                 case BT_ALPINE:
1853                         break;
1854                 case BT_SD64:
1855                         vga_wseq (cinfo->regbase, CL_SEQRF, 0xb8);
1856                         break;
1857                 default:
1858                         vga_wseq (cinfo->regbase, CL_SEQR16, 0x0f);
1859                         vga_wseq (cinfo->regbase, CL_SEQRF, 0xb0);
1860                         break;
1861                 }
1862         }
1863         vga_wseq (cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);   /* plane mask: nothing */
1864         vga_wseq (cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */
1865         vga_wseq (cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e);   /* memory mode: chain-4, no odd/even, ext. memory */
1866
1867         /* controller-internal base address of video memory */
1868         if (bi->init_sr07)
1869                 vga_wseq (cinfo->regbase, CL_SEQR7, bi->sr07);
1870
1871         /*  vga_wseq (cinfo->regbase, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
1872
1873         vga_wseq (cinfo->regbase, CL_SEQR10, 0x00);             /* graphics cursor X position (incomplete; position gives rem. 3 bits */
1874         vga_wseq (cinfo->regbase, CL_SEQR11, 0x00);             /* graphics cursor Y position (..."... ) */
1875         vga_wseq (cinfo->regbase, CL_SEQR12, 0x00);             /* graphics cursor attributes */
1876         vga_wseq (cinfo->regbase, CL_SEQR13, 0x00);             /* graphics cursor pattern address */
1877
1878         /* writing these on a P4 might give problems..  */
1879         if (cinfo->btype != BT_PICASSO4) {
1880                 vga_wseq (cinfo->regbase, CL_SEQR17, 0x00);             /* configuration readback and ext. color */
1881                 vga_wseq (cinfo->regbase, CL_SEQR18, 0x02);             /* signature generator */
1882         }
1883
1884         /* MCLK select etc. */
1885         if (bi->init_sr1f)
1886                 vga_wseq (cinfo->regbase, CL_SEQR1F, bi->sr1f);
1887
1888         vga_wcrt (cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);   /* Screen A preset row scan: none */
1889         vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */
1890         vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);   /* Text cursor end: - */
1891         vga_wcrt (cinfo->regbase, VGA_CRTC_START_HI, 0x00);     /* Screen start address high: 0 */
1892         vga_wcrt (cinfo->regbase, VGA_CRTC_START_LO, 0x00);     /* Screen start address low: 0 */
1893         vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);    /* text cursor location high: 0 */
1894         vga_wcrt (cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);    /* text cursor location low: 0 */
1895
1896         vga_wcrt (cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);    /* Underline Row scanline: - */
1897         vga_wcrt (cinfo->regbase, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */
1898         vga_wcrt (cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */
1899         /* ### add 0x40 for text modes with > 30 MHz pixclock */
1900         vga_wcrt (cinfo->regbase, CL_CRT1B, 0x02);      /* ext. display controls: ext.adr. wrap */
1901
1902         vga_wgfx (cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);      /* Set/Reset registes: - */
1903         vga_wgfx (cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);     /* Set/Reset enable: - */
1904         vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */
1905         vga_wgfx (cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);   /* Data Rotate: - */
1906         vga_wgfx (cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);    /* Read Map Select: - */
1907         vga_wgfx (cinfo->regbase, VGA_GFX_MODE, 0x00);  /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
1908         vga_wgfx (cinfo->regbase, VGA_GFX_MISC, 0x01);  /* Miscellaneous: memory map base address, graphics mode */
1909         vga_wgfx (cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);  /* Color Don't care: involve all planes */
1910         vga_wgfx (cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);      /* Bit Mask: no mask at all */
1911         if (cinfo->btype == BT_ALPINE)
1912                 vga_wgfx (cinfo->regbase, CL_GRB, 0x20);        /* (5434 can't have bit 3 set for bitblt) */
1913         else
1914                 vga_wgfx (cinfo->regbase, CL_GRB, 0x28);        /* Graphics controller mode extensions: finer granularity, 8byte data latches */
1915
1916         vga_wgfx (cinfo->regbase, CL_GRC, 0xff);        /* Color Key compare: - */
1917         vga_wgfx (cinfo->regbase, CL_GRD, 0x00);        /* Color Key compare mask: - */
1918         vga_wgfx (cinfo->regbase, CL_GRE, 0x00);        /* Miscellaneous control: - */
1919         /*  vga_wgfx (cinfo->regbase, CL_GR10, 0x00); *//* Background color byte 1: - */
1920 /*  vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
1921
1922         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE0, 0x00);     /* Attribute Controller palette registers: "identity mapping" */
1923         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
1924         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
1925         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
1926         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
1927         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
1928         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
1929         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
1930         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
1931         vga_wattr (cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
1932         vga_wattr (cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
1933         vga_wattr (cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
1934         vga_wattr (cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
1935         vga_wattr (cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
1936         vga_wattr (cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
1937         vga_wattr (cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
1938
1939         vga_wattr (cinfo->regbase, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */
1940         vga_wattr (cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);     /* Overscan color reg.: reg. 0 */
1941         vga_wattr (cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */
1942 /* ###  vga_wattr (cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */
1943         vga_wattr (cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);   /* Color Select: - */
1944
1945         WGen (cinfo, VGA_PEL_MSK, 0xff);        /* Pixel mask: no mask */
1946
1947         if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1948                 WGen (cinfo, VGA_MIS_W, 0xc3);  /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
1949
1950         vga_wgfx (cinfo->regbase, CL_GR31, 0x04);       /* BLT Start/status: Blitter reset */
1951         vga_wgfx (cinfo->regbase, CL_GR31, 0x00);       /* - " -           : "end-of-reset" */
1952
1953         /* misc... */
1954         WHDR (cinfo, 0);        /* Hidden DAC register: - */
1955
1956         printk (KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n", cinfo->size);
1957         DPRINTK ("EXIT\n");
1958         return;
1959 }
1960
1961 static void switch_monitor (struct cirrusfb_info *cinfo, int on)
1962 {
1963 #ifdef CONFIG_ZORRO /* only works on Zorro boards */
1964         static int IsOn = 0;    /* XXX not ok for multiple boards */
1965
1966         DPRINTK ("ENTER\n");
1967
1968         if (cinfo->btype == BT_PICASSO4)
1969                 return;         /* nothing to switch */
1970         if (cinfo->btype == BT_ALPINE)
1971                 return;         /* nothing to switch */
1972         if (cinfo->btype == BT_GD5480)
1973                 return;         /* nothing to switch */
1974         if (cinfo->btype == BT_PICASSO) {
1975                 if ((on && !IsOn) || (!on && IsOn))
1976                         WSFR (cinfo, 0xff);
1977
1978                 DPRINTK ("EXIT\n");
1979                 return;
1980         }
1981         if (on) {
1982                 switch (cinfo->btype) {
1983                 case BT_SD64:
1984                         WSFR (cinfo, cinfo->SFR | 0x21);
1985                         break;
1986                 case BT_PICCOLO:
1987                         WSFR (cinfo, cinfo->SFR | 0x28);
1988                         break;
1989                 case BT_SPECTRUM:
1990                         WSFR (cinfo, 0x6f);
1991                         break;
1992                 default: /* do nothing */ break;
1993                 }
1994         } else {
1995                 switch (cinfo->btype) {
1996                 case BT_SD64:
1997                         WSFR (cinfo, cinfo->SFR & 0xde);
1998                         break;
1999                 case BT_PICCOLO:
2000                         WSFR (cinfo, cinfo->SFR & 0xd7);
2001                         break;
2002                 case BT_SPECTRUM:
2003                         WSFR (cinfo, 0x4f);
2004                         break;
2005                 default: /* do nothing */ break;
2006                 }
2007         }
2008
2009         DPRINTK ("EXIT\n");
2010 #endif /* CONFIG_ZORRO */
2011 }
2012
2013
2014 /******************************************/
2015 /* Linux 2.6-style  accelerated functions */
2016 /******************************************/
2017
2018 static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo,
2019                                    const struct fb_fillrect *region)
2020 {
2021         int m; /* bytes per pixel */
2022         u32 color = (cinfo->info->fix.visual == FB_VISUAL_TRUECOLOR) ?
2023                 cinfo->pseudo_palette[region->color] : region->color;
2024
2025         if(cinfo->info->var.bits_per_pixel == 1) {
2026                 cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2027                                   region->dx / 8, region->dy,
2028                                   region->width / 8, region->height,
2029                                   color,
2030                                   cinfo->currentmode.line_length);
2031         } else {
2032                 m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8;
2033                 cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2034                                   region->dx * m, region->dy,
2035                                   region->width * m, region->height,
2036                                   color,
2037                                   cinfo->currentmode.line_length);
2038         }
2039         return;
2040 }
2041
2042 static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region)
2043 {
2044         struct cirrusfb_info *cinfo = info->par;
2045         struct fb_fillrect modded;
2046         int vxres, vyres;
2047
2048         if (info->state != FBINFO_STATE_RUNNING)
2049                 return;
2050         if (info->flags & FBINFO_HWACCEL_DISABLED) {
2051                 cfb_fillrect(info, region);
2052                 return;
2053         }
2054
2055         vxres = info->var.xres_virtual;
2056         vyres = info->var.yres_virtual;
2057
2058         memcpy(&modded, region, sizeof(struct fb_fillrect));
2059
2060         if(!modded.width || !modded.height ||
2061            modded.dx >= vxres || modded.dy >= vyres)
2062                 return;
2063
2064         if(modded.dx + modded.width  > vxres) modded.width  = vxres - modded.dx;
2065         if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
2066
2067         cirrusfb_prim_fillrect(cinfo, &modded);
2068 }
2069
2070 static void cirrusfb_prim_copyarea(struct cirrusfb_info *cinfo,
2071                                    const struct fb_copyarea *area)
2072 {
2073         int m; /* bytes per pixel */
2074         if(cinfo->info->var.bits_per_pixel == 1) {
2075                 cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2076                                 area->sx / 8, area->sy,
2077                                 area->dx / 8, area->dy,
2078                                 area->width / 8, area->height,
2079                                 cinfo->currentmode.line_length);
2080         } else {
2081                 m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8;
2082                 cirrusfb_BitBLT(cinfo->regbase, cinfo->info->var.bits_per_pixel,
2083                                 area->sx * m, area->sy,
2084                                 area->dx * m, area->dy,
2085                                 area->width * m, area->height,
2086                                 cinfo->currentmode.line_length);
2087         }
2088         return;
2089 }
2090
2091
2092 static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2093 {
2094         struct cirrusfb_info *cinfo = info->par;
2095         struct fb_copyarea modded;
2096         u32 vxres, vyres;
2097         modded.sx = area->sx;
2098         modded.sy = area->sy;
2099         modded.dx = area->dx;
2100         modded.dy = area->dy;
2101         modded.width  = area->width;
2102         modded.height = area->height;
2103
2104         if (info->state != FBINFO_STATE_RUNNING)
2105                 return;
2106         if (info->flags & FBINFO_HWACCEL_DISABLED) {
2107                 cfb_copyarea(info, area);
2108                 return;
2109         }
2110
2111         vxres = info->var.xres_virtual;
2112         vyres = info->var.yres_virtual;
2113
2114         if(!modded.width || !modded.height ||
2115            modded.sx >= vxres || modded.sy >= vyres ||
2116            modded.dx >= vxres || modded.dy >= vyres)
2117                 return;
2118
2119         if(modded.sx + modded.width > vxres)  modded.width = vxres - modded.sx;
2120         if(modded.dx + modded.width > vxres)  modded.width = vxres - modded.dx;
2121         if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy;
2122         if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
2123
2124         cirrusfb_prim_copyarea(cinfo, &modded);
2125 }
2126
2127 static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image)
2128 {
2129         struct cirrusfb_info *cinfo = info->par;
2130
2131         cirrusfb_WaitBLT(cinfo->regbase);
2132         cfb_imageblit(info, image);
2133 }
2134
2135
2136 #ifdef CONFIG_PPC_PREP
2137 #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
2138 #define PREP_IO_BASE    ((volatile unsigned char *) 0x80000000)
2139 static void get_prep_addrs (unsigned long *display, unsigned long *registers)
2140 {
2141         DPRINTK ("ENTER\n");
2142
2143         *display = PREP_VIDEO_BASE;
2144         *registers = (unsigned long) PREP_IO_BASE;
2145
2146         DPRINTK ("EXIT\n");
2147 }
2148
2149 #endif                          /* CONFIG_PPC_PREP */
2150
2151
2152 #ifdef CONFIG_PCI
2153 static int release_io_ports = 0;
2154
2155 /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
2156  * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
2157  * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2158  * seem to have. */
2159 static unsigned int cirrusfb_get_memsize (u8 __iomem *regbase)
2160 {
2161         unsigned long mem;
2162         unsigned char SRF;
2163
2164         DPRINTK ("ENTER\n");
2165
2166         SRF = vga_rseq (regbase, CL_SEQRF);
2167         switch ((SRF & 0x18)) {
2168             case 0x08: mem = 512 * 1024; break;
2169             case 0x10: mem = 1024 * 1024; break;
2170                 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2171                    * on the 5430. */
2172             case 0x18: mem = 2048 * 1024; break;
2173             default: printk ("CLgenfb: Unknown memory size!\n");
2174                 mem = 1024 * 1024;
2175         }
2176         if (SRF & 0x80) {
2177                 /* If DRAM bank switching is enabled, there must be twice as much
2178                    * memory installed. (4MB on the 5434) */
2179                 mem *= 2;
2180         }
2181         /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
2182
2183         DPRINTK ("EXIT\n");
2184         return mem;
2185 }
2186
2187
2188
2189 static void get_pci_addrs (const struct pci_dev *pdev,
2190                            unsigned long *display, unsigned long *registers)
2191 {
2192         assert (pdev != NULL);
2193         assert (display != NULL);
2194         assert (registers != NULL);
2195
2196         DPRINTK ("ENTER\n");
2197
2198         *display = 0;
2199         *registers = 0;
2200
2201         /* This is a best-guess for now */
2202
2203         if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2204                 *display = pci_resource_start(pdev, 1);
2205                 *registers = pci_resource_start(pdev, 0);
2206         } else {
2207                 *display = pci_resource_start(pdev, 0);
2208                 *registers = pci_resource_start(pdev, 1);
2209         }
2210
2211         assert (*display != 0);
2212
2213         DPRINTK ("EXIT\n");
2214 }
2215
2216
2217 static void cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
2218 {
2219         struct pci_dev *pdev = cinfo->pdev;
2220
2221         iounmap(cinfo->fbmem);
2222 #if 0 /* if system didn't claim this region, we would... */
2223         release_mem_region(0xA0000, 65535);
2224 #endif
2225         if (release_io_ports)
2226                 release_region(0x3C0, 32);
2227         pci_release_regions(pdev);
2228         framebuffer_release(cinfo->info);
2229 }
2230 #endif /* CONFIG_PCI */
2231
2232
2233 #ifdef CONFIG_ZORRO
2234 static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
2235 {
2236         zorro_release_device(cinfo->zdev);
2237
2238         if (cinfo->btype == BT_PICASSO4) {
2239                 cinfo->regbase -= 0x600000;
2240                 iounmap ((void *)cinfo->regbase);
2241                 iounmap ((void *)cinfo->fbmem);
2242         } else {
2243                 if (zorro_resource_start(cinfo->zdev) > 0x01000000)
2244                         iounmap ((void *)cinfo->fbmem);
2245         }
2246         framebuffer_release(cinfo->info);
2247 }
2248 #endif /* CONFIG_ZORRO */
2249
2250 static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
2251 {
2252         struct fb_info *info = cinfo->info;
2253         struct fb_var_screeninfo *var = &info->var;
2254
2255         info->par = cinfo;
2256         info->pseudo_palette = cinfo->pseudo_palette;
2257         info->flags = FBINFO_DEFAULT
2258                     | FBINFO_HWACCEL_XPAN
2259                     | FBINFO_HWACCEL_YPAN
2260                     | FBINFO_HWACCEL_FILLRECT
2261                     | FBINFO_HWACCEL_COPYAREA;
2262         if (noaccel)
2263                 info->flags |= FBINFO_HWACCEL_DISABLED;
2264         info->fbops = &cirrusfb_ops;
2265         info->screen_base = cinfo->fbmem;
2266         if (cinfo->btype == BT_GD5480) {
2267                 if (var->bits_per_pixel == 16)
2268                         info->screen_base += 1 * MB_;
2269                 if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
2270                         info->screen_base += 2 * MB_;
2271         }
2272
2273         /* Fill fix common fields */
2274         strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
2275                 sizeof(info->fix.id));
2276
2277         /* monochrome: only 1 memory plane */
2278         /* 8 bit and above: Use whole memory area */
2279         info->fix.smem_start = cinfo->fbmem_phys;
2280         info->fix.smem_len   = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size;
2281         info->fix.type       = cinfo->currentmode.type;
2282         info->fix.type_aux   = 0;
2283         info->fix.visual     = cinfo->currentmode.visual;
2284         info->fix.xpanstep   = 1;
2285         info->fix.ypanstep   = 1;
2286         info->fix.ywrapstep  = 0;
2287         info->fix.line_length = cinfo->currentmode.line_length;
2288
2289         /* FIXME: map region at 0xB8000 if available, fill in here */
2290         info->fix.mmio_start = cinfo->fbregs_phys;
2291         info->fix.mmio_len   = 0;
2292         info->fix.accel = FB_ACCEL_NONE;
2293
2294         fb_alloc_cmap(&info->cmap, 256, 0);
2295
2296         return 0;
2297 }
2298
2299 static int cirrusfb_register(struct cirrusfb_info *cinfo)
2300 {
2301         struct fb_info *info;
2302         int err;
2303         cirrusfb_board_t btype;
2304
2305         DPRINTK ("ENTER\n");
2306
2307         printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n");
2308
2309         info = cinfo->info;
2310         btype = cinfo->btype;
2311
2312         /* sanity checks */
2313         assert (btype != BT_NONE);
2314
2315         DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem);
2316
2317         /* Make pretend we've set the var so our structures are in a "good" */
2318         /* state, even though we haven't written the mode to the hw yet...  */
2319         info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
2320         info->var.activate = FB_ACTIVATE_NOW;
2321
2322         err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2323         if (err < 0) {
2324                 /* should never happen */
2325                 DPRINTK("choking on default var... umm, no good.\n");
2326                 goto err_unmap_cirrusfb;
2327         }
2328
2329         /* set all the vital stuff */
2330         cirrusfb_set_fbinfo(cinfo);
2331
2332         err = register_framebuffer(info);
2333         if (err < 0) {
2334                 printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err);
2335                 goto err_dealloc_cmap;
2336         }
2337
2338         DPRINTK ("EXIT, returning 0\n");
2339         return 0;
2340
2341 err_dealloc_cmap:
2342         fb_dealloc_cmap(&info->cmap);
2343 err_unmap_cirrusfb:
2344         cinfo->unmap(cinfo);
2345         return err;
2346 }
2347
2348 static void __devexit cirrusfb_cleanup (struct fb_info *info)
2349 {
2350         struct cirrusfb_info *cinfo = info->par;
2351         DPRINTK ("ENTER\n");
2352
2353         switch_monitor (cinfo, 0);
2354
2355         unregister_framebuffer (info);
2356         fb_dealloc_cmap (&info->cmap);
2357         printk ("Framebuffer unregistered\n");
2358         cinfo->unmap(cinfo);
2359
2360         DPRINTK ("EXIT\n");
2361 }
2362
2363
2364 #ifdef CONFIG_PCI
2365 static int cirrusfb_pci_register (struct pci_dev *pdev,
2366                                   const struct pci_device_id *ent)
2367 {
2368         struct cirrusfb_info *cinfo;
2369         struct fb_info *info;
2370         cirrusfb_board_t btype;
2371         unsigned long board_addr, board_size;
2372         int ret;
2373
2374         ret = pci_enable_device(pdev);
2375         if (ret < 0) {
2376                 printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
2377                 goto err_out;
2378         }
2379
2380         info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
2381         if (!info) {
2382                 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2383                 ret = -ENOMEM;
2384                 goto err_disable;
2385         }
2386
2387         cinfo = info->par;
2388         cinfo->info = info;
2389         cinfo->pdev = pdev;
2390         cinfo->btype = btype = (cirrusfb_board_t) ent->driver_data;
2391
2392         DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n",
2393                 pdev->resource[0].start, btype);
2394         DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start);
2395
2396         if(isPReP) {
2397                 pci_write_config_dword (pdev, PCI_BASE_ADDRESS_0, 0x00000000);
2398 #ifdef CONFIG_PPC_PREP
2399                 get_prep_addrs (&board_addr, &cinfo->fbregs_phys);
2400 #endif
2401                 /* PReP dies if we ioremap the IO registers, but it works w/out... */
2402                 cinfo->regbase = (char __iomem *) cinfo->fbregs_phys;
2403         } else {
2404                 DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
2405                 get_pci_addrs (pdev, &board_addr, &cinfo->fbregs_phys);
2406                 cinfo->regbase = NULL;          /* FIXME: this forces VGA.  alternatives? */
2407         }
2408
2409         DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, cinfo->fbregs_phys);
2410
2411         board_size = (btype == BT_GD5480) ?
2412                 32 * MB_ : cirrusfb_get_memsize (cinfo->regbase);
2413
2414         ret = pci_request_regions(pdev, "cirrusfb");
2415         if (ret <0) {
2416                 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
2417                        board_addr);
2418                 goto err_release_fb;
2419         }
2420 #if 0 /* if the system didn't claim this region, we would... */
2421         if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
2422                 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n"
2423 ,
2424                        0xA0000L);
2425                 ret = -EBUSY;
2426                 goto err_release_regions;
2427         }
2428 #endif
2429         if (request_region(0x3C0, 32, "cirrusfb"))
2430                 release_io_ports = 1;
2431
2432         cinfo->fbmem = ioremap(board_addr, board_size);
2433         if (!cinfo->fbmem) {
2434                 ret = -EIO;
2435                 goto err_release_legacy;
2436         }
2437
2438         cinfo->fbmem_phys = board_addr;
2439         cinfo->size = board_size;
2440         cinfo->unmap = cirrusfb_pci_unmap;
2441
2442         printk (" RAM (%lu kB) at 0xx%lx, ", cinfo->size / KB_, board_addr);
2443         printk ("Cirrus Logic chipset on PCI bus\n");
2444         pci_set_drvdata(pdev, info);
2445
2446         return cirrusfb_register(cinfo);
2447
2448 err_release_legacy:
2449         if (release_io_ports)
2450                 release_region(0x3C0, 32);
2451 #if 0
2452         release_mem_region(0xA0000, 65535);
2453 err_release_regions:
2454 #endif
2455         pci_release_regions(pdev);
2456 err_release_fb:
2457         framebuffer_release(info);
2458 err_disable:
2459 err_out:
2460         return ret;
2461 }
2462
2463 static void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
2464 {
2465         struct fb_info *info = pci_get_drvdata(pdev);
2466         DPRINTK ("ENTER\n");
2467
2468         cirrusfb_cleanup (info);
2469
2470         DPRINTK ("EXIT\n");
2471 }
2472
2473 static struct pci_driver cirrusfb_pci_driver = {
2474         .name           = "cirrusfb",
2475         .id_table       = cirrusfb_pci_table,
2476         .probe          = cirrusfb_pci_register,
2477         .remove         = __devexit_p(cirrusfb_pci_unregister),
2478 #ifdef CONFIG_PM
2479 #if 0
2480         .suspend        = cirrusfb_pci_suspend,
2481         .resume         = cirrusfb_pci_resume,
2482 #endif
2483 #endif
2484 };
2485 #endif /* CONFIG_PCI */
2486
2487
2488 #ifdef CONFIG_ZORRO
2489 static int cirrusfb_zorro_register(struct zorro_dev *z,
2490                                    const struct zorro_device_id *ent)
2491 {
2492         struct cirrusfb_info *cinfo;
2493         struct fb_info *info;
2494         cirrusfb_board_t btype;
2495         struct zorro_dev *z2 = NULL;
2496         unsigned long board_addr, board_size, size;
2497         int ret;
2498
2499         btype = ent->driver_data;
2500         if (cirrusfb_zorro_table2[btype].id2)
2501                 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2502         size = cirrusfb_zorro_table2[btype].size;
2503         printk(KERN_INFO "cirrusfb: %s board detected; ",
2504                cirrusfb_board_info[btype].name);
2505
2506         info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2507         if (!info) {
2508                 printk (KERN_ERR "cirrusfb: could not allocate memory\n");
2509                 ret = -ENOMEM;
2510                 goto err_out;
2511         }
2512
2513         cinfo = info->par;
2514         cinfo->info = info;
2515         cinfo->btype = btype;
2516
2517         assert (z > 0);
2518         assert (z2 >= 0);
2519         assert (btype != BT_NONE);
2520
2521         cinfo->zdev = z;
2522         board_addr = zorro_resource_start(z);
2523         board_size = zorro_resource_len(z);
2524         cinfo->size = size;
2525
2526         if (!zorro_request_device(z, "cirrusfb")) {
2527                 printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
2528                        board_addr);
2529                 ret = -EBUSY;
2530                 goto err_release_fb;
2531         }
2532
2533         printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2534
2535         ret = -EIO;
2536
2537         if (btype == BT_PICASSO4) {
2538                 printk (" REG at $%lx\n", board_addr + 0x600000);
2539
2540                 /* To be precise, for the P4 this is not the */
2541                 /* begin of the board, but the begin of RAM. */
2542                 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2543                 /* (note the ugly hardcoded 16M number) */
2544                 cinfo->regbase = ioremap (board_addr, 16777216);
2545                 if (!cinfo->regbase)
2546                         goto err_release_region;
2547
2548                 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
2549                 cinfo->regbase += 0x600000;
2550                 cinfo->fbregs_phys = board_addr + 0x600000;
2551
2552                 cinfo->fbmem_phys = board_addr + 16777216;
2553                 cinfo->fbmem = ioremap (cinfo->fbmem_phys, 16777216);
2554                 if (!cinfo->fbmem)
2555                         goto err_unmap_regbase;
2556         } else {
2557                 printk (" REG at $%lx\n", (unsigned long) z2->resource.start);
2558
2559                 cinfo->fbmem_phys = board_addr;
2560                 if (board_addr > 0x01000000)
2561                         cinfo->fbmem = ioremap (board_addr, board_size);
2562                 else
2563                         cinfo->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
2564                 if (!cinfo->fbmem)
2565                         goto err_release_region;
2566
2567                 /* set address for REG area of board */
2568                 cinfo->regbase = (caddr_t) ZTWO_VADDR (z2->resource.start);
2569                 cinfo->fbregs_phys = z2->resource.start;
2570
2571                 DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
2572         }
2573         cinfo->unmap = cirrusfb_zorro_unmap;
2574
2575         printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2576         zorro_set_drvdata(z, info);
2577
2578         return cirrusfb_register(cinfo);
2579
2580 err_unmap_regbase:
2581         /* Parental advisory: explicit hack */
2582         iounmap(cinfo->regbase - 0x600000);
2583 err_release_region:
2584         release_region(board_addr, board_size);
2585 err_release_fb:
2586         framebuffer_release(info);
2587 err_out:
2588         return ret;
2589 }
2590
2591 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2592 {
2593         struct fb_info *info = zorro_get_drvdata(z);
2594         DPRINTK ("ENTER\n");
2595
2596         cirrusfb_cleanup (info);
2597
2598         DPRINTK ("EXIT\n");
2599 }
2600
2601 static struct zorro_driver cirrusfb_zorro_driver = {
2602         .name           = "cirrusfb",
2603         .id_table       = cirrusfb_zorro_table,
2604         .probe          = cirrusfb_zorro_register,
2605         .remove         = __devexit_p(cirrusfb_zorro_unregister),
2606 };
2607 #endif /* CONFIG_ZORRO */
2608
2609 static int __init cirrusfb_init(void)
2610 {
2611         int error = 0;
2612
2613 #ifndef MODULE
2614         char *option = NULL;
2615
2616         if (fb_get_options("cirrusfb", &option))
2617                 return -ENODEV;
2618         cirrusfb_setup(option);
2619 #endif
2620
2621 #ifdef CONFIG_ZORRO
2622         error |= zorro_register_driver(&cirrusfb_zorro_driver);
2623 #endif
2624 #ifdef CONFIG_PCI
2625         error |= pci_register_driver(&cirrusfb_pci_driver);
2626 #endif
2627         return error;
2628 }
2629
2630
2631
2632 #ifndef MODULE
2633 static int __init cirrusfb_setup(char *options) {
2634         char *this_opt, s[32];
2635         int i;
2636
2637         DPRINTK ("ENTER\n");
2638
2639         if (!options || !*options)
2640                 return 0;
2641
2642         while ((this_opt = strsep (&options, ",")) != NULL) {   
2643                 if (!*this_opt) continue;
2644
2645                 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2646
2647                 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2648                         sprintf (s, "mode:%s", cirrusfb_predefined[i].name);
2649                         if (strcmp (this_opt, s) == 0)
2650                                 cirrusfb_def_mode = i;
2651                 }
2652                 if (!strcmp(this_opt, "noaccel"))
2653                         noaccel = 1;
2654         }
2655         return 0;
2656 }
2657 #endif
2658
2659
2660     /*
2661      *  Modularization
2662      */
2663
2664 MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
2665 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2666 MODULE_LICENSE("GPL");
2667
2668 static void __exit cirrusfb_exit (void)
2669 {
2670 #ifdef CONFIG_PCI
2671         pci_unregister_driver(&cirrusfb_pci_driver);
2672 #endif
2673 #ifdef CONFIG_ZORRO
2674         zorro_unregister_driver(&cirrusfb_zorro_driver);
2675 #endif
2676 }
2677
2678 module_init(cirrusfb_init);
2679
2680 #ifdef MODULE
2681 module_exit(cirrusfb_exit);
2682 #endif
2683
2684
2685 /**********************************************************************/
2686 /* about the following functions - I have used the same names for the */
2687 /* functions as Markus Wild did in his Retina driver for NetBSD as    */
2688 /* they just made sense for this purpose. Apart from that, I wrote    */
2689 /* these functions myself.                                            */
2690 /**********************************************************************/
2691
2692 /*** WGen() - write into one of the external/general registers ***/
2693 static void WGen (const struct cirrusfb_info *cinfo,
2694                   int regnum, unsigned char val)
2695 {
2696         unsigned long regofs = 0;
2697
2698         if (cinfo->btype == BT_PICASSO) {
2699                 /* Picasso II specific hack */
2700 /*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2701                 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2702                         regofs = 0xfff;
2703         }
2704
2705         vga_w (cinfo->regbase, regofs + regnum, val);
2706 }
2707
2708 /*** RGen() - read out one of the external/general registers ***/
2709 static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum)
2710 {
2711         unsigned long regofs = 0;
2712
2713         if (cinfo->btype == BT_PICASSO) {
2714                 /* Picasso II specific hack */
2715 /*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2716                 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2717                         regofs = 0xfff;
2718         }
2719
2720         return vga_r (cinfo->regbase, regofs + regnum);
2721 }
2722
2723 /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2724 static void AttrOn (const struct cirrusfb_info *cinfo)
2725 {
2726         assert (cinfo != NULL);
2727
2728         DPRINTK ("ENTER\n");
2729
2730         if (vga_rcrt (cinfo->regbase, CL_CRT24) & 0x80) {
2731                 /* if we're just in "write value" mode, write back the */
2732                 /* same value as before to not modify anything */
2733                 vga_w (cinfo->regbase, VGA_ATT_IW,
2734                        vga_r (cinfo->regbase, VGA_ATT_R));
2735         }
2736         /* turn on video bit */
2737 /*      vga_w (cinfo->regbase, VGA_ATT_IW, 0x20); */
2738         vga_w (cinfo->regbase, VGA_ATT_IW, 0x33);
2739
2740         /* dummy write on Reg0 to be on "write index" mode next time */
2741         vga_w (cinfo->regbase, VGA_ATT_IW, 0x00);
2742
2743         DPRINTK ("EXIT\n");
2744 }
2745
2746 /*** WHDR() - write into the Hidden DAC register ***/
2747 /* as the HDR is the only extension register that requires special treatment
2748  * (the other extension registers are accessible just like the "ordinary"
2749  * registers of their functional group) here is a specialized routine for
2750  * accessing the HDR
2751  */
2752 static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val)
2753 {
2754         unsigned char dummy;
2755
2756         if (cinfo->btype == BT_PICASSO) {
2757                 /* Klaus' hint for correct access to HDR on some boards */
2758                 /* first write 0 to pixel mask (3c6) */
2759                 WGen (cinfo, VGA_PEL_MSK, 0x00);
2760                 udelay (200);
2761                 /* next read dummy from pixel address (3c8) */
2762                 dummy = RGen (cinfo, VGA_PEL_IW);
2763                 udelay (200);
2764         }
2765         /* now do the usual stuff to access the HDR */
2766
2767         dummy = RGen (cinfo, VGA_PEL_MSK);
2768         udelay (200);
2769         dummy = RGen (cinfo, VGA_PEL_MSK);
2770         udelay (200);
2771         dummy = RGen (cinfo, VGA_PEL_MSK);
2772         udelay (200);
2773         dummy = RGen (cinfo, VGA_PEL_MSK);
2774         udelay (200);
2775
2776         WGen (cinfo, VGA_PEL_MSK, val);
2777         udelay (200);
2778
2779         if (cinfo->btype == BT_PICASSO) {
2780                 /* now first reset HDR access counter */
2781                 dummy = RGen (cinfo, VGA_PEL_IW);
2782                 udelay (200);
2783
2784                 /* and at the end, restore the mask value */
2785                 /* ## is this mask always 0xff? */
2786                 WGen (cinfo, VGA_PEL_MSK, 0xff);
2787                 udelay (200);
2788         }
2789 }
2790
2791
2792 /*** WSFR() - write to the "special function register" (SFR) ***/
2793 static void WSFR (struct cirrusfb_info *cinfo, unsigned char val)
2794 {
2795 #ifdef CONFIG_ZORRO
2796         assert (cinfo->regbase != NULL);
2797         cinfo->SFR = val;
2798         z_writeb (val, cinfo->regbase + 0x8000);
2799 #endif
2800 }
2801
2802 /* The Picasso has a second register for switching the monitor bit */
2803 static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val)
2804 {
2805 #ifdef CONFIG_ZORRO
2806         /* writing an arbitrary value to this one causes the monitor switcher */
2807         /* to flip to Amiga display */
2808         assert (cinfo->regbase != NULL);
2809         cinfo->SFR = val;
2810         z_writeb (val, cinfo->regbase + 0x9000);
2811 #endif
2812 }
2813
2814
2815 /*** WClut - set CLUT entry (range: 0..63) ***/
2816 static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
2817             unsigned char green, unsigned char blue)
2818 {
2819         unsigned int data = VGA_PEL_D;
2820
2821         /* address write mode register is not translated.. */
2822         vga_w (cinfo->regbase, VGA_PEL_IW, regnum);
2823
2824         if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2825             cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2826                 /* but DAC data register IS, at least for Picasso II */
2827                 if (cinfo->btype == BT_PICASSO)
2828                         data += 0xfff;
2829                 vga_w (cinfo->regbase, data, red);
2830                 vga_w (cinfo->regbase, data, green);
2831                 vga_w (cinfo->regbase, data, blue);
2832         } else {
2833                 vga_w (cinfo->regbase, data, blue);
2834                 vga_w (cinfo->regbase, data, green);
2835                 vga_w (cinfo->regbase, data, red);
2836         }
2837 }
2838
2839
2840 #if 0
2841 /*** RClut - read CLUT entry (range 0..63) ***/
2842 static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
2843             unsigned char *green, unsigned char *blue)
2844 {
2845         unsigned int data = VGA_PEL_D;
2846
2847         vga_w (cinfo->regbase, VGA_PEL_IR, regnum);
2848
2849         if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
2850             cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
2851                 if (cinfo->btype == BT_PICASSO)
2852                         data += 0xfff;
2853                 *red = vga_r (cinfo->regbase, data);
2854                 *green = vga_r (cinfo->regbase, data);
2855                 *blue = vga_r (cinfo->regbase, data);
2856         } else {
2857                 *blue = vga_r (cinfo->regbase, data);
2858                 *green = vga_r (cinfo->regbase, data);
2859                 *red = vga_r (cinfo->regbase, data);
2860         }
2861 }
2862 #endif
2863
2864
2865 /*******************************************************************
2866         cirrusfb_WaitBLT()
2867
2868         Wait for the BitBLT engine to complete a possible earlier job
2869 *********************************************************************/
2870
2871 /* FIXME: use interrupts instead */
2872 static void cirrusfb_WaitBLT (u8 __iomem *regbase)
2873 {
2874         /* now busy-wait until we're done */
2875         while (vga_rgfx (regbase, CL_GR31) & 0x08)
2876                 /* do nothing */ ;
2877 }
2878
2879 /*******************************************************************
2880         cirrusfb_BitBLT()
2881
2882         perform accelerated "scrolling"
2883 ********************************************************************/
2884
2885 static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
2886                              u_short curx, u_short cury, u_short destx, u_short desty,
2887                              u_short width, u_short height, u_short line_length)
2888 {
2889         u_short nwidth, nheight;
2890         u_long nsrc, ndest;
2891         u_char bltmode;
2892
2893         DPRINTK ("ENTER\n");
2894
2895         nwidth = width - 1;
2896         nheight = height - 1;
2897
2898         bltmode = 0x00;
2899         /* if source adr < dest addr, do the Blt backwards */
2900         if (cury <= desty) {
2901                 if (cury == desty) {
2902                         /* if src and dest are on the same line, check x */
2903                         if (curx < destx)
2904                                 bltmode |= 0x01;
2905                 } else
2906                         bltmode |= 0x01;
2907         }
2908         if (!bltmode) {
2909                 /* standard case: forward blitting */
2910                 nsrc = (cury * line_length) + curx;
2911                 ndest = (desty * line_length) + destx;
2912         } else {
2913                 /* this means start addresses are at the end, counting backwards */
2914                 nsrc = cury * line_length + curx + nheight * line_length + nwidth;
2915                 ndest = desty * line_length + destx + nheight * line_length + nwidth;
2916         }
2917
2918         /*
2919            run-down of registers to be programmed:
2920            destination pitch
2921            source pitch
2922            BLT width/height
2923            source start
2924            destination start
2925            BLT mode
2926            BLT ROP
2927            VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
2928            start/stop
2929          */
2930
2931         cirrusfb_WaitBLT(regbase);
2932
2933         /* pitch: set to line_length */
2934         vga_wgfx (regbase, CL_GR24, line_length & 0xff);        /* dest pitch low */
2935         vga_wgfx (regbase, CL_GR25, (line_length >> 8));        /* dest pitch hi */
2936         vga_wgfx (regbase, CL_GR26, line_length & 0xff);        /* source pitch low */
2937         vga_wgfx (regbase, CL_GR27, (line_length >> 8));        /* source pitch hi */
2938
2939         /* BLT width: actual number of pixels - 1 */
2940         vga_wgfx (regbase, CL_GR20, nwidth & 0xff);     /* BLT width low */
2941         vga_wgfx (regbase, CL_GR21, (nwidth >> 8));     /* BLT width hi */
2942
2943         /* BLT height: actual number of lines -1 */
2944         vga_wgfx (regbase, CL_GR22, nheight & 0xff);    /* BLT height low */
2945         vga_wgfx (regbase, CL_GR23, (nheight >> 8));    /* BLT width hi */
2946
2947         /* BLT destination */
2948         vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff));   /* BLT dest low */
2949         vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8));     /* BLT dest mid */
2950         vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16));    /* BLT dest hi */
2951
2952         /* BLT source */
2953         vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff));    /* BLT src low */
2954         vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8));              /* BLT src mid */
2955         vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16));     /* BLT src hi */
2956
2957         /* BLT mode */
2958         vga_wgfx (regbase, CL_GR30, bltmode);   /* BLT mode */
2959
2960         /* BLT ROP: SrcCopy */
2961         vga_wgfx (regbase, CL_GR32, 0x0d);              /* BLT ROP */
2962
2963         /* and finally: GO! */
2964         vga_wgfx (regbase, CL_GR31, 0x02);              /* BLT Start/status */
2965
2966         DPRINTK ("EXIT\n");
2967 }
2968
2969
2970 /*******************************************************************
2971         cirrusfb_RectFill()
2972
2973         perform accelerated rectangle fill
2974 ********************************************************************/
2975
2976 static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
2977                      u_short x, u_short y, u_short width, u_short height,
2978                      u_char color, u_short line_length)
2979 {
2980         u_short nwidth, nheight;
2981         u_long ndest;
2982         u_char op;
2983
2984         DPRINTK ("ENTER\n");
2985
2986         nwidth = width - 1;
2987         nheight = height - 1;
2988
2989         ndest = (y * line_length) + x;
2990
2991         cirrusfb_WaitBLT(regbase);
2992
2993         /* pitch: set to line_length */
2994         vga_wgfx (regbase, CL_GR24, line_length & 0xff);        /* dest pitch low */
2995         vga_wgfx (regbase, CL_GR25, (line_length >> 8));        /* dest pitch hi */
2996         vga_wgfx (regbase, CL_GR26, line_length & 0xff);        /* source pitch low */
2997         vga_wgfx (regbase, CL_GR27, (line_length >> 8));        /* source pitch hi */
2998
2999         /* BLT width: actual number of pixels - 1 */
3000         vga_wgfx (regbase, CL_GR20, nwidth & 0xff);     /* BLT width low */
3001         vga_wgfx (regbase, CL_GR21, (nwidth >> 8));     /* BLT width hi */
3002
3003         /* BLT height: actual number of lines -1 */
3004         vga_wgfx (regbase, CL_GR22, nheight & 0xff);            /* BLT height low */
3005         vga_wgfx (regbase, CL_GR23, (nheight >> 8));            /* BLT width hi */
3006
3007         /* BLT destination */
3008         vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff));   /* BLT dest low */
3009         vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8));     /* BLT dest mid */
3010         vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16));            /* BLT dest hi */
3011
3012         /* BLT source: set to 0 (is a dummy here anyway) */
3013         vga_wgfx (regbase, CL_GR2C, 0x00);      /* BLT src low */
3014         vga_wgfx (regbase, CL_GR2D, 0x00);      /* BLT src mid */
3015         vga_wgfx (regbase, CL_GR2E, 0x00);      /* BLT src hi */
3016
3017         /* This is a ColorExpand Blt, using the */
3018         /* same color for foreground and background */
3019         vga_wgfx (regbase, VGA_GFX_SR_VALUE, color);    /* foreground color */
3020         vga_wgfx (regbase, VGA_GFX_SR_ENABLE, color);   /* background color */
3021
3022         op = 0xc0;
3023         if (bits_per_pixel == 16) {
3024                 vga_wgfx (regbase, CL_GR10, color);     /* foreground color */
3025                 vga_wgfx (regbase, CL_GR11, color);     /* background color */
3026                 op = 0x50;
3027                 op = 0xd0;
3028         } else if (bits_per_pixel == 32) {
3029                 vga_wgfx (regbase, CL_GR10, color);     /* foreground color */
3030                 vga_wgfx (regbase, CL_GR11, color);     /* background color */
3031                 vga_wgfx (regbase, CL_GR12, color);     /* foreground color */
3032                 vga_wgfx (regbase, CL_GR13, color);     /* background color */
3033                 vga_wgfx (regbase, CL_GR14, 0); /* foreground color */
3034                 vga_wgfx (regbase, CL_GR15, 0); /* background color */
3035                 op = 0x50;
3036                 op = 0xf0;
3037         }
3038         /* BLT mode: color expand, Enable 8x8 copy (faster?) */
3039         vga_wgfx (regbase, CL_GR30, op);        /* BLT mode */
3040
3041         /* BLT ROP: SrcCopy */
3042         vga_wgfx (regbase, CL_GR32, 0x0d);      /* BLT ROP */
3043
3044         /* and finally: GO! */
3045         vga_wgfx (regbase, CL_GR31, 0x02);      /* BLT Start/status */
3046
3047         DPRINTK ("EXIT\n");
3048 }
3049
3050
3051 /**************************************************************************
3052  * bestclock() - determine closest possible clock lower(?) than the
3053  * desired pixel clock
3054  **************************************************************************/
3055 static void bestclock (long freq, long *best, long *nom,
3056                        long *den, long *div, long maxfreq)
3057 {
3058         long n, h, d, f;
3059
3060         assert (best != NULL);
3061         assert (nom != NULL);
3062         assert (den != NULL);
3063         assert (div != NULL);
3064         assert (maxfreq > 0);
3065
3066         *nom = 0;
3067         *den = 0;
3068         *div = 0;
3069
3070         DPRINTK ("ENTER\n");
3071
3072         if (freq < 8000)
3073                 freq = 8000;
3074
3075         if (freq > maxfreq)
3076                 freq = maxfreq;
3077
3078         *best = 0;
3079         f = freq * 10;
3080
3081         for (n = 32; n < 128; n++) {
3082                 d = (143181 * n) / f;
3083                 if ((d >= 7) && (d <= 63)) {
3084                         if (d > 31)
3085                                 d = (d / 2) * 2;
3086                         h = (14318 * n) / d;
3087                         if (abs (h - freq) < abs (*best - freq)) {
3088                                 *best = h;
3089                                 *nom = n;
3090                                 if (d < 32) {
3091                                         *den = d;
3092                                         *div = 0;
3093                                 } else {
3094                                         *den = d / 2;
3095                                         *div = 1;
3096                                 }
3097                         }
3098                 }
3099                 d = ((143181 * n) + f - 1) / f;
3100                 if ((d >= 7) && (d <= 63)) {
3101                         if (d > 31)
3102                                 d = (d / 2) * 2;
3103                         h = (14318 * n) / d;
3104                         if (abs (h - freq) < abs (*best - freq)) {
3105                                 *best = h;
3106                                 *nom = n;
3107                                 if (d < 32) {
3108                                         *den = d;
3109                                         *div = 0;
3110                                 } else {
3111                                         *den = d / 2;
3112                                         *div = 1;
3113                                 }
3114                         }
3115                 }
3116         }
3117
3118         DPRINTK ("Best possible values for given frequency:\n");
3119         DPRINTK ("        best: %ld kHz  nom: %ld  den: %ld  div: %ld\n",
3120                  freq, *nom, *den, *div);
3121
3122         DPRINTK ("EXIT\n");
3123 }
3124
3125
3126 /* -------------------------------------------------------------------------
3127  *
3128  * debugging functions
3129  *
3130  * -------------------------------------------------------------------------
3131  */
3132
3133 #ifdef CIRRUSFB_DEBUG
3134
3135 /**
3136  * cirrusfb_dbg_print_byte
3137  * @name: name associated with byte value to be displayed
3138  * @val: byte value to be displayed
3139  *
3140  * DESCRIPTION:
3141  * Display an indented string, along with a hexidecimal byte value, and
3142  * its decoded bits.  Bits 7 through 0 are listed in left-to-right
3143  * order.
3144  */
3145
3146 static
3147 void cirrusfb_dbg_print_byte (const char *name, unsigned char val)
3148 {
3149         DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3150                  name, val,
3151                  val & 0x80 ? '1' : '0',
3152                  val & 0x40 ? '1' : '0',
3153                  val & 0x20 ? '1' : '0',
3154                  val & 0x10 ? '1' : '0',
3155                  val & 0x08 ? '1' : '0',
3156                  val & 0x04 ? '1' : '0',
3157                  val & 0x02 ? '1' : '0',
3158                  val & 0x01 ? '1' : '0');
3159 }
3160
3161
3162 /**
3163  * cirrusfb_dbg_print_regs
3164  * @base: If using newmmio, the newmmio base address, otherwise %NULL
3165  * @reg_class: type of registers to read: %CRT, or %SEQ
3166  *
3167  * DESCRIPTION:
3168  * Dumps the given list of VGA CRTC registers.  If @base is %NULL,
3169  * old-style I/O ports are queried for information, otherwise MMIO is
3170  * used at the given @base address to query the information.
3171  */
3172
3173 static
3174 void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...)
3175 {
3176         va_list list;
3177         unsigned char val = 0;
3178         unsigned reg;
3179         char *name;
3180
3181         va_start (list, reg_class);
3182
3183         name = va_arg (list, char *);
3184         while (name != NULL) {
3185                 reg = va_arg (list, int);
3186
3187                 switch (reg_class) {
3188                 case CRT:
3189                         val = vga_rcrt (regbase, (unsigned char) reg);
3190                         break;
3191                 case SEQ:
3192                         val = vga_rseq (regbase, (unsigned char) reg);
3193                         break;
3194                 default:
3195                         /* should never occur */
3196                         assert (FALSE);
3197                         break;
3198                 }
3199
3200                 cirrusfb_dbg_print_byte (name, val);
3201
3202                 name = va_arg (list, char *);
3203         }
3204
3205         va_end (list);
3206 }
3207
3208
3209 /**
3210  * cirrusfb_dump
3211  * @cirrusfbinfo:
3212  *
3213  * DESCRIPTION:
3214  */
3215
3216 static
3217 void cirrusfb_dump (void)
3218 {
3219         cirrusfb_dbg_reg_dump (NULL);
3220 }
3221
3222
3223 /**
3224  * cirrusfb_dbg_reg_dump
3225  * @base: If using newmmio, the newmmio base address, otherwise %NULL
3226  *
3227  * DESCRIPTION:
3228  * Dumps a list of interesting VGA and CIRRUSFB registers.  If @base is %NULL,
3229  * old-style I/O ports are queried for information, otherwise MMIO is
3230  * used at the given @base address to query the information.
3231  */
3232
3233 static
3234 void cirrusfb_dbg_reg_dump (caddr_t regbase)
3235 {
3236         DPRINTK ("CIRRUSFB VGA CRTC register dump:\n");
3237
3238         cirrusfb_dbg_print_regs (regbase, CRT,
3239                            "CR00", 0x00,
3240                            "CR01", 0x01,
3241                            "CR02", 0x02,
3242                            "CR03", 0x03,
3243                            "CR04", 0x04,
3244                            "CR05", 0x05,
3245                            "CR06", 0x06,
3246                            "CR07", 0x07,
3247                            "CR08", 0x08,
3248                            "CR09", 0x09,
3249                            "CR0A", 0x0A,
3250                            "CR0B", 0x0B,
3251                            "CR0C", 0x0C,
3252                            "CR0D", 0x0D,
3253                            "CR0E", 0x0E,
3254                            "CR0F", 0x0F,
3255                            "CR10", 0x10,
3256                            "CR11", 0x11,
3257                            "CR12", 0x12,
3258                            "CR13", 0x13,
3259                            "CR14", 0x14,
3260                            "CR15", 0x15,
3261                            "CR16", 0x16,
3262                            "CR17", 0x17,
3263                            "CR18", 0x18,
3264                            "CR22", 0x22,
3265                            "CR24", 0x24,
3266                            "CR26", 0x26,
3267                            "CR2D", 0x2D,
3268                            "CR2E", 0x2E,
3269                            "CR2F", 0x2F,
3270                            "CR30", 0x30,
3271                            "CR31", 0x31,
3272                            "CR32", 0x32,
3273                            "CR33", 0x33,
3274                            "CR34", 0x34,
3275                            "CR35", 0x35,
3276                            "CR36", 0x36,
3277                            "CR37", 0x37,
3278                            "CR38", 0x38,
3279                            "CR39", 0x39,
3280                            "CR3A", 0x3A,
3281                            "CR3B", 0x3B,
3282                            "CR3C", 0x3C,
3283                            "CR3D", 0x3D,
3284                            "CR3E", 0x3E,
3285                            "CR3F", 0x3F,
3286                            NULL);
3287
3288         DPRINTK ("\n");
3289
3290         DPRINTK ("CIRRUSFB VGA SEQ register dump:\n");
3291
3292         cirrusfb_dbg_print_regs (regbase, SEQ,
3293                            "SR00", 0x00,
3294                            "SR01", 0x01,
3295                            "SR02", 0x02,
3296                            "SR03", 0x03,
3297                            "SR04", 0x04,
3298                            "SR08", 0x08,
3299                            "SR09", 0x09,
3300                            "SR0A", 0x0A,
3301                            "SR0B", 0x0B,
3302                            "SR0D", 0x0D,
3303                            "SR10", 0x10,
3304                            "SR11", 0x11,
3305                            "SR12", 0x12,
3306                            "SR13", 0x13,
3307                            "SR14", 0x14,
3308                            "SR15", 0x15,
3309                            "SR16", 0x16,
3310                            "SR17", 0x17,
3311                            "SR18", 0x18,
3312                            "SR19", 0x19,
3313                            "SR1A", 0x1A,
3314                            "SR1B", 0x1B,
3315                            "SR1C", 0x1C,
3316                            "SR1D", 0x1D,
3317                            "SR1E", 0x1E,
3318                            "SR1F", 0x1F,
3319                            NULL);
3320
3321         DPRINTK ("\n");
3322 }
3323
3324 #endif                          /* CIRRUSFB_DEBUG */
3325