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