Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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