3 * Denis Peter, MPL AG Switzerland
5 * See file CREDITS for list of people who contributed to this
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.
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.
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,
25 * ported from ctfb.c (linux kernel) for the U-Boot
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:
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 --------+-----------------------------------
44 - the parameters are parsed from the bootargs.
45 The format is "NAME:VALUE,NAME:VALUE" etc.
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:
55 if "mode" is not provided within the parameter list,
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
65 hs hsync_len length of horizontal sync
66 vs vsync_len length of vertical sync
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 ****************************************************************************/
83 #ifdef CONFIG_VIDEO_CT69000
89 #define PRINTF(fmt,args...) printf (fmt ,##args)
91 #define PRINTF(fmt,args...)
96 #define min( a, b ) ( ( a ) < ( b ) ) ? ( a ) : ( b )
99 #define max( a, b ) ( ( a ) > ( b ) ) ? ( a ) : ( b )
102 #error "term minmax already used."
104 #define minmax( a, x, b ) max( ( a ), min( ( x ), ( b ) ) )
105 #define N_ELTS( x ) ( sizeof( x ) / sizeof( x[ 0 ] ) )
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) */
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 */
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 */
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 */
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 */
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
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 */
163 /* table for VGA Initialization */
165 const unsigned char reg;
166 const unsigned char val;
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 */
220 * Bit2 and Bit4..6 are used for the Loop Divisor and Post Divisor.
221 * They are encoded as follows:
223 * +---+--------------+
224 * | 2 | Loop Divisor |
225 * +---+--------------+
227 * +---+--------------+
229 * +---+--------------+
230 * Note: The Memory Clock does not have a Loop Divisor.
231 * +---+---+---+--------------+
232 * | 6 | 5 | 4 | Post Divisor |
233 * +---+---+---+--------------+
235 * +---+---+---+--------------+
237 * +---+---+---+--------------+
239 * +---+---+---+--------------+
241 * +---+---+---+--------------+
243 * +---+---+---+--------------+
245 * +---+---+---+--------------+
246 * | 1 | 1 | X | reserved |
247 * +---+---+---+--------------+
249 * All other bits are reserved in these registers.
251 * Clock VCO M Registers:
252 * ----------------------
253 * These Registers contain the M Value -2.
255 * Clock VCO N Registers:
256 * ----------------------
257 * These Registers contain the N Value -2.
261 * Fvco = (Fref * Loop Divisor * M/N), whereas 100MHz < Fvco < 220MHz
262 * Fout = Fvco / Post Divisor
264 * Dot Clk0 (default 25MHz):
265 * -------------------------
266 * Fvco = 14.318 * 127 / 9 = 202.045MHz
267 * Fout = 202.045MHz / 8 = 25.25MHz
270 * XRC0 = (M - 2) = 125 = 0x7D
271 * XRC1 = (N - 2) = 7 = 0x07
274 * Dot Clk1 (default 28MHz):
275 * -------------------------
276 * Fvco = 14.318 * 87 / 11 = 113.24MHz
277 * Fout = 113.24MHz / 4 = 28.31MHz
280 * XRC4 = (M - 2) = 85 = 0x55
281 * XRC5 = (N - 2) = 9 = 0x09
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
290 * XRC8 = (M - 2) = 125 = 0x7D
291 * XRC9 = (N - 2) = 7 = 0x07
294 * Memory Clk for most modes >50MHz:
295 * ----------------------------------
296 * Fvco = 14.318 * 58 / 5 = 166MHz
297 * Fout = 166MHz / 2 = 83MHz
299 * XRCC = (M - 2) = 57 = 0x38
300 * XRCD = (N - 2) = 3 = 0x03
303 * Note Bit7 enables the clock source from the VCO
307 /******************************************************************
309 ******************************************************************/
310 struct ctfb_res_modes {
311 int xres; /* visible resolution */
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 */
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_* */
325 /******************************************************************
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 */
333 /*******************************************************************
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 */
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 */
354 /*************************************************
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 ?
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
373 #define VESA_MODES_COUNT 15
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}
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}
411 /*******************************************************************************
416 /*******************************************************************************
418 * Read CT ISA register
422 ctRead (unsigned short index)
424 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
425 if (index == CT_AR_O)
426 /* synch the Flip Flop */
427 in8 (pGD->isaBase + CT_STATUS_REG1_O);
429 return (in8 (pGD->isaBase + index));
432 /*******************************************************************************
434 * Write CT ISA register
437 ctWrite (unsigned short index, unsigned char val)
439 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
441 out8 ((pGD->isaBase + index), val);
444 /*******************************************************************************
446 * Read CT ISA register indexed
449 ctRead_i (unsigned short index, char reg)
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));
459 /*******************************************************************************
461 * Write CT ISA register indexed
464 ctWrite_i (unsigned short index, char reg, char val)
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);
473 out8 ((pGD->isaBase + index), reg);
474 out8 ((pGD->isaBase + index + 1), val);
478 /*******************************************************************************
480 * Write a table of CT ISA register
483 ctLoadRegs (unsigned short index, CT_CFG_TABLE * regTab)
485 while (regTab->reg != 0xFF) {
486 ctWrite_i (index, regTab->reg, regTab->val);
491 /*****************************************************************************/
497 for (i = 0; i < 0x10; i++)
498 ctWrite_i (CT_AR_O, i, i);
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 */
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 */
516 /*****************************************************************************/
519 { /* Set Graphics Mode */
522 for (i = 0; i < 0x05; i++)
523 ctWrite_i (CT_GR_O, i, 0);
525 ctWrite_i (CT_GR_O, 0x05, 0x10);
526 ctWrite_i (CT_GR_O, 0x06, 0x02);
528 ctWrite_i (CT_GR_O, 0x05, 0x40);
529 ctWrite_i (CT_GR_O, 0x06, 0x05);
531 ctWrite_i (CT_GR_O, 0x07, 0x0f);
532 ctWrite_i (CT_GR_O, 0x08, 0xff);
535 /*****************************************************************************/
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 ); */
546 ctWrite_i (CT_SR_O, 0x01, 0x01); /* Clocking Mode Register */
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 */
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
558 ctWrite_i (CT_SR_O, 0x00, 0x03); /* enable */
561 /*****************************************************************************/
563 SetBitsPerPixelIntoXrRegs (int bpp)
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 */
571 tmp = ctRead_i (CT_XR_O, 0x20);
574 ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
575 ctWrite_i (CT_XR_O, 0x81, md[n]);
578 /*****************************************************************************/
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];
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;
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 */
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 */
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 ) */
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 ) */
630 wd = var->xres * bpp / 64; /* double words per line */
631 if (interlaced) { /* we divide all vertical timings, exept vd */
636 memset (cr, 0, sizeof (cr));
637 cr[0x00] = 0xff & (ht - 5);
638 cr[0x01] = hd - 1; /* soll:4f ist 59 */
640 cr[0x03] = (hbe & 0x1F) | 0x80; /* hd + ht - hd */
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);
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)
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]);
687 for (i = 0x10; i <= 0x18; i++) { /*CR10 .. CR18 */
688 ctWrite_i (CT_CR_O, i, cr[i]);
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]);
696 ctWrite_i (CT_CR_O, i, cr[i]);
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]);
702 for (i = 0x70; i <= 0x74; i++) { /*CR70 .. CR74 */
703 ctWrite_i (CT_CR_O, i, cr[i]);
705 tmp = ctRead_i (CT_CR_O, 0x40);
708 ctWrite_i (CT_CR_O, 0x40, tmp); /* StartAddressEnable */
711 /* pixelclock control */
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 ******************************************************************************/
719 FindBestPQFittingMN (unsigned int p, unsigned int q, unsigned int mnmin,
720 unsigned int mnmax, unsigned int *pm, unsigned int *pn)
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 */
733 /* difference is less or equal than 0 or m > maximum */
735 break; /* no solution: if we increase n we get the same situation */
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 */
741 L = (L < 0) ? -L : +L; /* absolute value */
742 if (D < L) /* if last difference was better take next n */
746 *pn = n; /* keep improved data */
748 break; /* best result we can get */
750 return (unsigned int) (0xffffffff & D);
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 ___________________________________________________________________|
761 | +--------+ +------------+ +-----+ +-------------------+ +----+
762 +-| Phase |__|Charge Pump |__| VCO |_____|Post Divisor (PD) |___|CLK |--->
763 +-| Detect | |& Filter VCO| | | | |÷1, 2, 4, 8, 16, 32| | |
764 | +--------+ +------------+ +-----+ | +-------------------+ +----+
766 | +--+ +---------------+ |
767 |____|÷M|___|VCO Loop Divide|__________|
768 | | |(VLD)(÷4, ÷16) |
769 +--+ +---------------+
770 ****************************************************************************
771 that is the hardware >= 69000 we have to manage
779 | +--------+ +------------+ +-----+ +-------------------+ +----+
780 +-| Phase |__|Charge Pump |__| VCO |_____|Post Divisor (PD) |___|CLK |--->
781 +-| Detect | |& Filter VCO| | | | |÷1, 2, 4, 8, 16, 32| | |
782 | +--------+ +------------+ +-----+ | +-------------------+ +----+
784 | +--+ +---------------+ |
785 |____|÷M|___|VCO Loop Divide|__________|
786 | | |(VLD)(÷1, ÷4) |
787 +--+ +---------------+
792 #define VIDEO_FREF 14318180; /* Hz */
793 /*****************************************************************************/
795 ReadPixClckFromXrRegsBack (struct ctfb_chips_properties *param)
797 unsigned int m, n, vld, pd, PD, fref, xr_cb, i, pixclock;
801 m = ctRead_i (CT_XR_O, 0xc8);
802 n = ctRead_i (CT_XR_O, 0xc9);
805 xr_cb = ctRead_i (CT_XR_O, 0xcb);
806 PD = (0x70 & xr_cb) >> 4;
808 for (i = 0; i < PD; i++) {
811 vld = (0x04 & xr_cb) ? param->vld_set : param->vld_not_set;
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 */
819 pixclock = (unsigned) p / (unsigned) q;
821 printf ("Invalid data in xr regs.\n");
825 /*****************************************************************************/
827 FindAndSetPllParamIntoXrRegs (unsigned int pixelclock,
828 struct ctfb_chips_properties *param)
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;
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 */
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 */
853 /* fvco is exactly pd * pixelclock and higher than the ninmal VCO frequency */
855 vld = param->vld_set;
856 D=FindBestPQFittingMN (fvco / vld, fref, param->mn_min, param->mn_max, &m, &n); /* rds = 1 */
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 */
865 vld = param->vld_set;
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.
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);
884 /*****************************************************************************/
886 SetMsrRegs (struct ctfb_res_modes *mode)
888 unsigned char h_synch_high, v_synch_high;
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
902 /************************************************************************************/
906 ctDispRegs (unsigned short index, int from, int to)
908 unsigned char status;
911 for (i = from; i < to; i++) {
912 status = ctRead_i (index, i);
913 printf ("%02X: is %02X\n", i, status);
918 video_dump_reg (void)
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 */
950 #ifdef CONFIG_VIDEO_HW_CURSOR
951 /***************************************************************
952 * Set Hardware Cursor in Pixel
955 video_set_hw_cursor (int x, int y)
957 int sig_x = 0, sig_y = 0;
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);
972 /***************************************************************
973 * Init Hardware Cursor. To know the size of the Cursor,
974 * we have to know the Font size.
977 video_init_hw_cursor (int font_width, int font_height)
980 unsigned long *curs, pattern;
983 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
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;
994 curs[i++] = 0xffffffff; /* AND mask */
995 curs[i++] = 0xffffffff; /* AND mask */
996 curs[i++] = 0; /* XOR mask */
997 curs[i++] = 0; /* XOR mask */
1000 pattern = 0xffffffff >> font_width;
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 */
1009 /* set blink rate */
1010 ctWrite_i (CT_FP_O, 0x19, 0xf);
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);
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);
1026 #endif /* CONFIG_VIDEO_HW_CURSOR */
1028 /***************************************************************
1029 * Wait for BitBlt ready
1032 video_wait_bitblt (unsigned long addr)
1036 br04 = in32r (addr);
1037 while (br04 & 0x80000000) {
1039 br04 = in32r (addr);
1040 if (i++ > 1000000) {
1041 printf ("ERROR Timeout %lx\n", br04);
1048 /***************************************************************
1049 * Set up BitBlt Registrs
1052 SetDrawingEngine (int bits_per_pixel)
1054 unsigned long br04, br00;
1057 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
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 */
1063 tmp &= 0xfd; /* release reset BitBLT */
1064 ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
1065 video_wait_bitblt (pGD->pciBase + BR04_o);
1067 /* set pattern Address */
1068 out32r (pGD->pciBase + BR05_o, PATTERN_ADR & 0x003ffff8);
1070 if (bits_per_pixel == 1) {
1071 br04 |= 0x00040000; /* monochome Pattern */
1072 br04 |= 0x00001000; /* monochome source */
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);
1082 /************************************************************************
1083 * Get Parameters for the video mode:
1085 /*********************************************************************
1086 * returns the length to the next seperator
1089 video_get_param_len (char *start, char sep)
1092 while ((*start != 0) && (*start != sep)) {
1100 video_search_param (char *start, char *param)
1102 int len, totallen, i;
1104 len = strlen (param);
1105 totallen = len + strlen (start);
1106 for (i = 0; i < totallen; i++) {
1107 if (strncmp (p++, param, len) == 0)
1113 /***************************************************************
1114 * Get parameter via the environment as it is done for the
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
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"
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); \
1130 video_get_params (struct ctfb_res_modes *pPar, char *penv)
1132 char *p, *s, *val_s;
1136 /* first search for the environment containing the real param string */
1138 if ((p = getenv (s)) != NULL) {
1141 /* in case of the bootargs line, we have to start
1142 * after "video=ctfb:"
1144 i = video_search_param (s, "video=ctfb:");
1147 s += strlen ("video=ctfb:");
1149 /* search for mode as a default value */
1152 mode = 0; /* default */
1153 while ((i = video_get_param_len (p, ',')) != 0) {
1154 GET_OPTION ("mode:", mode)
1159 if (mode >= RES_MODES_COUNT)
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)
1184 /****************************************************************************
1185 * supported Video Chips
1187 static struct pci_device_id supported[] = {
1188 {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000},
1192 /*******************************************************************************
1197 video_hw_init (void)
1199 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1200 unsigned short device_id;
1203 unsigned long t1, hsynch, vsynch;
1204 unsigned int pci_mem_base, *vm;
1205 int tmp, i, bits_per_pixel;
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 */
1212 if ((devbusfn = pci_find_devices (supported, 0)) < 0) {
1213 #ifdef CONFIG_VIDEO_ONBOARD
1214 printf ("Video: Controller not found !\n");
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);
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)
1232 if (chips_param->device_id == 0) {
1233 #ifdef CONFIG_VIDEO_ONBOARD
1234 printf ("Video: controller 0x%X not supported\n", device_id);
1238 /* supported Video controller found */
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);
1254 /* parameter are vesa modes */
1256 for (i = 0; i < VESA_MODES_COUNT; i++) {
1257 if (vesa_modes[i].vesanr == videomode)
1260 if (i == VESA_MODES_COUNT) {
1261 printf ("no VESA Mode found, switching to mode 0x301 ");
1265 (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
1267 bits_per_pixel = vesa_modes[i].bits_per_pixel;
1270 res_mode = (struct ctfb_res_modes *) &var_mode;
1271 bits_per_pixel = video_get_params (res_mode, penv);
1274 /* calculate available color depth for controller memory */
1275 if (bits_per_pixel == 15)
1278 tmp = bits_per_pixel >> 3; /* /8 */
1279 if (((chips_param->max_mem -
1280 ACCELMEMORY) / (res_mode->xres * res_mode->yres)) < tmp) {
1282 ((chips_param->max_mem -
1283 ACCELMEMORY) / (res_mode->xres * res_mode->yres));
1286 ("No matching videomode found .-> reduce resolution\n");
1289 printf ("Switching back to %d Bits per Pixel ",
1291 bits_per_pixel = tmp << 3;
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;
1299 t1 *= res_mode->pixclock;
1301 hsynch = 1000000000L / t1;
1303 (res_mode->upper_margin + res_mode->yres +
1304 res_mode->lower_margin + res_mode->vsync_len);
1306 vsynch = 1000000000L / t1;
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),
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) {
1319 pGD->gdfBytesPP = 1;
1320 pGD->gdfIndex = GDF__8BIT_INDEX;
1323 pGD->gdfBytesPP = 2;
1324 pGD->gdfIndex = GDF_15BIT_555RGB;
1327 pGD->gdfBytesPP = 2;
1328 pGD->gdfIndex = GDF_16BIT_565RGB;
1331 pGD->gdfBytesPP = 3;
1332 pGD->gdfIndex = GDF_24BIT_888RGB;
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 */
1341 (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + pci_mem_base;
1342 if ((pGD->dprBase & 0x0fff) != 0) {
1344 pGD->dprBase &= 0xfffff000;
1345 pGD->dprBase += 0x00001000;
1347 PRINTF ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
1349 pGD->vprBase = pci_mem_base; /* Dummy */
1350 pGD->cprBase = pci_mem_base; /* Dummy */
1351 /* set up Hardware */
1353 ctWrite (CT_MSR_W_O, 0x01);
1355 /* set the extended Registers */
1356 ctLoadRegs (CT_XR_O, xreg);
1357 /* set atribute registers */
1359 /* set Graphics register */
1365 SetMsrRegs (res_mode);
1367 /* set CRT Registers */
1368 SetCrRegs (res_mode, bits_per_pixel);
1369 /* set color mode */
1370 SetBitsPerPixelIntoXrRegs (bits_per_pixel);
1373 FindAndSetPllParamIntoXrRegs (res_mode->pixclock, chips_param);
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;
1381 SetDrawingEngine (bits_per_pixel);
1386 return ((void *) &ctfb);
1389 /*******************************************************************************
1391 * Set a RGB color in the LUT (8 bit index)
1394 video_set_lut (unsigned int index, /* color number */
1395 unsigned char r, /* red */
1396 unsigned char g, /* green */
1397 unsigned char b /* blue */
1401 ctWrite (CT_LUT_MASK_O, 0xff);
1403 ctWrite (CT_LUT_START_O, (char) index);
1405 ctWrite (CT_LUT_RGB_O, r); /* red */
1406 ctWrite (CT_LUT_RGB_O, g); /* green */
1407 ctWrite (CT_LUT_RGB_O, b); /* blue */
1409 ctWrite (CT_LUT_MASK_O, 0xff);
1412 /*******************************************************************************
1414 * Drawing engine fill on screen region
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 */
1425 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1426 unsigned long *p, br04;
1428 video_wait_bitblt (pGD->pciBase + BR04_o);
1430 p = (unsigned long *) PATTERN_ADR;
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);
1443 /*******************************************************************************
1445 * Drawing engine bitblt with screen region
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 */
1457 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
1460 br04 = in32r (pGD->pciBase + BR04_o);
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 */
1471 br04 &= 0xfffffeff; /* clear bit 8 left to right */
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 */
1480 br04 &= 0xfffffdff; /* clear bit 9 top to bottom */
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 */
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);
1492 #endif /* CONFIG_CT69000 */
1494 #endif /* CONFIG_VIDEO */