]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/ct69000.c
Add support for CompactFlash on ATC board
[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         unsigned int D,nback,mback;
834
835         fref = VIDEO_FREF;
836         pd = 1;
837         PD = 0;
838         fvcomin = param->vco_min;
839         fvcomax = param->vco_max;       /* MHz */
840         pclckmin = 1000000 / fvcomax + 1;       /*   4546 */
841         pclckmax = 32000000 / fvcomin - 1;      /* 666665 */
842         pclk = minmax (pclckmin, pixelclock, pclckmax); /* ps pp */
843         pfreq = 250 * (4000000000U / pclk);
844         fvco = pfreq;           /* Hz */
845         new_pixclock = 0;
846         while (fvco < fvcomin * 1000000) {
847                 /* double VCO starting with the pixelclock frequency
848                  * as long as it is lower than the minimal VCO frequency */
849                 fvco *= 2;
850                 pd *= 2;
851                 PD++;
852         }
853         /* fvco is exactly pd * pixelclock and higher than the ninmal VCO frequency */
854         /* first try */
855         vld = param->vld_set;
856         D=FindBestPQFittingMN (fvco / vld, fref, param->mn_min, param->mn_max, &m, &n); /* rds = 1 */
857         mback=m;
858         nback=n;
859         /* second try */
860         vld = param->vld_not_set;
861         if(D<FindBestPQFittingMN (fvco / vld, fref, param->mn_min, param->mn_max, &m, &n)) {    /* rds = 1 */
862                 /* first try was better */
863                 m=mback;
864                 n=nback;
865                 vld = param->vld_set;
866         }
867         m += param->mn_diff;
868         n += param->mn_diff;
869         PRINTF ("VCO %d, pd %d, m %d n %d vld %d \n", fvco, pd, m, n, vld);
870         xr_cb = ((0x7 & PD) << 4) | (vld == param->vld_set ? 0x04 : 0);
871         /* All four of the registers used for dot clock 2 (XRC8 - XRCB) must be
872          * written, and in order from XRC8 to XRCB, before the hardware will
873          * update the synthesizer s settings.
874          */
875         ctWrite_i (CT_XR_O, 0xc8, m);
876         ctWrite_i (CT_XR_O, 0xc9, n);   /* xrca does not exist in CT69000 and CT69030 */
877         ctWrite_i (CT_XR_O, 0xca, 0);   /* because of a hw bug I guess, but we write */
878         ctWrite_i (CT_XR_O, 0xcb, xr_cb);       /* 0 to it for savety */
879         new_pixclock = ReadPixClckFromXrRegsBack (param);
880         PRINTF ("pixelclock.set = %d, pixelclock.real = %d \n",
881                 pixelclock, new_pixclock);
882 }
883
884 /*****************************************************************************/
885 static void
886 SetMsrRegs (struct ctfb_res_modes *mode)
887 {
888         unsigned char h_synch_high, v_synch_high;
889
890         h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40;  /* horizontal Synch High active */
891         v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
892         ctWrite (CT_MSR_W_O, (h_synch_high | v_synch_high | 0x29));
893         /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
894          * Selects the upper 64KB page.Bit5=1
895          * CLK2 (left reserved in standard VGA) Bit3|2=1|0
896          * Disables CPU access to frame buffer. Bit1=0
897          * Sets the I/O address decode for ST01, FCR, and all CR registers
898          * to the 3Dx I/O address range (CGA emulation). Bit0=1
899          */
900 }
901
902 /************************************************************************************/
903 #ifdef VGA_DUMP_REG
904
905 static void
906 ctDispRegs (unsigned short index, int from, int to)
907 {
908         unsigned char status;
909         int i;
910
911         for (i = from; i < to; i++) {
912                 status = ctRead_i (index, i);
913                 printf ("%02X: is %02X\n", i, status);
914         }
915 }
916
917 void
918 video_dump_reg (void)
919 {
920         int i;
921
922         printf ("Extended Regs:\n");
923         ctDispRegs (CT_XR_O, 0, 0xC);
924         ctDispRegs (CT_XR_O, 0xe, 0xf);
925         ctDispRegs (CT_XR_O, 0x20, 0x21);
926         ctDispRegs (CT_XR_O, 0x40, 0x50);
927         ctDispRegs (CT_XR_O, 0x60, 0x64);
928         ctDispRegs (CT_XR_O, 0x67, 0x68);
929         ctDispRegs (CT_XR_O, 0x70, 0x72);
930         ctDispRegs (CT_XR_O, 0x80, 0x83);
931         ctDispRegs (CT_XR_O, 0xA0, 0xB0);
932         ctDispRegs (CT_XR_O, 0xC0, 0xD3);
933         printf ("Sequencer Regs:\n");
934         ctDispRegs (CT_SR_O, 0, 0x8);
935         printf ("Graphic Regs:\n");
936         ctDispRegs (CT_GR_O, 0, 0x9);
937         printf ("CRT Regs:\n");
938         ctDispRegs (CT_CR_O, 0, 0x19);
939         ctDispRegs (CT_CR_O, 0x22, 0x23);
940         ctDispRegs (CT_CR_O, 0x30, 0x34);
941         ctDispRegs (CT_CR_O, 0x38, 0x39);
942         ctDispRegs (CT_CR_O, 0x3C, 0x3D);
943         ctDispRegs (CT_CR_O, 0x40, 0x42);
944         ctDispRegs (CT_CR_O, 0x70, 0x80);
945         /* don't display the attributes */
946 }
947
948 #endif
949
950 #ifdef CONFIG_VIDEO_HW_CURSOR
951 /***************************************************************
952  * Set Hardware Cursor in Pixel
953  */
954 void
955 video_set_hw_cursor (int x, int y)
956 {
957         int sig_x = 0, sig_y = 0;
958         if (x < 0) {
959                 x *= -1;
960                 sig_x = 1;
961         }
962         if (y < 0) {
963                 y *= -1;
964                 sig_y = 1;
965         }
966         ctWrite_i (CT_XR_O, 0xa4, x & 0xff);
967         ctWrite_i (CT_XR_O, 0xa5, (x >> 8) & 0x7);
968         ctWrite_i (CT_XR_O, 0xa6, y & 0xff);
969         ctWrite_i (CT_XR_O, 0xa7, (y >> 8) & 0x7);
970 }
971
972 /***************************************************************
973  * Init Hardware Cursor. To know the size of the Cursor,
974  * we have to know the Font size.
975  */
976 void
977 video_init_hw_cursor (int font_width, int font_height)
978 {
979         unsigned char xr_80;
980         unsigned long *curs, pattern;
981         int i;
982         int cursor_start;
983         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
984
985         cursor_start = pGD->dprBase;
986         xr_80 = ctRead_i (CT_XR_O, 0x80);
987         /* set start address */
988         ctWrite_i (CT_XR_O, 0xa2, (cursor_start >> 8) & 0xf0);
989         ctWrite_i (CT_XR_O, 0xa3, (cursor_start >> 16) & 0x3f);
990         /* set cursor shape */
991         curs = (unsigned long *) cursor_start;
992         i = 0;
993         while (i < 0x400) {
994                 curs[i++] = 0xffffffff; /* AND mask */
995                 curs[i++] = 0xffffffff; /* AND mask */
996                 curs[i++] = 0;  /* XOR mask */
997                 curs[i++] = 0;  /* XOR mask */
998                 /* Transparent */
999         }
1000         pattern = 0xffffffff >> font_width;
1001         i = 0;
1002         while (i < (font_height * 2)) {
1003                 curs[i++] = pattern;    /* AND mask */
1004                 curs[i++] = pattern;    /* AND mask */
1005                 curs[i++] = 0;  /* XOR mask */
1006                 curs[i++] = 0;  /* XOR mask */
1007                 /* Cursor Color 0 */
1008         }
1009         /* set blink rate */
1010         ctWrite_i (CT_FP_O, 0x19, 0xf);
1011
1012         /* set cursors colors */
1013         xr_80 = ctRead_i (CT_XR_O, 0x80);
1014         xr_80 |= 0x1;           /* alternate palette select */
1015         ctWrite_i (CT_XR_O, 0x80, xr_80);
1016         video_set_lut (4, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
1017         /* position 4 is color 0 cursor 0 */
1018         xr_80 &= 0xfe;          /* normal palette select */
1019         ctWrite_i (CT_XR_O, 0x80, xr_80);
1020         /* cursor enable */
1021         ctWrite_i (CT_XR_O, 0xa0, 0x91);
1022         xr_80 |= 0x10;          /* enable hwcursor */
1023         ctWrite_i (CT_XR_O, 0x80, xr_80);
1024         video_set_hw_cursor (0, 0);
1025 }
1026 #endif                          /* CONFIG_VIDEO_HW_CURSOR */
1027
1028 /***************************************************************
1029  * Wait for BitBlt ready
1030  */
1031 static int
1032 video_wait_bitblt (unsigned long addr)
1033 {
1034         unsigned long br04;
1035         int i = 0;
1036         br04 = in32r (addr);
1037         while (br04 & 0x80000000) {
1038                 udelay (1);
1039                 br04 = in32r (addr);
1040                 if (i++ > 1000000) {
1041                         printf ("ERROR Timeout %lx\n", br04);
1042                         return 1;
1043                 }
1044         }
1045         return 0;
1046 }
1047
1048 /***************************************************************
1049  * Set up BitBlt Registrs
1050  */
1051 static void
1052 SetDrawingEngine (int bits_per_pixel)
1053 {
1054         unsigned long br04, br00;
1055         unsigned char tmp;
1056
1057         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1058
1059         tmp = ctRead_i (CT_XR_O, 0x20); /* BitBLT Configuration */
1060         tmp |= 0x02;            /* reset BitBLT */
1061         ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
1062         udelay (10);
1063         tmp &= 0xfd;            /* release reset BitBLT */
1064         ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
1065         video_wait_bitblt (pGD->pciBase + BR04_o);
1066
1067         /* set pattern Address */
1068         out32r (pGD->pciBase + BR05_o, PATTERN_ADR & 0x003ffff8);
1069         br04 = 0;
1070         if (bits_per_pixel == 1) {
1071                 br04 |= 0x00040000;     /* monochome Pattern */
1072                 br04 |= 0x00001000;     /* monochome source */
1073         }
1074         br00 = ((pGD->winSizeX * pGD->gdfBytesPP) << 16) + (pGD->winSizeX * pGD->gdfBytesPP);   /* bytes per scanline */
1075         out32r (pGD->pciBase + BR00_o, br00);   /* */
1076         out32r (pGD->pciBase + BR08_o, (10 << 16) + 10);        /* dummy */
1077         out32r (pGD->pciBase + BR04_o, br04);   /* write all 0 */
1078         out32r (pGD->pciBase + BR07_o, 0);      /* destination */
1079         video_wait_bitblt (pGD->pciBase + BR04_o);
1080 }
1081
1082 /************************************************************************
1083  * Get Parameters for the video mode:
1084  */
1085 /*********************************************************************
1086  * returns the length to the next seperator
1087  */
1088 static int
1089 video_get_param_len (char *start, char sep)
1090 {
1091         int i = 0;
1092         while ((*start != 0) && (*start != sep)) {
1093                 start++;
1094                 i++;
1095         }
1096         return i;
1097 }
1098
1099 static int
1100 video_search_param (char *start, char *param)
1101 {
1102         int len, totallen, i;
1103         char *p = start;
1104         len = strlen (param);
1105         totallen = len + strlen (start);
1106         for (i = 0; i < totallen; i++) {
1107                 if (strncmp (p++, param, len) == 0)
1108                         return (i);
1109         }
1110         return -1;
1111 }
1112
1113 /***************************************************************
1114 * Get parameter via the environment as it is done for the
1115 * linux kernel i.e:
1116 * video=ctfb:x:800,xv:1280,y:600,yv:1024,depth:16,mode:0,pclk:25000,
1117 *       le:56,ri:48,up:26,lo:5,hs:152,vs:2,sync:0,vmode:0,accel:0
1118 *
1119 * penv is a pointer to the environment, containing the string, or the name of
1120 * another environment variable. It could even be the term "bootargs"
1121 */
1122
1123 #define GET_OPTION(name,var)                            \
1124                 if(strncmp(p,name,strlen(name))==0) {   \
1125                         val_s=p+strlen(name);           \
1126                         var=simple_strtoul(val_s, NULL, 10); \
1127                 }
1128
1129 static int
1130 video_get_params (struct ctfb_res_modes *pPar, char *penv)
1131 {
1132         char *p, *s, *val_s;
1133         int i = 0, t;
1134         int bpp;
1135         int mode;
1136         /* first search for the environment containing the real param string */
1137         s = penv;
1138         if ((p = getenv (s)) != NULL) {
1139                 s = p;
1140         }
1141         /* in case of the bootargs line, we have to start
1142          * after "video=ctfb:"
1143          */
1144         i = video_search_param (s, "video=ctfb:");
1145         if (i >= 0) {
1146                 s += i;
1147                 s += strlen ("video=ctfb:");
1148         }
1149         /* search for mode as a default value */
1150         p = s;
1151         t = 0;
1152         mode = 0;               /* default */
1153         while ((i = video_get_param_len (p, ',')) != 0) {
1154                 GET_OPTION ("mode:", mode)
1155                     p += i;
1156                 if (*p != 0)
1157                         p++;    /* skip ',' */
1158         }
1159         if (mode >= RES_MODES_COUNT)
1160                 mode = 0;
1161         *pPar = res_mode_init[mode];    /* copy default values */
1162         bpp = 24 - ((mode % 3) * 8);
1163         p = s;                  /* restart */
1164         while ((i = video_get_param_len (p, ',')) != 0) {
1165                 GET_OPTION ("x:", pPar->xres)
1166                     GET_OPTION ("y:", pPar->yres)
1167                     GET_OPTION ("le:", pPar->left_margin)
1168                     GET_OPTION ("ri:", pPar->right_margin)
1169                     GET_OPTION ("up:", pPar->upper_margin)
1170                     GET_OPTION ("lo:", pPar->lower_margin)
1171                     GET_OPTION ("hs:", pPar->hsync_len)
1172                     GET_OPTION ("vs:", pPar->vsync_len)
1173                     GET_OPTION ("sync:", pPar->sync)
1174                     GET_OPTION ("vmode:", pPar->vmode)
1175                     GET_OPTION ("pclk:", pPar->pixclock)
1176                     GET_OPTION ("depth:", bpp)
1177                     p += i;
1178                 if (*p != 0)
1179                         p++;    /* skip ',' */
1180         }
1181         return bpp;
1182 }
1183
1184 /****************************************************************************
1185 * supported Video Chips
1186 */
1187 static struct pci_device_id supported[] = {
1188         {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000},
1189         {}
1190 };
1191
1192 /*******************************************************************************
1193 *
1194 * Init video chip
1195 */
1196 void *
1197 video_hw_init (void)
1198 {
1199         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1200         unsigned short device_id;
1201         pci_dev_t devbusfn;
1202         int videomode;
1203         unsigned long t1, hsynch, vsynch;
1204         unsigned int pci_mem_base, *vm;
1205         int tmp, i, bits_per_pixel;
1206         char *penv;
1207         struct ctfb_res_modes *res_mode;
1208         struct ctfb_res_modes var_mode;
1209         struct ctfb_chips_properties *chips_param;
1210         /* Search for video chip */
1211
1212         if ((devbusfn = pci_find_devices (supported, 0)) < 0) {
1213 #ifdef CONFIG_VIDEO_ONBOARD
1214                 printf ("Video: Controller not found !\n");
1215 #endif
1216                 return (NULL);
1217         }
1218
1219         /* PCI setup */
1220         pci_write_config_dword (devbusfn, PCI_COMMAND,
1221                                 (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
1222         pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
1223         pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
1224         pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
1225
1226         /* get chips params */
1227         for (chips_param = (struct ctfb_chips_properties *) &chips[0];
1228              chips_param->device_id != 0; chips_param++) {
1229                 if (chips_param->device_id == device_id)
1230                         break;
1231         }
1232         if (chips_param->device_id == 0) {
1233 #ifdef CONFIG_VIDEO_ONBOARD
1234                 printf ("Video: controller 0x%X not supported\n", device_id);
1235 #endif
1236                 return NULL;
1237         }
1238         /* supported Video controller found */
1239         printf ("Video: ");
1240
1241         tmp = 0;
1242         videomode = 0x301;
1243         /* get video mode via environment */
1244         if ((penv = getenv ("videomode")) != NULL) {
1245                 /* deceide if it is a string */
1246                 if (penv[0] <= '9') {
1247                         videomode = (int) simple_strtoul (penv, NULL, 16);
1248                         tmp = 1;
1249                 }
1250         } else {
1251                 tmp = 1;
1252         }
1253         if (tmp) {
1254                 /* parameter are vesa modes */
1255                 /* search params */
1256                 for (i = 0; i < VESA_MODES_COUNT; i++) {
1257                         if (vesa_modes[i].vesanr == videomode)
1258                                 break;
1259                 }
1260                 if (i == VESA_MODES_COUNT) {
1261                         printf ("no VESA Mode found, switching to mode 0x301 ");
1262                         i = 0;
1263                 }
1264                 res_mode =
1265                     (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
1266                                                              resindex];
1267                 bits_per_pixel = vesa_modes[i].bits_per_pixel;
1268         } else {
1269
1270                 res_mode = (struct ctfb_res_modes *) &var_mode;
1271                 bits_per_pixel = video_get_params (res_mode, penv);
1272         }
1273
1274         /* calculate available color depth for controller memory */
1275         if (bits_per_pixel == 15)
1276                 tmp = 2;
1277         else
1278                 tmp = bits_per_pixel >> 3;      /* /8 */
1279         if (((chips_param->max_mem -
1280               ACCELMEMORY) / (res_mode->xres * res_mode->yres)) < tmp) {
1281                 tmp =
1282                     ((chips_param->max_mem -
1283                       ACCELMEMORY) / (res_mode->xres * res_mode->yres));
1284                 if (tmp == 0) {
1285                         printf
1286                             ("No matching videomode found .-> reduce resolution\n");
1287                         return NULL;
1288                 } else {
1289                         printf ("Switching back to %d Bits per Pixel ",
1290                                 tmp << 3);
1291                         bits_per_pixel = tmp << 3;
1292                 }
1293         }
1294
1295         /* calculate hsynch and vsynch freq (info only) */
1296         t1 = (res_mode->left_margin + res_mode->xres +
1297               res_mode->right_margin + res_mode->hsync_len) / 8;
1298         t1 *= 8;
1299         t1 *= res_mode->pixclock;
1300         t1 /= 1000;
1301         hsynch = 1000000000L / t1;
1302         t1 *=
1303             (res_mode->upper_margin + res_mode->yres +
1304              res_mode->lower_margin + res_mode->vsync_len);
1305         t1 /= 1000;
1306         vsynch = 1000000000L / t1;
1307
1308         /* fill in Graphic device struct */
1309         sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
1310                  res_mode->yres, bits_per_pixel, (hsynch / 1000),
1311                  (vsynch / 1000));
1312         printf ("%s\n", pGD->modeIdent);
1313         pGD->winSizeX = res_mode->xres;
1314         pGD->winSizeY = res_mode->yres;
1315         pGD->plnSizeX = res_mode->xres;
1316         pGD->plnSizeY = res_mode->yres;
1317         switch (bits_per_pixel) {
1318         case 8:
1319                 pGD->gdfBytesPP = 1;
1320                 pGD->gdfIndex = GDF__8BIT_INDEX;
1321                 break;
1322         case 15:
1323                 pGD->gdfBytesPP = 2;
1324                 pGD->gdfIndex = GDF_15BIT_555RGB;
1325                 break;
1326         case 16:
1327                 pGD->gdfBytesPP = 2;
1328                 pGD->gdfIndex = GDF_16BIT_565RGB;
1329                 break;
1330         case 24:
1331                 pGD->gdfBytesPP = 3;
1332                 pGD->gdfIndex = GDF_24BIT_888RGB;
1333                 break;
1334         }
1335         pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
1336         pGD->pciBase = pci_mem_base;
1337         pGD->frameAdrs = pci_mem_base;
1338         pGD->memSize = chips_param->max_mem;
1339         /* Cursor Start Address */
1340         pGD->dprBase =
1341             (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + pci_mem_base;
1342         if ((pGD->dprBase & 0x0fff) != 0) {
1343                 /* allign it */
1344                 pGD->dprBase &= 0xfffff000;
1345                 pGD->dprBase += 0x00001000;
1346         }
1347         PRINTF ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
1348                 PATTERN_ADR);
1349         pGD->vprBase = pci_mem_base;    /* Dummy */
1350         pGD->cprBase = pci_mem_base;    /* Dummy */
1351         /* set up Hardware */
1352
1353         ctWrite (CT_MSR_W_O, 0x01);
1354
1355         /* set the extended Registers */
1356         ctLoadRegs (CT_XR_O, xreg);
1357         /* set atribute registers */
1358         SetArRegs ();
1359         /* set Graphics register */
1360         SetGrRegs ();
1361         /* set sequencer */
1362         SetSrRegs ();
1363
1364         /* set msr */
1365         SetMsrRegs (res_mode);
1366
1367         /* set CRT Registers */
1368         SetCrRegs (res_mode, bits_per_pixel);
1369         /* set color mode */
1370         SetBitsPerPixelIntoXrRegs (bits_per_pixel);
1371
1372         /* set PLL */
1373         FindAndSetPllParamIntoXrRegs (res_mode->pixclock, chips_param);
1374
1375         ctWrite_i (CT_SR_O, 0, 0x03);   /* clear synchronous reset */
1376         /* Clear video memory */
1377         i = pGD->memSize / 4;
1378         vm = (unsigned int *) pGD->pciBase;
1379         while (i--)
1380                 *vm++ = 0;
1381         SetDrawingEngine (bits_per_pixel);
1382 #ifdef VGA_DUMP_REG
1383         video_dump_reg ();
1384 #endif
1385
1386         return ((void *) &ctfb);
1387 }
1388
1389  /*******************************************************************************
1390 *
1391 * Set a RGB color in the LUT (8 bit index)
1392 */
1393 void
1394 video_set_lut (unsigned int index,      /* color number */
1395                unsigned char r, /* red */
1396                unsigned char g, /* green */
1397                unsigned char b  /* blue */
1398     )
1399 {
1400
1401         ctWrite (CT_LUT_MASK_O, 0xff);
1402
1403         ctWrite (CT_LUT_START_O, (char) index);
1404
1405         ctWrite (CT_LUT_RGB_O, r);      /* red */
1406         ctWrite (CT_LUT_RGB_O, g);      /* green */
1407         ctWrite (CT_LUT_RGB_O, b);      /* blue */
1408         udelay (1);
1409         ctWrite (CT_LUT_MASK_O, 0xff);
1410 }
1411
1412 /*******************************************************************************
1413 *
1414 * Drawing engine fill on screen region
1415 */
1416 void
1417 video_hw_rectfill (unsigned int bpp,    /* bytes per pixel */
1418                    unsigned int dst_x,  /* dest pos x */
1419                    unsigned int dst_y,  /* dest pos y */
1420                    unsigned int dim_x,  /* frame width */
1421                    unsigned int dim_y,  /* frame height */
1422                    unsigned int color   /* fill color */
1423     )
1424 {
1425         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1426         unsigned long *p, br04;
1427
1428         video_wait_bitblt (pGD->pciBase + BR04_o);
1429
1430         p = (unsigned long *) PATTERN_ADR;
1431         dim_x *= bpp;
1432         if (bpp == 3)
1433                 bpp++;          /* 24Bit needs a 32bit pattern */
1434         memset (p, color, (bpp * sizeof (unsigned char) * 8 * 8));      /* 8 x 8 pattern data */
1435         out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP);    /* destination */
1436         br04 = in32r (pGD->pciBase + BR04_o) & 0xffffff00;
1437         br04 |= 0xF0;           /* write Pattern P -> D */
1438         out32r (pGD->pciBase + BR04_o, br04);   /* */
1439         out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x);  /* starts the BITBlt */
1440         video_wait_bitblt (pGD->pciBase + BR04_o);
1441 }
1442
1443 /*******************************************************************************
1444 *
1445 * Drawing engine bitblt with screen region
1446 */
1447 void
1448 video_hw_bitblt (unsigned int bpp,      /* bytes per pixel */
1449                  unsigned int src_x,    /* source pos x */
1450                  unsigned int src_y,    /* source pos y */
1451                  unsigned int dst_x,    /* dest pos x */
1452                  unsigned int dst_y,    /* dest pos y */
1453                  unsigned int dim_x,    /* frame width */
1454                  unsigned int dim_y     /* frame height */
1455     )
1456 {
1457         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1458         unsigned long br04;
1459
1460         br04 = in32r (pGD->pciBase + BR04_o);
1461
1462         /* to prevent data corruption due to overlap, we have to
1463          * find out if, and how the frames overlaps */
1464         if (src_x < dst_x) {
1465                 /* src is more left than dest
1466                  * the frame may overlap -> start from right to left */
1467                 br04 |= 0x00000100;     /* set bit 8 */
1468                 src_x += dim_x;
1469                 dst_x += dim_x;
1470         } else {
1471                 br04 &= 0xfffffeff;     /* clear bit 8 left to right */
1472         }
1473         if (src_y < dst_y) {
1474                 /* src is higher than dst
1475                  * the frame may overlap => start from bottom */
1476                 br04 |= 0x00000200;     /* set bit 9 */
1477                 src_y += dim_y;
1478                 dst_y += dim_y;
1479         } else {
1480                 br04 &= 0xfffffdff;     /* clear bit 9 top to bottom */
1481         }
1482         dim_x *= bpp;
1483         out32r (pGD->pciBase + BR06_o, ((pGD->winSizeX * src_y) + src_x) * pGD->gdfBytesPP);    /* source */
1484         out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP);    /* destination */
1485         br04 &= 0xffffff00;
1486         br04 |= 0x000000CC;     /* S -> D */
1487         out32r (pGD->pciBase + BR04_o, br04);   /* */
1488         out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x);  /* start the BITBlt */
1489         video_wait_bitblt (pGD->pciBase + BR04_o);
1490 }
1491
1492 #endif                          /* CONFIG_CT69000 */
1493
1494 #endif                          /* CONFIG_VIDEO */