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