]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/ct69000.c
* Switch LWMON board default config from FRAM to EEPROM;
[karo-tx-uboot.git] / drivers / ct69000.c
1 /*
2  * (C) Copyright 2002
3  * Denis Peter, MPL AG Switzerland
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * ported from ctfb.c (linux kernel) for the U-Boot
26  *
27  */
28
29 /************************************************************************
30   Get Parameters for the video mode:
31   Parameters can be set via the variable "videomode" in the environment.
32   2 diferent ways are possible:
33   "videomode=301"   - 301 is a hexadecimal number describing the VESA
34                       mode. Following modes are implemented:
35
36                       Colors    640x480 800x600 1024x768 1152x864
37                      --------+-----------------------------------
38                       8 bits |  0x301   0x303    0x305    0x161
39                      15 bits |  0x310   0x313    0x316    0x162
40                      16 bits |  0x311   0x314    0x317    0x163
41                      24 bits |  0x312   0x315    0x318      ?
42                      --------+-----------------------------------
43   "videomode=bootargs"
44                    - the parameters are parsed from the bootargs.
45                       The format is "NAME:VALUE,NAME:VALUE" etc.
46                       Ex.:
47                       "bootargs=video=ctfb:x:800,y:600,depth:16,pclk:25000"
48                       Parameters not included in the list will be taken from
49                       the default mode, which is one of the following:
50                       mode:0  640x480x24
51                       mode:1  800x600x16
52                       mode:2  1024x768x8
53                       mode:3  960x720x24
54                       mode:4  1152x864x16
55                       if "mode" is not provided within the parameter list,
56                       mode:0 is assumed.
57                       Following parameters are supported:
58                       x       xres = visible resolution horizontal
59                       y       yres = visible resolution vertical
60                       pclk    pixelclocks in pico sec
61                       le      left_marging time from sync to picture in pixelclocks
62                       ri      right_marging time from picture to sync in pixelclocks
63                       up      upper_margin time from sync to picture
64                       lo      lower_margin
65                       hs      hsync_len length of horizontal sync
66                       vs      vsync_len length of vertical sync
67                       sync    see FB_SYNC_*
68                       vmode   see FB_VMODE_*
69                       depth   Color depth in bits per pixel
70                       All other parameters in the variable bootargs are ignored.
71                       It is also possible to set the parameters direct in the
72                       variable "videomode", or in another variable i.e.
73                       "myvideo" and setting the variable "videomode=myvideo"..
74 ****************************************************************************/
75
76 #include <common.h>
77
78 #ifdef CONFIG_VIDEO
79
80 #include <pci.h>
81 #include <video_fb.h>
82
83 #ifdef CONFIG_VIDEO_CT69000
84
85 /* debug */
86 #undef VGA_DEBUG
87 #undef VGA_DUMP_REG
88 #ifdef VGA_DEBUG
89 #define PRINTF(fmt,args...)     printf (fmt ,##args)
90 #else
91 #define PRINTF(fmt,args...)
92 #endif
93
94 /* Macros */
95 #ifndef min
96 #define min( a, b ) ( ( a ) < ( b ) ) ? ( a ) : ( b )
97 #endif
98 #ifndef max
99 #define max( a, b ) ( ( a ) > ( b ) ) ? ( a ) : ( b )
100 #endif
101 #ifdef minmax
102 #error "term minmax already used."
103 #endif
104 #define minmax( a, x, b ) max( ( a ), min( ( x ), ( b ) ) )
105 #define N_ELTS( x ) ( sizeof( x ) / sizeof( x[ 0 ] ) )
106
107 /* CT Register Offsets */
108 #define CT_AR_O                 0x3c0   /* Index and Data write port of the attribute Registers */
109 #define CT_GR_O                 0x3ce   /* Index port of the Graphic Controller Registers */
110 #define CT_SR_O                 0x3c4   /* Index port of the Sequencer Controller */
111 #define CT_CR_O                 0x3d4   /* Index port of the CRT Controller */
112 #define CT_XR_O                 0x3d6   /* Extended Register index */
113 #define CT_MSR_W_O              0x3c2   /* Misc. Output Register (write only) */
114 #define CT_LUT_MASK_O           0x3c6   /* Color Palette Mask */
115 #define CT_LUT_START_O          0x3c8   /* Color Palette Write Mode Index */
116 #define CT_LUT_RGB_O            0x3c9   /* Color Palette Data Port */
117 #define CT_STATUS_REG0_O        0x3c2   /* Status Register 0 (read only) */
118 #define CT_STATUS_REG1_O        0x3da   /* Input Status Register 1 (read only) */
119
120 #define CT_FP_O                 0x3d0   /* Index port of the Flat panel Registers */
121 #define CT_MR_O                 0x3d2   /* Index Port of the Multimedia Extension */
122
123 /* defines for the memory mapped registers */
124 #define BR00_o          0x400000        /* Source and Destination Span Register */
125 #define BR01_o          0x400004        /* Pattern/Source Expansion Background Color & Transparency Key Register */
126 #define BR02_o          0x400008        /* Pattern/Source Expansion Foreground Color Register */
127 #define BR03_o          0x40000C        /* Monochrome Source Control Register */
128 #define BR04_o          0x400010        /* BitBLT Control Register */
129 #define BR05_o          0x400014        /* Pattern Address Registe */
130 #define BR06_o          0x400018        /* Source Address Register */
131 #define BR07_o          0x40001C        /* Destination Address Register */
132 #define BR08_o          0x400020        /* Destination Width & Height Register */
133 #define BR09_o          0x400024        /* Source Expansion Background Color & Transparency Key Register */
134 #define BR0A_o          0x400028        /* Source Expansion Foreground Color Register */
135
136 #define CURSOR_SIZE     0x1000  /* in KByte for HW Cursor */
137 #define PATTERN_ADR     (pGD->dprBase + CURSOR_SIZE)    /* pattern Memory after Cursor Memory */
138 #define PATTERN_SIZE    8*8*4   /* 4 Bytes per Pixel 8 x 8 Pixel */
139 #define ACCELMEMORY     (CURSOR_SIZE + PATTERN_SIZE)    /* reserved Memory for BITBlt and hw cursor */
140
141 /* Some Mode definitions */
142 #define FB_SYNC_HOR_HIGH_ACT    1       /* horizontal sync high active  */
143 #define FB_SYNC_VERT_HIGH_ACT   2       /* vertical sync high active    */
144 #define FB_SYNC_EXT             4       /* external sync                */
145 #define FB_SYNC_COMP_HIGH_ACT   8       /* composite sync high active   */
146 #define FB_SYNC_BROADCAST       16      /* broadcast video timings      */
147                                         /* vtotal = 144d/288n/576i => PAL  */
148                                         /* vtotal = 121d/242n/484i => NTSC */
149 #define FB_SYNC_ON_GREEN        32      /* sync on green */
150
151 #define FB_VMODE_NONINTERLACED  0       /* non interlaced */
152 #define FB_VMODE_INTERLACED     1       /* interlaced   */
153 #define FB_VMODE_DOUBLE         2       /* double scan */
154 #define FB_VMODE_MASK           255
155
156 #define FB_VMODE_YWRAP          256     /* ywrap instead of panning     */
157 #define FB_VMODE_SMOOTH_XPAN    512     /* smooth xpan possible (internally used) */
158 #define FB_VMODE_CONUPDATE      512     /* don't update x/yoffset       */
159
160 #define text                    0
161 #define fntwidth                8
162
163 /* table for VGA Initialization  */
164 typedef struct {
165         const unsigned char reg;
166         const unsigned char val;
167 } CT_CFG_TABLE;
168
169 /* this table provides some basic initialisations such as Memory Clock etc */
170 static CT_CFG_TABLE xreg[] = {
171         {0x09, 0x01},           /* CRT Controller Extensions Enable */
172         {0x0A, 0x02},           /* Frame Buffer Mapping */
173         {0x0B, 0x01},           /* PCI Write Burst support */
174         {0x20, 0x00},           /* BitBLT Configuration */
175         {0x40, 0x03},           /* Memory Access Control */
176         {0x60, 0x00},           /* Video Pin Control */
177         {0x61, 0x00},           /* DPMS Synch control */
178         {0x62, 0x00},           /* GPIO Pin Control */
179         {0x63, 0xBD},           /* GPIO Pin Data */
180         {0x67, 0x00},           /* Pin Tri-State */
181         {0x80, 0x80},           /* Pixel Pipeline Config 0 register */
182         {0xA0, 0x00},           /* Cursor 1 Control Reg */
183         {0xA1, 0x00},           /* Cursor 1 Vertical Extension Reg */
184         {0xA2, 0x00},           /* Cursor 1 Base Address Low */
185         {0xA3, 0x00},           /* Cursor 1 Base Address High */
186         {0xA4, 0x00},           /* Cursor 1 X-Position Low */
187         {0xA5, 0x00},           /* Cursor 1 X-Position High */
188         {0xA6, 0x00},           /* Cursor 1 Y-Position Low */
189         {0xA7, 0x00},           /* Cursor 1 Y-Position High */
190         {0xA8, 0x00},           /* Cursor 2 Control Reg */
191         {0xA9, 0x00},           /* Cursor 2 Vertical Extension Reg */
192         {0xAA, 0x00},           /* Cursor 2 Base Address Low */
193         {0xAB, 0x00},           /* Cursor 2 Base Address High */
194         {0xAC, 0x00},           /* Cursor 2 X-Position Low */
195         {0xAD, 0x00},           /* Cursor 2 X-Position High */
196         {0xAE, 0x00},           /* Cursor 2 Y-Position Low */
197         {0xAF, 0x00},           /* Cursor 2 Y-Position High */
198         {0xC0, 0x7D},           /* Dot Clock 0 VCO M-Divisor */
199         {0xC1, 0x07},           /* Dot Clock 0 VCO N-Divisor */
200         {0xC3, 0x34},           /* Dot Clock 0 Divisor select */
201         {0xC4, 0x55},           /* Dot Clock 1 VCO M-Divisor */
202         {0xC5, 0x09},           /* Dot Clock 1 VCO N-Divisor */
203         {0xC7, 0x24},           /* Dot Clock 1 Divisor select */
204         {0xC8, 0x7D},           /* Dot Clock 2 VCO M-Divisor */
205         {0xC9, 0x07},           /* Dot Clock 2 VCO N-Divisor */
206         {0xCB, 0x34},           /* Dot Clock 2 Divisor select */
207         {0xCC, 0x38},           /* Memory Clock 0 VCO M-Divisor */
208         {0xCD, 0x03},           /* Memory Clock 0 VCO N-Divisor */
209         {0xCE, 0x90},           /* Memory Clock 0 Divisor select */
210         {0xCF, 0x06},           /* Clock Config */
211         {0xD0, 0x0F},           /* Power Down */
212         {0xD1, 0x01},           /* Power Down BitBLT */
213         {0xFF, 0xFF}            /* end of table */
214 };
215 /* Clock Config:
216  * =============
217  *
218  * PD Registers:
219  * -------------
220  * Bit2 and Bit4..6 are used for the Loop Divisor and Post Divisor.
221  * They are encoded as follows:
222  *
223  * +---+--------------+
224  * | 2 | Loop Divisor |
225  * +---+--------------+
226  * | 1 | 1            |
227  * +---+--------------+
228  * | 0 | 4            |
229  * +---+--------------+
230  * Note: The Memory Clock does not have a Loop Divisor.
231  * +---+---+---+--------------+
232  * | 6 | 5 | 4 | Post Divisor |
233  * +---+---+---+--------------+
234  * | 0 | 0 | 0 | 1            |
235  * +---+---+---+--------------+
236  * | 0 | 0 | 1 | 2            |
237  * +---+---+---+--------------+
238  * | 0 | 1 | 0 | 4            |
239  * +---+---+---+--------------+
240  * | 0 | 1 | 1 | 8            |
241  * +---+---+---+--------------+
242  * | 1 | 0 | 0 | 16           |
243  * +---+---+---+--------------+
244  * | 1 | 0 | 1 | 32           |
245  * +---+---+---+--------------+
246  * | 1 | 1 | X | reserved     |
247  * +---+---+---+--------------+
248  *
249  * All other bits are reserved in these registers.
250  *
251  * Clock VCO M Registers:
252  * ----------------------
253  * These Registers contain the M Value -2.
254  *
255  * Clock VCO N Registers:
256  * ----------------------
257  * These Registers contain the N Value -2.
258  *
259  * Formulas:
260  * ---------
261  * Fvco = (Fref * Loop Divisor * M/N), whereas 100MHz < Fvco < 220MHz
262  * Fout = Fvco / Post Divisor
263  *
264  * Dot Clk0 (default 25MHz):
265  * -------------------------
266  * Fvco = 14.318 * 127 / 9 = 202.045MHz
267  * Fout = 202.045MHz / 8 = 25.25MHz
268  * Post Divisor = 8
269  * Loop Divisor = 1
270  * XRC0 = (M - 2) = 125 = 0x7D
271  * XRC1 = (N - 2) = 7   = 0x07
272  * XRC3 =                 0x34
273  *
274  * Dot Clk1 (default 28MHz):
275  * -------------------------
276  * Fvco = 14.318 * 87 / 11 = 113.24MHz
277  * Fout = 113.24MHz / 4 = 28.31MHz
278  * Post Divisor = 4
279  * Loop Divisor = 1
280  * XRC4 = (M - 2) = 85 = 0x55
281  * XRC5 = (N - 2) = 9  = 0x09
282  * XRC7 =                0x24
283  *
284  * Dot Clk2 (variable for extended modes set to 25MHz):
285  * ----------------------------------------------------
286  * Fvco = 14.318 * 127 / 9 = 202.045MHz
287  * Fout = 202.045MHz / 8 = 25.25MHz
288  * Post Divisor = 8
289  * Loop Divisor = 1
290  * XRC8 = (M - 2) = 125 = 0x7D
291  * XRC9 = (N - 2) = 7   = 0x07
292  * XRCB =                 0x34
293  *
294  * Memory Clk for most modes >50MHz:
295  * ----------------------------------
296  * Fvco = 14.318 * 58 / 5 = 166MHz
297  * Fout = 166MHz / 2      = 83MHz
298  * Post Divisor = 2
299  * XRCC = (M - 2) = 57  = 0x38
300  * XRCD = (N - 2) = 3   = 0x03
301  * XRCE =                 0x90
302  *
303  * Note Bit7 enables the clock source from the VCO
304  *
305  */
306
307 /******************************************************************
308  * Resolution Struct
309  ******************************************************************/
310 struct ctfb_res_modes {
311         int xres;               /* visible resolution           */
312         int yres;
313         /* Timing: All values in pixclocks, except pixclock (of course) */
314         int pixclock;           /* pixel clock in ps (pico seconds) */
315         int left_margin;        /* time from sync to picture    */
316         int right_margin;       /* time from picture to sync    */
317         int upper_margin;       /* time from sync to picture    */
318         int lower_margin;
319         int hsync_len;          /* length of horizontal sync    */
320         int vsync_len;          /* length of vertical sync      */
321         int sync;               /* see FB_SYNC_*                */
322         int vmode;              /* see FB_VMODE_*               */
323 };
324
325 /******************************************************************
326  * Vesa Mode Struct
327  ******************************************************************/
328 struct ctfb_vesa_modes {
329         int vesanr;             /* Vesa number as in LILO (VESA Nr + 0x200} */
330         int resindex;           /* index to resolution struct */
331         int bits_per_pixel;     /* bpp */
332 };
333 /*******************************************************************
334  * Chips struct
335  *******************************************************************/
336 struct ctfb_chips_properties {
337         int device_id;          /* PCI Device ID */
338         unsigned long max_mem;  /* memory for frame buffer */
339         int vld_set;            /* value of VLD if bit2 in clock control is set */
340         int vld_not_set;        /* value of VLD if bit2 in clock control is set */
341         int mn_diff;            /* difference between M/N Value + mn_diff = M/N Register */
342         int mn_min;             /* min value of M/N Value */
343         int mn_max;             /* max value of M/N Value */
344         int vco_min;            /* VCO Min in MHz */
345         int vco_max;            /* VCO Max in MHz */
346 };
347
348 static const struct ctfb_chips_properties chips[] = {
349         {PCI_DEVICE_ID_CT_69000, 0x200000, 1, 4, -2, 3, 257, 100, 220},
350         {PCI_DEVICE_ID_CT_65555, 0x100000, 16, 4, 0, 1, 255, 48, 220},  /* NOT TESTED */
351         {0, 0, 0, 0, 0, 0, 0, 0, 0}     /* Terminator */
352 };
353
354 /*************************************************
355  Video Modes:
356 Colours   640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200
357 --------+--------------------------------------------------------------
358  4 bits |    ?       ?     0x302      ?        ?        ?         ?
359  8 bits |  0x300   0x301   0x303    0x305    0x161    0x307     0x31C
360 15 bits |    ?     0x310   0x313    0x316    0x162    0x319     0x31D
361 16 bits |    ?     0x311   0x314    0x317    0x163    0x31A     0x31E
362 24 bits |    ?     0x312   0x315    0x318      ?      0x31B     0x31F
363 32 bits |    ?       ?       ?        ?      0x164      ?
364 */
365
366 #define RES_MODE_640x480        0
367 #define RES_MODE_800x600        1
368 #define RES_MODE_1024x768       2
369 #define RES_MODE_960_720        3
370 #define RES_MODE_1152x864       4
371 #define RES_MODES_COUNT         5
372
373 #define VESA_MODES_COUNT 15
374
375 static const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
376         {0x301, RES_MODE_640x480, 8},
377         {0x310, RES_MODE_640x480, 15},
378         {0x311, RES_MODE_640x480, 16},
379         {0x312, RES_MODE_640x480, 24},
380         {0x303, RES_MODE_800x600, 8},
381         {0x313, RES_MODE_800x600, 15},
382         {0x314, RES_MODE_800x600, 16},
383         {0x315, RES_MODE_800x600, 24},
384         {0x305, RES_MODE_1024x768, 8},
385         {0x316, RES_MODE_1024x768, 15},
386         {0x317, RES_MODE_1024x768, 16},
387         {0x318, RES_MODE_1024x768, 24},
388         {0x161, RES_MODE_1152x864, 8},
389         {0x162, RES_MODE_1152x864, 15},
390         {0x163, RES_MODE_1152x864, 16}
391 };
392
393 static const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
394         /* x     y pixclk   le  ri  up  lo   hs vs  s  vmode */
395         {640, 480, 39721, 40, 24, 32, 11, 96, 2, 0,
396          FB_VMODE_NONINTERLACED},
397         {800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},
398         {1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0,
399          FB_VMODE_NONINTERLACED},
400         {960, 720, 13100, 160, 40, 32, 8, 80, 4, 0,
401          FB_VMODE_NONINTERLACED},
402         {1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0,
403          FB_VMODE_NONINTERLACED}
404 };
405
406 /*
407  * The Graphic Device
408  */
409 GraphicDevice ctfb;
410
411 /*******************************************************************************
412 *
413 * Low Level Routines
414 */
415
416 /*******************************************************************************
417 *
418 * Read CT ISA register
419 */
420 #ifdef VGA_DEBUG
421 static unsigned char
422 ctRead (unsigned short index)
423 {
424         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
425         if (index == CT_AR_O)
426                 /* synch the Flip Flop */
427                 in8 (pGD->isaBase + CT_STATUS_REG1_O);
428
429         return (in8 (pGD->isaBase + index));
430 }
431 #endif
432 /*******************************************************************************
433 *
434 * Write CT ISA register
435 */
436 static void
437 ctWrite (unsigned short index, unsigned char val)
438 {
439         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
440
441         out8 ((pGD->isaBase + index), val);
442 }
443
444 /*******************************************************************************
445 *
446 * Read CT ISA register indexed
447 */
448 static unsigned char
449 ctRead_i (unsigned short index, char reg)
450 {
451         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
452         if (index == CT_AR_O)
453                 /* synch the Flip Flop */
454                 in8 (pGD->isaBase + CT_STATUS_REG1_O);
455         out8 ((pGD->isaBase + index), reg);
456         return (in8 (pGD->isaBase + index + 1));
457 }
458
459 /*******************************************************************************
460 *
461 * Write CT ISA register indexed
462 */
463 static void
464 ctWrite_i (unsigned short index, char reg, char val)
465 {
466         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
467         if (index == CT_AR_O) {
468                 /* synch the Flip Flop */
469                 in8 (pGD->isaBase + CT_STATUS_REG1_O);
470                 out8 ((pGD->isaBase + index), reg);
471                 out8 ((pGD->isaBase + index), val);
472         } else {
473                 out8 ((pGD->isaBase + index), reg);
474                 out8 ((pGD->isaBase + index + 1), val);
475         }
476 }
477
478 /*******************************************************************************
479 *
480 * Write a table of CT ISA register
481 */
482 static void
483 ctLoadRegs (unsigned short index, CT_CFG_TABLE * regTab)
484 {
485         while (regTab->reg != 0xFF) {
486                 ctWrite_i (index, regTab->reg, regTab->val);
487                 regTab++;
488         }
489 }
490
491 /*****************************************************************************/
492 static void
493 SetArRegs (void)
494 {
495         int i, tmp;
496
497         for (i = 0; i < 0x10; i++)
498                 ctWrite_i (CT_AR_O, i, i);
499         if (text)
500                 tmp = 0x04;
501         else
502                 tmp = 0x41;
503
504         ctWrite_i (CT_AR_O, 0x10, tmp); /* Mode Control Register */
505         ctWrite_i (CT_AR_O, 0x11, 0x00);        /* Overscan Color Register */
506         ctWrite_i (CT_AR_O, 0x12, 0x0f);        /* Memory Plane Enable Register */
507         if (fntwidth == 9)
508                 tmp = 0x08;
509         else
510                 tmp = 0x00;
511         ctWrite_i (CT_AR_O, 0x13, tmp); /* Horizontal Pixel Panning */
512         ctWrite_i (CT_AR_O, 0x14, 0x00);        /* Color Select Register    */
513         ctWrite (CT_AR_O, 0x20);        /* enable video             */
514 }
515
516 /*****************************************************************************/
517 static void
518 SetGrRegs (void)
519 {                               /* Set Graphics Mode */
520         int i;
521
522         for (i = 0; i < 0x05; i++)
523                 ctWrite_i (CT_GR_O, i, 0);
524         if (text) {
525                 ctWrite_i (CT_GR_O, 0x05, 0x10);
526                 ctWrite_i (CT_GR_O, 0x06, 0x02);
527         } else {
528                 ctWrite_i (CT_GR_O, 0x05, 0x40);
529                 ctWrite_i (CT_GR_O, 0x06, 0x05);
530         }
531         ctWrite_i (CT_GR_O, 0x07, 0x0f);
532         ctWrite_i (CT_GR_O, 0x08, 0xff);
533 }
534
535 /*****************************************************************************/
536 static void
537 SetSrRegs (void)
538 {
539         int tmp = 0;
540
541         ctWrite_i (CT_SR_O, 0x00, 0x00);        /* reset */
542         /*rr( sr, 0x01, tmp );
543            if( fntwidth == 8 ) tmp |= 0x01; else tmp &= ~0x01;
544            wr( sr, 0x01, tmp );  */
545         if (fntwidth == 8)
546                 ctWrite_i (CT_SR_O, 0x01, 0x01);        /* Clocking Mode Register */
547         else
548                 ctWrite_i (CT_SR_O, 0x01, 0x00);        /* Clocking Mode Register */
549         ctWrite_i (CT_SR_O, 0x02, 0x0f);        /* Enable CPU wr access to given memory plane */
550         ctWrite_i (CT_SR_O, 0x03, 0x00);        /* Character Map Select Register */
551         if (text)
552                 tmp = 0x02;
553         else
554                 tmp = 0x0e;
555         ctWrite_i (CT_SR_O, 0x04, tmp); /* Enable CPU accesses to the rest of the 256KB
556                                            total VGA memory beyond the first 64KB and set
557                                            fb mapping mode. */
558         ctWrite_i (CT_SR_O, 0x00, 0x03);        /* enable */
559 }
560
561 /*****************************************************************************/
562 static void
563 SetBitsPerPixelIntoXrRegs (int bpp)
564 {
565         unsigned int n = (bpp >> 3), tmp;       /* only for 15, 8, 16, 24 bpp */
566         static char md[4] = { 0x04, 0x02, 0x05, 0x06 }; /* DisplayColorMode */
567         static char off[4] = { ~0x20, ~0x30, ~0x20, ~0x10 };    /* mask */
568         static char on[4] = { 0x10, 0x00, 0x10, 0x20 }; /* mask */
569         if (bpp == 15)
570                 n = 0;
571         tmp = ctRead_i (CT_XR_O, 0x20);
572         tmp &= off[n];
573         tmp |= on[n];
574         ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
575         ctWrite_i (CT_XR_O, 0x81, md[n]);
576 }
577
578 /*****************************************************************************/
579 static void
580 SetCrRegs (struct ctfb_res_modes *var, int bits_per_pixel)
581 {                               /* he -le-   ht|0    hd -ri- hs     -h-      he */
582         unsigned char cr[0x7a];
583         int i, tmp;
584         unsigned int hd, hs, he, ht, hbe;       /* Horizontal.  */
585         unsigned int vd, vs, ve, vt;    /* vertical */
586         unsigned int bpp, wd, dblscan, interlaced, bcast, CrtHalfLine;
587         unsigned int CompSyncCharClkDelay, CompSyncPixelClkDelay;
588         unsigned int NTSC_PAL_HorizontalPulseWidth, BlDelayCtrl;
589         unsigned int HorizontalEqualizationPulses;
590         unsigned int HorizontalSerration1Start, HorizontalSerration2Start;
591
592         const int LineCompare = 0x3ff;
593         unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor   */
594         unsigned int RAMDAC_BlankPedestalEnable = 0;    /* 1=en-, 0=disable, see XR82 */
595
596         hd = (var->xres) / 8;   /* HDisp.  */
597         hs = (var->xres + var->right_margin) / 8;       /* HsStrt  */
598         he = (var->xres + var->right_margin + var->hsync_len) / 8;      /* HsEnd   */
599         ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8;   /* HTotal  */
600         hbe = ht - 1;           /* HBlankEnable todo docu wants ht here, but it does not work */
601         /* ve -up-  vt|0    vd -lo- vs     -v-      ve */
602         vd = var->yres;         /* VDisplay   */
603         vs = var->yres + var->lower_margin;     /* VSyncStart */
604         ve = var->yres + var->lower_margin + var->vsync_len;    /* VSyncEnd */
605         vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len;        /* VTotal  */
606         bpp = bits_per_pixel;
607         dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
608         interlaced = var->vmode & FB_VMODE_INTERLACED;
609         bcast = var->sync & FB_SYNC_BROADCAST;
610         CrtHalfLine = bcast ? (hd >> 1) : 0;
611         BlDelayCtrl = bcast ? 1 : 0;
612         CompSyncCharClkDelay = 0;       /* 2 bit */
613         CompSyncPixelClkDelay = 0;      /* 3 bit */
614         if (bcast) {
615                 NTSC_PAL_HorizontalPulseWidth = 7;      /*( var->hsync_len >> 1 ) + 1 */
616                 HorizontalEqualizationPulses = 0;       /* inverse value */
617                 HorizontalSerration1Start = 31; /* ( ht >> 1 ) */
618                 HorizontalSerration2Start = 89; /* ( ht >> 1 ) */
619         } else {
620                 NTSC_PAL_HorizontalPulseWidth = 0;
621                 /* 4 bit: hsync pulse width = ( ( CR74[4:0] - CR74[5] )
622                  * / 2 ) + 1 --> CR74[4:0] = 2*(hs-1) + CR74[5] */
623                 HorizontalEqualizationPulses = 1;       /* inverse value */
624                 HorizontalSerration1Start = 0;  /* ( ht >> 1 ) */
625                 HorizontalSerration2Start = 0;  /* ( ht >> 1 ) */
626         }
627
628         if (bpp == 15)
629                 bpp = 16;
630         wd = var->xres * bpp / 64;      /* double words per line */
631         if (interlaced) {       /* we divide all vertical timings, exept vd */
632                 vs >>= 1;
633                 ve >>= 1;
634                 vt >>= 1;
635         }
636         memset (cr, 0, sizeof (cr));
637         cr[0x00] = 0xff & (ht - 5);
638         cr[0x01] = hd - 1;      /* soll:4f ist 59 */
639         cr[0x02] = hd;
640         cr[0x03] = (hbe & 0x1F) | 0x80; /* hd + ht - hd  */
641         cr[0x04] = hs;
642         cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
643         cr[0x06] = (vt - 2) & 0xFF;
644         cr[0x30] = (vt - 2) >> 8;
645         cr[0x07] = ((vt & 0x100) >> 8)
646             | ((vd & 0x100) >> 7)
647             | ((vs & 0x100) >> 6)
648             | ((vs & 0x100) >> 5)
649             | ((LineCompare & 0x100) >> 4)
650             | ((vt & 0x200) >> 4)
651             | ((vd & 0x200) >> 3)
652             | ((vs & 0x200) >> 2);
653         cr[0x08] = 0x00;
654         cr[0x09] = (dblscan << 7)
655             | ((LineCompare & 0x200) >> 3)
656             | ((vs & 0x200) >> 4)
657             | (TextScanLines - 1);
658         cr[0x10] = vs & 0xff;   /* VSyncPulseStart */
659         cr[0x32] = (vs & 0xf00) >> 8;   /* VSyncPulseStart */
660         cr[0x11] = (ve & 0x0f); /* | 0x20;      */
661         cr[0x12] = (vd - 1) & 0xff;     /* LineCount  */
662         cr[0x31] = ((vd - 1) & 0xf00) >> 8;     /* LineCount */
663         cr[0x13] = wd & 0xff;
664         cr[0x41] = (wd & 0xf00) >> 8;
665         cr[0x15] = vs & 0xff;
666         cr[0x33] = (vs & 0xf00) >> 8;
667         cr[0x38] = (0x100 & (ht - 5)) >> 8;
668         cr[0x3C] = 0xc0 & hbe;
669         cr[0x16] = (vt - 1) & 0xff;     /* vbe - docu wants vt here, */
670         cr[0x17] = 0xe3;        /* but it does not work */
671         cr[0x18] = 0xff & LineCompare;
672         cr[0x22] = 0xff;        /* todo? */
673         cr[0x70] = interlaced ? (0x80 | CrtHalfLine) : 0x00;    /* check:0xa6  */
674         cr[0x71] = 0x80 | (RAMDAC_BlankPedestalEnable << 6)
675             | (BlDelayCtrl << 5)
676             | ((0x03 & CompSyncCharClkDelay) << 3)
677             | (0x07 & CompSyncPixelClkDelay);   /* todo: see XR82 */
678         cr[0x72] = HorizontalSerration1Start;
679         cr[0x73] = HorizontalSerration2Start;
680         cr[0x74] = (HorizontalEqualizationPulses << 5)
681             | NTSC_PAL_HorizontalPulseWidth;
682         /* todo: ct69000 has also 0x75-79 */
683         /* now set the registers */
684         for (i = 0; i <= 0x0d; i++) {   /*CR00 .. CR0D */
685                 ctWrite_i (CT_CR_O, i, cr[i]);
686         }
687         for (i = 0x10; i <= 0x18; i++) {        /*CR10 .. CR18 */
688                 ctWrite_i (CT_CR_O, i, cr[i]);
689         }
690         i = 0x22;               /*CR22 */
691         ctWrite_i (CT_CR_O, i, cr[i]);
692         for (i = 0x30; i <= 0x33; i++) {        /*CR30 .. CR33 */
693                 ctWrite_i (CT_CR_O, i, cr[i]);
694         }
695         i = 0x38;               /*CR38 */
696         ctWrite_i (CT_CR_O, i, cr[i]);
697         i = 0x3C;               /*CR3C */
698         ctWrite_i (CT_CR_O, i, cr[i]);
699         for (i = 0x40; i <= 0x41; i++) {        /*CR40 .. CR41 */
700                 ctWrite_i (CT_CR_O, i, cr[i]);
701         }
702         for (i = 0x70; i <= 0x74; i++) {        /*CR70 .. CR74 */
703                 ctWrite_i (CT_CR_O, i, cr[i]);
704         }
705         tmp = ctRead_i (CT_CR_O, 0x40);
706         tmp &= 0x0f;
707         tmp |= 0x80;
708         ctWrite_i (CT_CR_O, 0x40, tmp); /* StartAddressEnable */
709 }
710
711 /* pixelclock control */
712
713 /*****************************************************************************
714  We have a rational number p/q and need an m/n which is very close to p/q
715  but has m and n within mnmin and mnmax. We have no floating point in the
716  kernel. We can use long long without divide. And we have time to compute...
717 ******************************************************************************/
718 static unsigned int
719 FindBestPQFittingMN (unsigned int p, unsigned int q, unsigned int mnmin,
720                      unsigned int mnmax, unsigned int *pm, unsigned int *pn)
721 {
722         /* this code is not for general purpose usable but good for our number ranges */
723         unsigned int n = mnmin, m = 0;
724         long long int L = 0, P = p, Q = q, H = P >> 1;
725         long long int D = 0x7ffffffffffffffLL;
726         for (n = mnmin; n <= mnmax; n++) {
727                 m = mnmin;      /* p/q ~ m/n -> p*n ~ m*q -> p*n-x*q ~ 0 */
728                 L = P * n - m * Q;      /* n * vco - m * fref should be near 0 */
729                 while (L > 0 && m < mnmax) {
730                         L -= q; /* difference is greater as 0 subtract fref */
731                         m++;    /* and increment m */
732                 }
733                 /* difference is less or equal than 0 or m > maximum */
734                 if (m > mnmax)
735                         break;  /* no solution: if we increase n we get the same situation */
736                 /* L is <= 0 now */
737                 if (-L > H && m > mnmin) {      /* if difference > the half fref */
738                         L += q; /* we take the situation before */
739                         m--;    /* because its closer to 0 */
740                 }
741                 L = (L < 0) ? -L : +L;  /* absolute value */
742                 if (D < L)      /* if last difference was better take next n */
743                         continue;
744                 D = L;
745                 *pm = m;
746                 *pn = n;        /*  keep improved data */
747                 if (D == 0)
748                         break;  /* best result we can get */
749         }
750         return (unsigned int) (0xffffffff & D);
751 }
752
753 /* that is the hardware < 69000 we have to manage
754  +---------+  +-------------------+  +----------------------+  +--+
755  | REFCLK  |__|NTSC Divisor Select|__|FVCO Reference Divisor|__|÷N|__
756  | 14.3MHz |  |(NTSCDS) (÷1, Ã·5)  |  |Select (RDS) (÷1, Ã·4) |  |  |  |
757  +---------+  +-------------------+  +----------------------+  +--+  |
758   ___________________________________________________________________|
759  |
760  |                                    fvco                      fout
761  | +--------+  +------------+  +-----+     +-------------------+   +----+
762  +-| Phase  |__|Charge Pump |__| VCO |_____|Post Divisor (PD)  |___|CLK |--->
763  +-| Detect |  |& Filter VCO|  |     |  |  |÷1, 2, 4, 8, 16, 32|   |    |
764  | +--------+  +------------+  +-----+  |  +-------------------+   +----+
765  |                                      |
766  |    +--+   +---------------+          |
767  |____|÷M|___|VCO Loop Divide|__________|
768       |  |   |(VLD)(÷4, Ã·16) |
769       +--+   +---------------+
770 ****************************************************************************
771   that is the hardware >= 69000 we have to manage
772  +---------+  +--+
773  | REFCLK  |__|÷N|__
774  | 14.3MHz |  |  |  |
775  +---------+  +--+  |
776   __________________|
777  |
778  |                                    fvco                      fout
779  | +--------+  +------------+  +-----+     +-------------------+   +----+
780  +-| Phase  |__|Charge Pump |__| VCO |_____|Post Divisor (PD)  |___|CLK |--->
781  +-| Detect |  |& Filter VCO|  |     |  |  |÷1, 2, 4, 8, 16, 32|   |    |
782  | +--------+  +------------+  +-----+  |  +-------------------+   +----+
783  |                                      |
784  |    +--+   +---------------+          |
785  |____|÷M|___|VCO Loop Divide|__________|
786       |  |   |(VLD)(÷1, Ã·4)  |
787       +--+   +---------------+
788
789
790 */
791
792 #define VIDEO_FREF 14318180;    /* Hz  */
793 /*****************************************************************************/
794 static int
795 ReadPixClckFromXrRegsBack (struct ctfb_chips_properties *param)
796 {
797         unsigned int m, n, vld, pd, PD, fref, xr_cb, i, pixclock;
798         i = 0;
799         pixclock = -1;
800         fref = VIDEO_FREF;
801         m = ctRead_i (CT_XR_O, 0xc8);
802         n = ctRead_i (CT_XR_O, 0xc9);
803         m -= param->mn_diff;
804         n -= param->mn_diff;
805         xr_cb = ctRead_i (CT_XR_O, 0xcb);
806         PD = (0x70 & xr_cb) >> 4;
807         pd = 1;
808         for (i = 0; i < PD; i++) {
809                 pd *= 2;
810         }
811         vld = (0x04 & xr_cb) ? param->vld_set : param->vld_not_set;
812         if (n * vld * m) {
813                 unsigned long long p = 1000000000000LL * pd * n;
814                 unsigned long long q = (long long) fref * vld * m;
815                 while ((p > 0xffffffffLL) || (q > 0xffffffffLL)) {
816                         p >>= 1;        /* can't divide with long long so we scale down */
817                         q >>= 1;
818                 }
819                 pixclock = (unsigned) p / (unsigned) q;
820         } else
821                 printf ("Invalid data in xr regs.\n");
822         return pixclock;
823 }
824
825 /*****************************************************************************/
826 static void
827 FindAndSetPllParamIntoXrRegs (unsigned int pixelclock,
828                               struct ctfb_chips_properties *param)
829 {
830         unsigned int m, n, vld, pd, PD, fref, xr_cb;
831         unsigned int fvcomin, fvcomax, pclckmin, pclckmax, pclk;
832         unsigned int pfreq, fvco, new_pixclock;
833
834         fref = VIDEO_FREF;
835         pd = 1;
836         PD = 0;
837         fvcomin = param->vco_min;
838         fvcomax = param->vco_max;       /* MHz */
839         pclckmin = 1000000 / fvcomax + 1;       /*   4546 */
840         pclckmax = 32000000 / fvcomin - 1;      /* 666665 */
841         pclk = minmax (pclckmin, pixelclock, pclckmax); /* ps pp */
842         pfreq = 250 * (4000000000U / pclk);
843         fvco = pfreq;           /* Hz */
844         new_pixclock = 0;
845         while (fvco < fvcomin * 1000000) {
846                 /* double VCO starting with the pixelclock frequency
847                  * as long as it is lower than the minimal VCO frequency */
848                 fvco *= 2;
849                 pd *= 2;
850                 PD++;
851         }
852         /* fvco is exactly pd * pixelclock and higher than the ninmal VCO frequency */
853         vld = (param->vld_set > param->vld_not_set) ?
854             param->vld_not_set : param->vld_set;
855         /* start with lower VLD (higher VLD is NOT yet implemented */
856         FindBestPQFittingMN (fvco / vld, fref, param->mn_min, param->mn_max, &m, &n);   /* rds = 1 */
857         m += param->mn_diff;
858         n += param->mn_diff;
859         PRINTF ("VCO %d, pd %d, m %d n %d vld %d \n", fvco, pd, m, n, vld);
860         xr_cb = ((0x7 & PD) << 4) | (vld == param->vld_set ? 0x04 : 0);
861         /* All four of the registers used for dot clock 2 (XRC8 - XRCB) must be
862          * written, and in order from XRC8 to XRCB, before the hardware will
863          * update the synthesizer s settings.
864          */
865         ctWrite_i (CT_XR_O, 0xc8, m);
866         ctWrite_i (CT_XR_O, 0xc9, n);   /* xrca does not exist in CT69000 and CT69030 */
867         ctWrite_i (CT_XR_O, 0xca, 0);   /* because of a hw bug I guess, but we write */
868         ctWrite_i (CT_XR_O, 0xcb, xr_cb);       /* 0 to it for savety */
869         new_pixclock = ReadPixClckFromXrRegsBack (param);
870         PRINTF ("pixelclock.set = %d, pixelclock.real = %d \n",
871                 pixelclock, new_pixclock);
872 }
873
874 /*****************************************************************************/
875 static void
876 SetMsrRegs (struct ctfb_res_modes *mode)
877 {
878         unsigned char h_synch_high, v_synch_high;
879
880         h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40;  /* horizontal Synch High active */
881         v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
882         ctWrite (CT_MSR_W_O, (h_synch_high | v_synch_high | 0x29));
883         /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
884          * Selects the upper 64KB page.Bit5=1
885          * CLK2 (left reserved in standard VGA) Bit3|2=1|0
886          * Disables CPU access to frame buffer. Bit1=0
887          * Sets the I/O address decode for ST01, FCR, and all CR registers
888          * to the 3Dx I/O address range (CGA emulation). Bit0=1
889          */
890 }
891
892 /************************************************************************************/
893 #ifdef VGA_DUMP_REG
894
895 static void
896 ctDispRegs (unsigned short index, int from, int to)
897 {
898         unsigned char status;
899         int i;
900
901         for (i = from; i < to; i++) {
902                 status = ctRead_i (index, i);
903                 printf ("%02X: is %02X\n", i, status);
904         }
905 }
906
907 void
908 video_dump_reg (void)
909 {
910         int i;
911
912         printf ("Extended Regs:\n");
913         ctDispRegs (CT_XR_O, 0, 0xC);
914         ctDispRegs (CT_XR_O, 0xe, 0xf);
915         ctDispRegs (CT_XR_O, 0x20, 0x21);
916         ctDispRegs (CT_XR_O, 0x40, 0x50);
917         ctDispRegs (CT_XR_O, 0x60, 0x64);
918         ctDispRegs (CT_XR_O, 0x67, 0x68);
919         ctDispRegs (CT_XR_O, 0x70, 0x72);
920         ctDispRegs (CT_XR_O, 0x80, 0x83);
921         ctDispRegs (CT_XR_O, 0xA0, 0xB0);
922         ctDispRegs (CT_XR_O, 0xC0, 0xD3);
923         printf ("Sequencer Regs:\n");
924         ctDispRegs (CT_SR_O, 0, 0x8);
925         printf ("Graphic Regs:\n");
926         ctDispRegs (CT_GR_O, 0, 0x9);
927         printf ("CRT Regs:\n");
928         ctDispRegs (CT_CR_O, 0, 0x19);
929         ctDispRegs (CT_CR_O, 0x22, 0x23);
930         ctDispRegs (CT_CR_O, 0x30, 0x34);
931         ctDispRegs (CT_CR_O, 0x38, 0x39);
932         ctDispRegs (CT_CR_O, 0x3C, 0x3D);
933         ctDispRegs (CT_CR_O, 0x40, 0x42);
934         ctDispRegs (CT_CR_O, 0x70, 0x80);
935         /* don't display the attributes */
936 }
937
938 #endif
939
940 #ifdef CONFIG_VIDEO_HW_CURSOR
941 /***************************************************************
942  * Set Hardware Cursor in Pixel
943  */
944 void
945 video_set_hw_cursor (int x, int y)
946 {
947         int sig_x = 0, sig_y = 0;
948         if (x < 0) {
949                 x *= -1;
950                 sig_x = 1;
951         }
952         if (y < 0) {
953                 y *= -1;
954                 sig_y = 1;
955         }
956         ctWrite_i (CT_XR_O, 0xa4, x & 0xff);
957         ctWrite_i (CT_XR_O, 0xa5, (x >> 8) & 0x7);
958         ctWrite_i (CT_XR_O, 0xa6, y & 0xff);
959         ctWrite_i (CT_XR_O, 0xa7, (y >> 8) & 0x7);
960 }
961
962 /***************************************************************
963  * Init Hardware Cursor. To know the size of the Cursor,
964  * we have to know the Font size.
965  */
966 void
967 video_init_hw_cursor (int font_width, int font_height)
968 {
969         unsigned char xr_80;
970         unsigned long *curs, pattern;
971         int i;
972         int cursor_start;
973         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
974
975         cursor_start = pGD->dprBase;
976         xr_80 = ctRead_i (CT_XR_O, 0x80);
977         /* set start address */
978         ctWrite_i (CT_XR_O, 0xa2, (cursor_start >> 8) & 0xf0);
979         ctWrite_i (CT_XR_O, 0xa3, (cursor_start >> 16) & 0x3f);
980         /* set cursor shape */
981         curs = (unsigned long *) cursor_start;
982         i = 0;
983         while (i < 0x400) {
984                 curs[i++] = 0xffffffff; /* AND mask */
985                 curs[i++] = 0xffffffff; /* AND mask */
986                 curs[i++] = 0;  /* XOR mask */
987                 curs[i++] = 0;  /* XOR mask */
988                 /* Transparent */
989         }
990         pattern = 0xffffffff >> font_width;
991         i = 0;
992         while (i < (font_height * 2)) {
993                 curs[i++] = pattern;    /* AND mask */
994                 curs[i++] = pattern;    /* AND mask */
995                 curs[i++] = 0;  /* XOR mask */
996                 curs[i++] = 0;  /* XOR mask */
997                 /* Cursor Color 0 */
998         }
999         /* set blink rate */
1000         ctWrite_i (CT_FP_O, 0x19, 0xf);
1001
1002         /* set cursors colors */
1003         xr_80 = ctRead_i (CT_XR_O, 0x80);
1004         xr_80 |= 0x1;           /* alternate palette select */
1005         ctWrite_i (CT_XR_O, 0x80, xr_80);
1006         video_set_lut (4, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
1007         /* position 4 is color 0 cursor 0 */
1008         xr_80 &= 0xfe;          /* normal palette select */
1009         ctWrite_i (CT_XR_O, 0x80, xr_80);
1010         /* cursor enable */
1011         ctWrite_i (CT_XR_O, 0xa0, 0x91);
1012         xr_80 |= 0x10;          /* enable hwcursor */
1013         ctWrite_i (CT_XR_O, 0x80, xr_80);
1014         video_set_hw_cursor (0, 0);
1015 }
1016 #endif                          /* CONFIG_VIDEO_HW_CURSOR */
1017
1018 /***************************************************************
1019  * Wait for BitBlt ready
1020  */
1021 static int
1022 video_wait_bitblt (unsigned long addr)
1023 {
1024         unsigned long br04;
1025         int i = 0;
1026         br04 = in32r (addr);
1027         while (br04 & 0x80000000) {
1028                 udelay (1);
1029                 br04 = in32r (addr);
1030                 if (i++ > 1000000) {
1031                         printf ("ERROR Timeout %lx\n", br04);
1032                         return 1;
1033                 }
1034         }
1035         return 0;
1036 }
1037
1038 /***************************************************************
1039  * Set up BitBlt Registrs
1040  */
1041 static void
1042 SetDrawingEngine (int bits_per_pixel)
1043 {
1044         unsigned long br04, br00;
1045         unsigned char tmp;
1046
1047         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1048
1049         tmp = ctRead_i (CT_XR_O, 0x20); /* BitBLT Configuration */
1050         tmp |= 0x02;            /* reset BitBLT */
1051         ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
1052         udelay (10);
1053         tmp &= 0xfd;            /* release reset BitBLT */
1054         ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
1055         video_wait_bitblt (pGD->pciBase + BR04_o);
1056
1057         /* set pattern Address */
1058         out32r (pGD->pciBase + BR05_o, PATTERN_ADR & 0x003ffff8);
1059         br04 = 0;
1060         if (bits_per_pixel == 1) {
1061                 br04 |= 0x00040000;     /* monochome Pattern */
1062                 br04 |= 0x00001000;     /* monochome source */
1063         }
1064         br00 = ((pGD->winSizeX * pGD->gdfBytesPP) << 16) + (pGD->winSizeX * pGD->gdfBytesPP);   /* bytes per scanline */
1065         out32r (pGD->pciBase + BR00_o, br00);   /* */
1066         out32r (pGD->pciBase + BR08_o, (10 << 16) + 10);        /* dummy */
1067         out32r (pGD->pciBase + BR04_o, br04);   /* write all 0 */
1068         out32r (pGD->pciBase + BR07_o, 0);      /* destination */
1069         video_wait_bitblt (pGD->pciBase + BR04_o);
1070 }
1071
1072 /************************************************************************
1073  * Get Parameters for the video mode:
1074  */
1075 /*********************************************************************
1076  * returns the length to the next seperator
1077  */
1078 static int
1079 video_get_param_len (char *start, char sep)
1080 {
1081         int i = 0;
1082         while ((*start != 0) && (*start != sep)) {
1083                 start++;
1084                 i++;
1085         }
1086         return i;
1087 }
1088
1089 static int
1090 video_search_param (char *start, char *param)
1091 {
1092         int len, totallen, i;
1093         char *p = start;
1094         len = strlen (param);
1095         totallen = len + strlen (start);
1096         for (i = 0; i < totallen; i++) {
1097                 if (strncmp (p++, param, len) == 0)
1098                         return (i);
1099         }
1100         return -1;
1101 }
1102
1103 /***************************************************************
1104 * Get parameter via the environment as it is done for the
1105 * linux kernel i.e:
1106 * video=ctfb:x:800,xv:1280,y:600,yv:1024,depth:16,mode:0,pclk:25000,
1107 *       le:56,ri:48,up:26,lo:5,hs:152,vs:2,sync:0,vmode:0,accel:0
1108 *
1109 * penv is a pointer to the environment, containing the string, or the name of
1110 * another environment variable. It could even be the term "bootargs"
1111 */
1112
1113 #define GET_OPTION(name,var)                            \
1114                 if(strncmp(p,name,strlen(name))==0) {   \
1115                         val_s=p+strlen(name);           \
1116                         var=simple_strtoul(val_s, NULL, 10); \
1117                 }
1118
1119 static int
1120 video_get_params (struct ctfb_res_modes *pPar, char *penv)
1121 {
1122         char *p, *s, *val_s;
1123         int i = 0, t;
1124         int bpp;
1125         int mode;
1126         /* first search for the environment containing the real param string */
1127         s = penv;
1128         if ((p = getenv (s)) != NULL) {
1129                 s = p;
1130         }
1131         /* in case of the bootargs line, we have to start
1132          * after "video=ctfb:"
1133          */
1134         i = video_search_param (s, "video=ctfb:");
1135         if (i >= 0) {
1136                 s += i;
1137                 s += strlen ("video=ctfb:");
1138         }
1139         /* search for mode as a default value */
1140         p = s;
1141         t = 0;
1142         mode = 0;               /* default */
1143         while ((i = video_get_param_len (p, ',')) != 0) {
1144                 GET_OPTION ("mode:", mode)
1145                     p += i;
1146                 if (*p != 0)
1147                         p++;    /* skip ',' */
1148         }
1149         if (mode >= RES_MODES_COUNT)
1150                 mode = 0;
1151         *pPar = res_mode_init[mode];    /* copy default values */
1152         bpp = 24 - ((mode % 3) * 8);
1153         p = s;                  /* restart */
1154         while ((i = video_get_param_len (p, ',')) != 0) {
1155                 GET_OPTION ("x:", pPar->xres)
1156                     GET_OPTION ("y:", pPar->yres)
1157                     GET_OPTION ("le:", pPar->left_margin)
1158                     GET_OPTION ("ri:", pPar->right_margin)
1159                     GET_OPTION ("up:", pPar->upper_margin)
1160                     GET_OPTION ("lo:", pPar->lower_margin)
1161                     GET_OPTION ("hs:", pPar->hsync_len)
1162                     GET_OPTION ("vs:", pPar->vsync_len)
1163                     GET_OPTION ("sync:", pPar->sync)
1164                     GET_OPTION ("vmode:", pPar->vmode)
1165                     GET_OPTION ("pclk:", pPar->pixclock)
1166                     GET_OPTION ("depth:", bpp)
1167                     p += i;
1168                 if (*p != 0)
1169                         p++;    /* skip ',' */
1170         }
1171         return bpp;
1172 }
1173
1174 /****************************************************************************
1175 * supported Video Chips
1176 */
1177 static struct pci_device_id supported[] = {
1178         {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000},
1179         {}
1180 };
1181
1182 /*******************************************************************************
1183 *
1184 * Init video chip
1185 */
1186 void *
1187 video_hw_init (void)
1188 {
1189         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1190         unsigned short device_id;
1191         pci_dev_t devbusfn;
1192         int videomode;
1193         unsigned long t1, hsynch, vsynch;
1194         unsigned int pci_mem_base, *vm;
1195         int tmp, i, bits_per_pixel;
1196         char *penv;
1197         struct ctfb_res_modes *res_mode;
1198         struct ctfb_res_modes var_mode;
1199         struct ctfb_chips_properties *chips_param;
1200         /* Search for video chip */
1201
1202         if ((devbusfn = pci_find_devices (supported, 0)) < 0) {
1203 #ifdef CONFIG_VIDEO_ONBOARD
1204                 printf ("Video: Controller not found !\n");
1205 #endif
1206                 return (NULL);
1207         }
1208
1209         /* PCI setup */
1210         pci_write_config_dword (devbusfn, PCI_COMMAND,
1211                                 (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
1212         pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
1213         pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
1214         pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
1215
1216         /* get chips params */
1217         for (chips_param = (struct ctfb_chips_properties *) &chips[0];
1218              chips_param->device_id != 0; chips_param++) {
1219                 if (chips_param->device_id == device_id)
1220                         break;
1221         }
1222         if (chips_param->device_id == 0) {
1223 #ifdef CONFIG_VIDEO_ONBOARD
1224                 printf ("Video: controller 0x%X not supported\n", device_id);
1225 #endif
1226                 return NULL;
1227         }
1228         /* supported Video controller found */
1229         printf ("Video: ");
1230
1231         tmp = 0;
1232         videomode = 0x301;
1233         /* get video mode via environment */
1234         if ((penv = getenv ("videomode")) != NULL) {
1235                 /* deceide if it is a string */
1236                 if (penv[0] <= '9') {
1237                         videomode = (int) simple_strtoul (penv, NULL, 16);
1238                         tmp = 1;
1239                 }
1240         } else {
1241                 tmp = 1;
1242         }
1243         if (tmp) {
1244                 /* parameter are vesa modes */
1245                 /* search params */
1246                 for (i = 0; i < VESA_MODES_COUNT; i++) {
1247                         if (vesa_modes[i].vesanr == videomode)
1248                                 break;
1249                 }
1250                 if (i == VESA_MODES_COUNT) {
1251                         printf ("no VESA Mode found, switching to mode 0x301 ");
1252                         i = 0;
1253                 }
1254                 res_mode =
1255                     (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
1256                                                              resindex];
1257                 bits_per_pixel = vesa_modes[i].bits_per_pixel;
1258         } else {
1259
1260                 res_mode = (struct ctfb_res_modes *) &var_mode;
1261                 bits_per_pixel = video_get_params (res_mode, penv);
1262         }
1263
1264         /* calculate available color depth for controller memory */
1265         if (bits_per_pixel == 15)
1266                 tmp = 2;
1267         else
1268                 tmp = bits_per_pixel >> 3;      /* /8 */
1269         if (((chips_param->max_mem -
1270               ACCELMEMORY) / (res_mode->xres * res_mode->yres)) < tmp) {
1271                 tmp =
1272                     ((chips_param->max_mem -
1273                       ACCELMEMORY) / (res_mode->xres * res_mode->yres));
1274                 if (tmp == 0) {
1275                         printf
1276                             ("No matching videomode found .-> reduce resolution\n");
1277                         return NULL;
1278                 } else {
1279                         printf ("Switching back to %d Bits per Pixel ",
1280                                 tmp << 3);
1281                         bits_per_pixel = tmp << 3;
1282                 }
1283         }
1284
1285         /* calculate hsynch and vsynch freq (info only) */
1286         t1 = (res_mode->left_margin + res_mode->xres +
1287               res_mode->right_margin + res_mode->hsync_len) / 8;
1288         t1 *= 8;
1289         t1 *= res_mode->pixclock;
1290         t1 /= 1000;
1291         hsynch = 1000000000L / t1;
1292         t1 *=
1293             (res_mode->upper_margin + res_mode->yres +
1294              res_mode->lower_margin + res_mode->vsync_len);
1295         t1 /= 1000;
1296         vsynch = 1000000000L / t1;
1297
1298         /* fill in Graphic device struct */
1299         sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
1300                  res_mode->yres, bits_per_pixel, (hsynch / 1000),
1301                  (vsynch / 1000));
1302         printf ("%s\n", pGD->modeIdent);
1303         pGD->winSizeX = res_mode->xres;
1304         pGD->winSizeY = res_mode->yres;
1305         pGD->plnSizeX = res_mode->xres;
1306         pGD->plnSizeY = res_mode->yres;
1307         switch (bits_per_pixel) {
1308         case 8:
1309                 pGD->gdfBytesPP = 1;
1310                 pGD->gdfIndex = GDF__8BIT_INDEX;
1311                 break;
1312         case 15:
1313                 pGD->gdfBytesPP = 2;
1314                 pGD->gdfIndex = GDF_15BIT_555RGB;
1315                 break;
1316         case 16:
1317                 pGD->gdfBytesPP = 2;
1318                 pGD->gdfIndex = GDF_16BIT_565RGB;
1319                 break;
1320         case 24:
1321                 pGD->gdfBytesPP = 3;
1322                 pGD->gdfIndex = GDF_24BIT_888RGB;
1323                 break;
1324         }
1325         pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
1326         pGD->pciBase = pci_mem_base;
1327         pGD->frameAdrs = pci_mem_base;
1328         pGD->memSize = chips_param->max_mem;
1329         /* Cursor Start Address */
1330         pGD->dprBase =
1331             (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + pci_mem_base;
1332         if ((pGD->dprBase & 0x0fff) != 0) {
1333                 /* allign it */
1334                 pGD->dprBase &= 0xfffff000;
1335                 pGD->dprBase += 0x00001000;
1336         }
1337         PRINTF ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
1338                 PATTERN_ADR);
1339         pGD->vprBase = pci_mem_base;    /* Dummy */
1340         pGD->cprBase = pci_mem_base;    /* Dummy */
1341         /* set up Hardware */
1342
1343         ctWrite (CT_MSR_W_O, 0x01);
1344
1345         /* set the extended Registers */
1346         ctLoadRegs (CT_XR_O, xreg);
1347         /* set atribute registers */
1348         SetArRegs ();
1349         /* set Graphics register */
1350         SetGrRegs ();
1351         /* set sequencer */
1352         SetSrRegs ();
1353
1354         /* set msr */
1355         SetMsrRegs (res_mode);
1356
1357         /* set CRT Registers */
1358         SetCrRegs (res_mode, bits_per_pixel);
1359         /* set color mode */
1360         SetBitsPerPixelIntoXrRegs (bits_per_pixel);
1361
1362         /* set PLL */
1363         FindAndSetPllParamIntoXrRegs (res_mode->pixclock, chips_param);
1364
1365         ctWrite_i (CT_SR_O, 0, 0x03);   /* clear synchronous reset */
1366         /* Clear video memory */
1367         i = pGD->memSize / 4;
1368         vm = (unsigned int *) pGD->pciBase;
1369         while (i--)
1370                 *vm++ = 0;
1371         SetDrawingEngine (bits_per_pixel);
1372 #ifdef VGA_DUMP_REG
1373         video_dump_reg ();
1374 #endif
1375
1376         return ((void *) &ctfb);
1377 }
1378
1379  /*******************************************************************************
1380 *
1381 * Set a RGB color in the LUT (8 bit index)
1382 */
1383 void
1384 video_set_lut (unsigned int index,      /* color number */
1385                unsigned char r, /* red */
1386                unsigned char g, /* green */
1387                unsigned char b  /* blue */
1388     )
1389 {
1390
1391         ctWrite (CT_LUT_MASK_O, 0xff);
1392
1393         ctWrite (CT_LUT_START_O, (char) index);
1394
1395         ctWrite (CT_LUT_RGB_O, r);      /* red */
1396         ctWrite (CT_LUT_RGB_O, g);      /* green */
1397         ctWrite (CT_LUT_RGB_O, b);      /* blue */
1398         udelay (1);
1399         ctWrite (CT_LUT_MASK_O, 0xff);
1400 }
1401
1402 /*******************************************************************************
1403 *
1404 * Drawing engine fill on screen region
1405 */
1406 void
1407 video_hw_rectfill (unsigned int bpp,    /* bytes per pixel */
1408                    unsigned int dst_x,  /* dest pos x */
1409                    unsigned int dst_y,  /* dest pos y */
1410                    unsigned int dim_x,  /* frame width */
1411                    unsigned int dim_y,  /* frame height */
1412                    unsigned int color   /* fill color */
1413     )
1414 {
1415         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1416         unsigned long *p, br04;
1417
1418         video_wait_bitblt (pGD->pciBase + BR04_o);
1419
1420         p = (unsigned long *) PATTERN_ADR;
1421         dim_x *= bpp;
1422         if (bpp == 3)
1423                 bpp++;          /* 24Bit needs a 32bit pattern */
1424         memset (p, color, (bpp * sizeof (unsigned char) * 8 * 8));      /* 8 x 8 pattern data */
1425         out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP);    /* destination */
1426         br04 = in32r (pGD->pciBase + BR04_o) & 0xffffff00;
1427         br04 |= 0xF0;           /* write Pattern P -> D */
1428         out32r (pGD->pciBase + BR04_o, br04);   /* */
1429         out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x);  /* starts the BITBlt */
1430         video_wait_bitblt (pGD->pciBase + BR04_o);
1431 }
1432
1433 /*******************************************************************************
1434 *
1435 * Drawing engine bitblt with screen region
1436 */
1437 void
1438 video_hw_bitblt (unsigned int bpp,      /* bytes per pixel */
1439                  unsigned int src_x,    /* source pos x */
1440                  unsigned int src_y,    /* source pos y */
1441                  unsigned int dst_x,    /* dest pos x */
1442                  unsigned int dst_y,    /* dest pos y */
1443                  unsigned int dim_x,    /* frame width */
1444                  unsigned int dim_y     /* frame height */
1445     )
1446 {
1447         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1448         unsigned long br04;
1449
1450         br04 = in32r (pGD->pciBase + BR04_o);
1451
1452         /* to prevent data corruption due to overlap, we have to
1453          * find out if, and how the frames overlaps */
1454         if (src_x < dst_x) {
1455                 /* src is more left than dest
1456                  * the frame may overlap -> start from right to left */
1457                 br04 |= 0x00000100;     /* set bit 8 */
1458                 src_x += dim_x;
1459                 dst_x += dim_x;
1460         } else {
1461                 br04 &= 0xfffffeff;     /* clear bit 8 left to right */
1462         }
1463         if (src_y < dst_y) {
1464                 /* src is higher than dst
1465                  * the frame may overlap => start from bottom */
1466                 br04 |= 0x00000200;     /* set bit 9 */
1467                 src_y += dim_y;
1468                 dst_y += dim_y;
1469         } else {
1470                 br04 &= 0xfffffdff;     /* clear bit 9 top to bottom */
1471         }
1472         dim_x *= bpp;
1473         out32r (pGD->pciBase + BR06_o, ((pGD->winSizeX * src_y) + src_x) * pGD->gdfBytesPP);    /* source */
1474         out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP);    /* destination */
1475         br04 &= 0xffffff00;
1476         br04 |= 0x000000CC;     /* S -> D */
1477         out32r (pGD->pciBase + BR04_o, br04);   /* */
1478         out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x);  /* start the BITBlt */
1479         video_wait_bitblt (pGD->pciBase + BR04_o);
1480 }
1481
1482 #endif                          /* CONFIG_CT69000 */
1483
1484 #endif                          /* CONFIG_VIDEO */