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