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