2 * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
4 * Copyright (C) 1994 Martin Schaller & Roman Hodek
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
11 * - 03 Jan 95: Original version by Martin Schaller: The TT driver and
12 * all the device independent stuff
13 * - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
14 * and wrote the Falcon, ST(E), and External drivers
15 * based on the original TT driver.
16 * - 07 May 95: Martin: Added colormap operations for the external driver
17 * - 21 May 95: Martin: Added support for overscan
18 * Andreas: some bug fixes for this
19 * - Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
20 * Programmable Falcon video modes
21 * (thanks to Christian Cartus for documentation
22 * of VIDEL registers).
23 * - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
24 * on minor 24...31. "user0" may be set on commandline by
25 * "R<x>;<y>;<depth>". (Makes sense only on Falcon)
26 * Video mode switch on Falcon now done at next VBL interrupt
27 * to avoid the annoying right shift of the screen.
28 * - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
29 * The external-part is legacy, therefore hardware-specific
30 * functions like panning/hardwarescrolling/blanking isn't
32 * - 29 Sep 97: Juergen: added Romans suggestion for pan_display
33 * (var->xoffset was changed even if no set_screen_base avail.)
34 * - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
35 * we know how to set the colors
36 * ext_*palette: read from ext_colors (former MV300_colors)
37 * write to ext_colors and RAMDAC
40 * - For the Falcon it is not possible to set random video modes on
41 * SM124 and SC/TV, only the bootup resolution is supported.
50 #include <linux/module.h>
51 #include <linux/kernel.h>
52 #include <linux/sched.h>
53 #include <linux/errno.h>
54 #include <linux/string.h>
56 #include <linux/tty.h>
57 #include <linux/malloc.h>
58 #include <linux/delay.h>
59 #include <linux/init.h>
61 #include <asm/setup.h>
62 #include <asm/uaccess.h>
63 #include <asm/pgtable.h>
67 #include <asm/atarihw.h>
68 #include <asm/atariints.h>
69 #include <asm/atari_stram.h>
72 #include <asm/atarikb.h>
74 #include <video/fbcon-cfb8.h>
75 #include <video/fbcon-cfb16.h>
76 #include <video/fbcon-iplan2p2.h>
77 #include <video/fbcon-iplan2p4.h>
78 #include <video/fbcon-iplan2p8.h>
79 #include <video/fbcon-mfb.h>
82 #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
83 #define SWITCH_SND6 0x40
84 #define SWITCH_SND7 0x80
85 #define SWITCH_NONE 0x00
88 #define arraysize(x) (sizeof(x)/sizeof(*(x)))
90 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
93 static int default_par
=0; /* default resolution (0=none) */
95 static unsigned long default_mem_req
=0;
97 static int hwscroll
=-1;
99 static int use_hwscroll
= 1;
101 static int sttt_xres
=640,st_yres
=400,tt_yres
=480;
102 static int sttt_xres_virtual
=640,sttt_yres_virtual
=400;
103 static int ovsc_offset
=0, ovsc_addlen
=0;
105 static struct atafb_par
{
106 unsigned long screen_base
;
108 #if defined ATAFB_TT || defined ATAFB_STE
117 /* Here are fields for storing a video mode, as direct
118 * parameters for the hardware.
128 short hht
, hbb
, hbe
, hdb
, hde
, hss
;
129 short vft
, vbb
, vbe
, vdb
, vde
, vss
;
130 /* auxiliary information */
136 /* Nothing needed for external mode */
140 /* Don't calculate an own resolution, and thus don't change the one found when
141 * booting (currently used for the Falcon to keep settings for internal video
142 * hardware extensions (e.g. ScreenBlaster) */
143 static int DontCalcRes
= 0;
146 #define HHT hw.falcon.hht
147 #define HBB hw.falcon.hbb
148 #define HBE hw.falcon.hbe
149 #define HDB hw.falcon.hdb
150 #define HDE hw.falcon.hde
151 #define HSS hw.falcon.hss
152 #define VFT hw.falcon.vft
153 #define VBB hw.falcon.vbb
154 #define VBE hw.falcon.vbe
155 #define VDB hw.falcon.vdb
156 #define VDE hw.falcon.vde
157 #define VSS hw.falcon.vss
158 #define VCO_CLOCK25 0x04
159 #define VCO_CSYPOS 0x10
160 #define VCO_VSYPOS 0x20
161 #define VCO_HSYPOS 0x40
162 #define VCO_SHORTOFFS 0x100
163 #define VMO_DOUBLE 0x01
164 #define VMO_INTER 0x02
165 #define VMO_PREMASK 0x0c
168 static struct fb_info fb_info
;
170 static unsigned long screen_base
; /* base address of screen */
171 static unsigned long real_screen_base
; /* (only for Overscan) */
173 static int screen_len
;
175 static int current_par_valid
=0;
177 static int currcon
=0;
179 static int mono_moni
=0;
181 static struct display disp
;
185 /* external video handling */
187 static unsigned external_xres
;
188 static unsigned external_xres_virtual
;
189 static unsigned external_yres
;
190 /* not needed - atafb will never support panning/hardwarescroll with external
191 * static unsigned external_yres_virtual;
194 static unsigned external_depth
;
195 static int external_pmode
;
196 static unsigned long external_addr
= 0;
197 static unsigned long external_len
;
198 static unsigned long external_vgaiobase
= 0;
199 static unsigned int external_bitspercol
= 6;
202 JOE <joe@amber.dinoco.de>:
203 added card type for external driver, is only needed for
207 enum cardtype
{ IS_VGA
, IS_MV300
};
208 static enum cardtype external_card_type
= IS_VGA
;
211 The MV300 mixes the color registers. So we need an array of munged
212 indices in order to acces the correct reg.
214 static int MV300_reg_1bit
[2]={0,1};
215 static int MV300_reg_4bit
[16]={
216 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
217 static int MV300_reg_8bit
[256]={
218 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
219 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
220 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
221 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
222 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
223 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
224 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
225 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
226 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
227 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
228 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
229 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
230 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
231 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
232 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
233 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 };
235 static int *MV300_reg
= MV300_reg_8bit
;
238 And on the MV300 it's difficult to read out the hardware palette. So we
239 just keep track of the set colors in our own array here, and use that!
242 static struct { unsigned char red
,green
,blue
,pad
; } ext_color
[256];
243 #endif /* ATAFB_EXT */
246 static int inverse
=0;
248 extern int fontheight_8x8
;
249 extern int fontwidth_8x8
;
250 extern unsigned char fontdata_8x8
[];
252 extern int fontheight_8x16
;
253 extern int fontwidth_8x16
;
254 extern unsigned char fontdata_8x16
[];
256 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
259 * int (*detect)( void )
260 * This function should detect the current video mode settings and
261 * store them in atafb_predefined[0] for later reference by the
262 * user. Return the index+1 of an equivalent predefined mode or 0
263 * if there is no such.
265 * int (*encode_fix)( struct fb_fix_screeninfo *fix,
266 * struct atafb_par *par )
267 * This function should fill in the 'fix' structure based on the
268 * values in the 'par' structure.
270 * int (*decode_var)( struct fb_var_screeninfo *var,
271 * struct atafb_par *par )
272 * Get the video params out of 'var'. If a value doesn't fit, round
273 * it up, if it's too big, return EINVAL.
274 * Round up in the following order: bits_per_pixel, xres, yres,
275 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
276 * horizontal timing, vertical timing.
278 * int (*encode_var)( struct fb_var_screeninfo *var,
279 * struct atafb_par *par );
280 * Fill the 'var' structure based on the values in 'par' and maybe
281 * other values read out of the hardware.
283 * void (*get_par)( struct atafb_par *par )
284 * Fill the hardware's 'par' structure.
286 * void (*set_par)( struct atafb_par *par )
287 * Set the hardware according to 'par'.
289 * int (*setcolreg)( unsigned regno, unsigned red,
290 * unsigned green, unsigned blue,
291 * unsigned transp, struct fb_info *info )
292 * Set a single color register. The values supplied are already
293 * rounded down to the hardware's capabilities (according to the
294 * entries in the var structure). Return != 0 for invalid regno.
296 * int (*getcolreg)( unsigned regno, unsigned *red,
297 * unsigned *green, unsigned *blue,
298 * unsigned *transp, struct fb_info *info )
299 * Read a single color register and split it into
300 * colors/transparent. Return != 0 for invalid regno.
302 * void (*set_screen_base)( unsigned long s_base )
303 * Set the base address of the displayed frame buffer. Only called
304 * if yres_virtual > yres or xres_virtual > xres.
306 * int (*blank)( int blank_mode )
307 * Blank the screen if blank_mode!=0, else unblank. If blank==NULL then
308 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
309 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
310 * doesn't support it. Implements VESA suspend and powerdown modes on
311 * hardware that supports disabling hsync/vsync:
312 * blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown.
315 static struct fb_hwswitch
{
316 int (*detect
)( void );
317 int (*encode_fix
)( struct fb_fix_screeninfo
*fix
,
318 struct atafb_par
*par
);
319 int (*decode_var
)( struct fb_var_screeninfo
*var
,
320 struct atafb_par
*par
);
321 int (*encode_var
)( struct fb_var_screeninfo
*var
,
322 struct atafb_par
*par
);
323 void (*get_par
)( struct atafb_par
*par
);
324 void (*set_par
)( struct atafb_par
*par
);
325 int (*getcolreg
)( unsigned regno
, unsigned *red
,
326 unsigned *green
, unsigned *blue
,
327 unsigned *transp
, struct fb_info
*info
);
328 int (*setcolreg
)( unsigned regno
, unsigned red
,
329 unsigned green
, unsigned blue
,
330 unsigned transp
, struct fb_info
*info
);
331 void (*set_screen_base
)( unsigned long s_base
);
332 int (*blank
)( int blank_mode
);
333 int (*pan_display
)( struct fb_var_screeninfo
*var
,
334 struct atafb_par
*par
);
337 static char *autodetect_names
[] = {"autodetect", NULL
};
338 static char *stlow_names
[] = {"stlow", NULL
};
339 static char *stmid_names
[] = {"stmid", "default5", NULL
};
340 static char *sthigh_names
[] = {"sthigh", "default4", NULL
};
341 static char *ttlow_names
[] = {"ttlow", NULL
};
342 static char *ttmid_names
[]= {"ttmid", "default1", NULL
};
343 static char *tthigh_names
[]= {"tthigh", "default2", NULL
};
344 static char *vga2_names
[] = {"vga2", NULL
};
345 static char *vga4_names
[] = {"vga4", NULL
};
346 static char *vga16_names
[] = {"vga16", "default3", NULL
};
347 static char *vga256_names
[] = {"vga256", NULL
};
348 static char *falh2_names
[] = {"falh2", NULL
};
349 static char *falh16_names
[] = {"falh16", NULL
};
351 static char **fb_var_names
[] = {
352 /* Writing the name arrays directly in this array (via "(char *[]){...}")
353 * crashes gcc 2.5.8 (sigsegv) if the inner array
354 * contains more than two items. I've also seen that all elements
355 * were identical to the last (my cross-gcc) :-(*/
370 /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
373 static struct fb_var_screeninfo atafb_predefined
[] = {
375 * yres_virtual==0 means use hw-scrolling if possible, else yres
378 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
379 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
380 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
382 320, 200, 320, 0, 0, 0, 4, 0,
383 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
384 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
386 640, 200, 640, 0, 0, 0, 2, 0,
387 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
388 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
390 640, 400, 640, 0, 0, 0, 1, 0,
391 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
392 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
394 320, 480, 320, 0, 0, 0, 8, 0,
395 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
396 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
398 640, 480, 640, 0, 0, 0, 4, 0,
399 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
400 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
402 1280, 960, 1280, 0, 0, 0, 1, 0,
403 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
404 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
406 640, 480, 640, 0, 0, 0, 1, 0,
407 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
408 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
410 640, 480, 640, 0, 0, 0, 2, 0,
411 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
412 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
414 640, 480, 640, 0, 0, 0, 4, 0,
415 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
416 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
418 640, 480, 640, 0, 0, 0, 8, 0,
419 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
420 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
422 896, 608, 896, 0, 0, 0, 1, 0,
423 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
424 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
426 896, 608, 896, 0, 0, 0, 4, 0,
427 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
428 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
431 static int num_atafb_predefined
=arraysize(atafb_predefined
);
435 get_video_mode(char *vname
)
440 name_list
=fb_var_names
;
441 for (i
= 0 ; i
< num_atafb_predefined
; i
++) {
443 if (! name
|| ! *name
)
446 if (! strcmp(vname
, *name
))
456 /* ------------------- TT specific functions ---------------------- */
460 static int tt_encode_fix( struct fb_fix_screeninfo
*fix
,
461 struct atafb_par
*par
)
466 strcpy(fix
->id
,"Atari Builtin");
467 fix
->smem_start
= (char *)real_screen_base
;
468 fix
->smem_len
= screen_len
;
469 fix
->type
=FB_TYPE_INTERLEAVED_PLANES
;
471 fix
->visual
=FB_VISUAL_PSEUDOCOLOR
;
472 mode
= par
->hw
.tt
.mode
& TT_SHIFTER_MODEMASK
;
473 if (mode
== TT_SHIFTER_TTHIGH
|| mode
== TT_SHIFTER_STHIGH
) {
474 fix
->type
=FB_TYPE_PACKED_PIXELS
;
476 if (mode
== TT_SHIFTER_TTHIGH
)
477 fix
->visual
=FB_VISUAL_MONO01
;
482 fix
->line_length
= 0;
483 fix
->accel
= FB_ACCEL_ATARIBLITT
;
488 static int tt_decode_var( struct fb_var_screeninfo
*var
,
489 struct atafb_par
*par
)
493 int bpp
=var
->bits_per_pixel
;
495 int yres_virtual
= var
->yres_virtual
;
498 if (bpp
> 1 || xres
> sttt_xres
*2 || yres
>tt_yres
*2)
500 par
->hw
.tt
.mode
=TT_SHIFTER_TTHIGH
;
505 if (bpp
> 8 || xres
> sttt_xres
|| yres
> tt_yres
)
508 if (xres
> sttt_xres
/2 || yres
> tt_yres
)
510 par
->hw
.tt
.mode
=TT_SHIFTER_TTLOW
;
516 if (xres
> sttt_xres
|| yres
> tt_yres
)
518 if (xres
> sttt_xres
/2 || yres
> st_yres
/2) {
519 par
->hw
.tt
.mode
=TT_SHIFTER_TTMID
;
525 par
->hw
.tt
.mode
=TT_SHIFTER_STLOW
;
532 if (xres
> sttt_xres
|| yres
> st_yres
/2)
534 par
->hw
.tt
.mode
=TT_SHIFTER_STMID
;
539 else if (var
->xres
> sttt_xres
|| var
->yres
> st_yres
) {
543 par
->hw
.tt
.mode
=TT_SHIFTER_STHIGH
;
549 if (yres_virtual
<= 0)
551 else if (yres_virtual
< yres
)
553 if (var
->sync
& FB_SYNC_EXT
)
558 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
560 if (yres
* linelen
> screen_len
&& screen_len
)
562 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
564 par
->yres_virtual
= yres_virtual
;
565 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
569 static int tt_encode_var( struct fb_var_screeninfo
*var
,
570 struct atafb_par
*par
)
573 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
576 var
->red
.msb_right
=0;
580 var
->left_margin
=120; /* these may be incorrect */
581 var
->right_margin
=100;
583 var
->lower_margin
=16;
590 if (par
->hw
.tt
.sync
& 1)
593 var
->sync
=FB_SYNC_EXT
;
595 switch (par
->hw
.tt
.mode
& TT_SHIFTER_MODEMASK
) {
596 case TT_SHIFTER_STLOW
:
597 var
->xres
=sttt_xres
/2;
598 var
->xres_virtual
=sttt_xres_virtual
/2;
600 var
->bits_per_pixel
=4;
602 case TT_SHIFTER_STMID
:
604 var
->xres_virtual
=sttt_xres_virtual
;
606 var
->bits_per_pixel
=2;
608 case TT_SHIFTER_STHIGH
:
610 var
->xres_virtual
=sttt_xres_virtual
;
612 var
->bits_per_pixel
=1;
614 case TT_SHIFTER_TTLOW
:
615 var
->xres
=sttt_xres
/2;
616 var
->xres_virtual
=sttt_xres_virtual
/2;
618 var
->bits_per_pixel
=8;
620 case TT_SHIFTER_TTMID
:
622 var
->xres_virtual
=sttt_xres_virtual
;
624 var
->bits_per_pixel
=4;
626 case TT_SHIFTER_TTHIGH
:
628 var
->xres
=sttt_xres
*2;
629 var
->xres_virtual
=sttt_xres_virtual
*2;
631 var
->bits_per_pixel
=1;
634 var
->blue
=var
->green
=var
->red
;
635 var
->transp
.offset
=0;
636 var
->transp
.length
=0;
637 var
->transp
.msb_right
=0;
638 linelen
=var
->xres_virtual
* var
->bits_per_pixel
/ 8;
640 var
->yres_virtual
=var
->yres
;
641 else if (screen_len
) {
642 if (par
->yres_virtual
)
643 var
->yres_virtual
= par
->yres_virtual
;
645 /* yres_virtual==0 means use maximum */
646 var
->yres_virtual
= screen_len
/ linelen
;
649 var
->yres_virtual
= 2 * var
->yres
;
651 var
->yres_virtual
=var
->yres
+hwscroll
* 16;
655 var
->yoffset
=(par
->screen_base
- screen_base
)/linelen
;
660 var
->vmode
=FB_VMODE_NONINTERLACED
;
665 static void tt_get_par( struct atafb_par
*par
)
668 par
->hw
.tt
.mode
=shifter_tt
.tt_shiftmode
;
669 par
->hw
.tt
.sync
=shifter
.syncmode
;
670 addr
= ((shifter
.bas_hi
& 0xff) << 16) |
671 ((shifter
.bas_md
& 0xff) << 8) |
672 ((shifter
.bas_lo
& 0xff));
673 par
->screen_base
= phys_to_virt(addr
);
676 static void tt_set_par( struct atafb_par
*par
)
678 shifter_tt
.tt_shiftmode
=par
->hw
.tt
.mode
;
679 shifter
.syncmode
=par
->hw
.tt
.sync
;
680 /* only set screen_base if really necessary */
681 if (current_par
.screen_base
!= par
->screen_base
)
682 fbhw
->set_screen_base(par
->screen_base
);
686 static int tt_getcolreg(unsigned regno
, unsigned *red
,
687 unsigned *green
, unsigned *blue
,
688 unsigned *transp
, struct fb_info
*info
)
692 if ((shifter_tt
.tt_shiftmode
& TT_SHIFTER_MODEMASK
) == TT_SHIFTER_STHIGH
)
696 t
= tt_palette
[regno
];
714 static int tt_setcolreg(unsigned regno
, unsigned red
,
715 unsigned green
, unsigned blue
,
716 unsigned transp
, struct fb_info
*info
)
718 if ((shifter_tt
.tt_shiftmode
& TT_SHIFTER_MODEMASK
) == TT_SHIFTER_STHIGH
)
722 tt_palette
[regno
] = (((red
>> 12) << 8) | ((green
>> 12) << 4) |
724 if ((shifter_tt
.tt_shiftmode
& TT_SHIFTER_MODEMASK
) ==
725 TT_SHIFTER_STHIGH
&& regno
== 254)
731 static int tt_detect( void )
733 { struct atafb_par par
;
735 /* Determine the connected monitor: The DMA sound must be
736 * disabled before reading the MFP GPIP, because the Sound
737 * Done Signal and the Monochrome Detect are XORed together!
739 * Even on a TT, we should look if there is a DMA sound. It was
740 * announced that the Eagle is TT compatible, but only the PCM is
743 if (ATARIHW_PRESENT(PCM_8BIT
)) {
744 tt_dmasnd
.ctrl
= DMASND_CTRL_OFF
;
745 udelay(20); /* wait a while for things to settle down */
747 mono_moni
= (mfp
.par_dt_reg
& 0x80) == 0;
750 tt_encode_var(&atafb_predefined
[0], &par
);
755 #endif /* ATAFB_TT */
757 /* ------------------- Falcon specific functions ---------------------- */
761 static int mon_type
; /* Falcon connected monitor */
762 static int f030_bus_width
; /* Falcon ram bus width (for vid_control) */
768 static struct pixel_clock
{
769 unsigned long f
; /* f/[Hz] */
770 unsigned long t
; /* t/[ps] (=1/f) */
771 int right
, hsync
, left
; /* standard timing in clock cycles, not pixel */
772 /* hsync initialized in falcon_detect() */
773 int sync_mask
; /* or-mask for hw.falcon.sync to set this clock */
774 int control_mask
; /* ditto, for hw.falcon.vid_control */
776 f25
= {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
},
777 f32
= {32000000, 31250, 18, 0, 42, 0x0, 0},
778 fext
= { 0, 0, 18, 0, 42, 0x1, 0};
780 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
781 static int vdl_prescale
[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
783 /* Default hsync timing [mon_type] in picoseconds */
784 static long h_syncs
[4] = {3000000, 4875000, 4000000, 4875000};
786 #ifdef FBCON_HAS_CFB16
787 static u16 fbcon_cfb16_cmap
[16];
790 static inline int hxx_prescale(struct falcon_hw
*hw
)
792 return hw
->ste_mode
? 16 :
793 vdl_prescale
[mon_type
][hw
->vid_mode
>> 2 & 0x3];
796 static int falcon_encode_fix( struct fb_fix_screeninfo
*fix
,
797 struct atafb_par
*par
)
799 strcpy(fix
->id
, "Atari Builtin");
800 fix
->smem_start
= (char *)real_screen_base
;
801 fix
->smem_len
= screen_len
;
802 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
804 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
808 if (par
->hw
.falcon
.mono
) {
809 fix
->type
= FB_TYPE_PACKED_PIXELS
;
811 /* no smooth scrolling with longword aligned video mem */
814 else if (par
->hw
.falcon
.f_shift
& 0x100) {
815 fix
->type
= FB_TYPE_PACKED_PIXELS
;
817 /* Is this ok or should it be DIRECTCOLOR? */
818 fix
->visual
= FB_VISUAL_TRUECOLOR
;
821 fix
->line_length
= 0;
822 fix
->accel
= FB_ACCEL_ATARIBLITT
;
827 static int falcon_decode_var( struct fb_var_screeninfo
*var
,
828 struct atafb_par
*par
)
830 int bpp
= var
->bits_per_pixel
;
831 int xres
= var
->xres
;
832 int yres
= var
->yres
;
833 int xres_virtual
= var
->xres_virtual
;
834 int yres_virtual
= var
->yres_virtual
;
835 int left_margin
, right_margin
, hsync_len
;
836 int upper_margin
, lower_margin
, vsync_len
;
838 int interlace
= 0, doubleline
= 0;
839 struct pixel_clock
*pclock
;
840 int plen
; /* width of pixel in clock cycles */
847 Get the video params out of 'var'. If a value doesn't fit, round
848 it up, if it's too big, return EINVAL.
849 Round up in the following order: bits_per_pixel, xres, yres,
850 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
851 horizontal timing, vertical timing.
853 There is a maximum of screen resolution determined by pixelclock
854 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
855 In interlace mode this is " * " *vfmin <= pixelclock.
856 Additional constraints: hfreq.
857 Frequency range for multisync monitors is given via command line.
858 For TV and SM124 both frequencies are fixed.
860 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
861 Y % 16 == 0 to fit 8x16 font
864 Currently interlace and doubleline mode in var are ignored.
865 On SM124 and TV only the standard resolutions can be used.
868 /* Reject uninitialized mode */
869 if (!xres
|| !yres
|| !bpp
)
872 if (mon_type
== F_MON_SM
&& bpp
!= 1) {
877 par
->hw
.falcon
.f_shift
= 0x400;
878 par
->hw
.falcon
.st_shift
= 0x200;
882 par
->hw
.falcon
.f_shift
= 0x000;
883 par
->hw
.falcon
.st_shift
= 0x100;
887 par
->hw
.falcon
.f_shift
= 0x000;
888 par
->hw
.falcon
.st_shift
= 0x000;
892 par
->hw
.falcon
.f_shift
= 0x010;
894 else if (bpp
<= 16) {
895 bpp
= 16; /* packed pixel mode */
896 par
->hw
.falcon
.f_shift
= 0x100; /* hicolor, no overlay */
900 par
->hw
.falcon
.bpp
= bpp
;
902 if (mon_type
== F_MON_SM
|| DontCalcRes
) {
903 /* Skip all calculations. VGA/TV/SC1224 only supported. */
904 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
906 if (bpp
> myvar
->bits_per_pixel
||
907 var
->xres
> myvar
->xres
||
908 var
->yres
> myvar
->yres
)
910 fbhw
->get_par(par
); /* Current par will be new par */
911 goto set_screen_base
; /* Don't forget this */
914 /* Only some fixed resolutions < 640x400 */
917 else if (xres
<= 640 && bpp
!= 16)
921 else if (yres
<= 240)
923 else if (yres
<= 400)
926 /* 2 planes must use STE compatibility mode */
927 par
->hw
.falcon
.ste_mode
= bpp
==2;
928 par
->hw
.falcon
.mono
= bpp
==1;
930 /* Total and visible scanline length must be a multiple of one longword,
931 * this and the console fontwidth yields the alignment for xres and
933 * TODO: this way "odd" fontheights are not supported
935 * Special case in STE mode: blank and graphic positions don't align,
936 * avoid trash at right margin
938 if (par
->hw
.falcon
.ste_mode
)
939 xres
= (xres
+ 63) & ~63;
941 xres
= (xres
+ 31) & ~31;
943 xres
= (xres
+ 15) & ~15;
945 yres
= (yres
+ 15) & ~15;
947 yres
= (yres
+ 7) & ~7;
949 if (xres_virtual
< xres
)
952 xres_virtual
= (xres_virtual
+ 31) & ~31;
954 xres_virtual
= (xres_virtual
+ 15) & ~15;
956 if (yres_virtual
<= 0)
958 else if (yres_virtual
< yres
)
961 /* backward bug-compatibility */
962 if (var
->pixclock
> 1)
965 par
->hw
.falcon
.line_width
= bpp
* xres
/ 16;
966 par
->hw
.falcon
.line_offset
= bpp
* (xres_virtual
- xres
) / 16;
968 /* single or double pixel width */
969 xstretch
= (xres
< 640) ? 2 : 1;
971 #if 0 /* SM124 supports only 640x400, this is rejected above */
972 if (mon_type
== F_MON_SM
) {
973 if (xres
!= 640 && yres
!= 400)
977 /* SM124-mode is special */
978 par
->hw
.falcon
.ste_mode
= 1;
979 par
->hw
.falcon
.f_shift
= 0x000;
980 par
->hw
.falcon
.st_shift
= 0x200;
981 left_margin
= hsync_len
= 128 / plen
;
983 /* TODO set all margins */
987 if (mon_type
== F_MON_SC
|| mon_type
== F_MON_TV
) {
989 if (var
->pixclock
> f32
.t
* plen
)
994 if (var
->pixclock
== 0) {
995 /* set some minimal margins which center the screen */
998 hsync_len
= pclock
->hsync
/ plen
;
1001 vsync_len
= interlace
? 3 : 4;
1003 left_margin
= var
->left_margin
;
1004 right_margin
= var
->right_margin
;
1005 hsync_len
= var
->hsync_len
;
1006 upper_margin
= var
->upper_margin
;
1007 lower_margin
= var
->lower_margin
;
1008 vsync_len
= var
->vsync_len
;
1009 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1010 upper_margin
= (upper_margin
+ 1) / 2;
1011 lower_margin
= (lower_margin
+ 1) / 2;
1012 vsync_len
= (vsync_len
+ 1) / 2;
1013 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1023 xstretch
= 2; /* Double pixel width only for hicolor */
1024 /* Default values are used for vert./hor. timing if no pixelclock given. */
1025 if (var
->pixclock
== 0) {
1028 /* Choose master pixelclock depending on hor. timing */
1029 plen
= 1 * xstretch
;
1030 if ((plen
* xres
+ f25
.right
+f25
.hsync
+f25
.left
) *
1031 fb_info
.monspecs
.hfmin
< f25
.f
)
1033 else if ((plen
* xres
+ f32
.right
+f32
.hsync
+f32
.left
) *
1034 fb_info
.monspecs
.hfmin
< f32
.f
)
1036 else if ((plen
* xres
+ fext
.right
+fext
.hsync
+fext
.left
) *
1037 fb_info
.monspecs
.hfmin
< fext
.f
1043 left_margin
= pclock
->left
/ plen
;
1044 right_margin
= pclock
->right
/ plen
;
1045 hsync_len
= pclock
->hsync
/ plen
;
1046 linesize
= left_margin
+ xres
+ right_margin
+ hsync_len
;
1052 /* Choose largest pixelclock <= wanted clock */
1054 unsigned long pcl
= ULONG_MAX
;
1056 for (i
=1; i
<= 4; i
*= 2) {
1057 if (f25
.t
*i
>= var
->pixclock
&& f25
.t
*i
< pcl
) {
1061 if (f32
.t
*i
>= var
->pixclock
&& f32
.t
*i
< pcl
) {
1065 if (fext
.t
&& fext
.t
*i
>= var
->pixclock
&& fext
.t
*i
< pcl
) {
1072 plen
= pcl
/ pclock
->t
;
1074 left_margin
= var
->left_margin
;
1075 right_margin
= var
->right_margin
;
1076 hsync_len
= var
->hsync_len
;
1077 upper_margin
= var
->upper_margin
;
1078 lower_margin
= var
->lower_margin
;
1079 vsync_len
= var
->vsync_len
;
1080 /* Internal unit is [single lines per (half-)frame] */
1081 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1082 /* # lines in half frame */
1083 /* External unit is [lines per full frame] */
1084 upper_margin
= (upper_margin
+ 1) / 2;
1085 lower_margin
= (lower_margin
+ 1) / 2;
1086 vsync_len
= (vsync_len
+ 1) / 2;
1088 else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1089 /* External unit is [double lines per frame] */
1095 if (pclock
== &fext
)
1096 longoffset
= 1; /* VIDEL doesn't synchronize on short offset */
1098 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1099 /* this is definitely wrong if bus clock != 32MHz */
1100 if (pclock
->f
/ plen
/ 8 * bpp
> 32000000L)
1106 /* include sync lengths in right/lower margin for all calculations */
1107 right_margin
+= hsync_len
;
1108 lower_margin
+= vsync_len
;
1110 /* ! In all calculations of margins we use # of lines in half frame
1111 * (which is a full frame in non-interlace mode), so we can switch
1112 * between interlace and non-interlace without messing around
1116 /* Set base_offset 128 and video bus width */
1117 par
->hw
.falcon
.vid_control
= mon_type
| f030_bus_width
;
1119 par
->hw
.falcon
.vid_control
|= VCO_SHORTOFFS
; /* base_offset 64 */
1120 if (var
->sync
& FB_SYNC_HOR_HIGH_ACT
)
1121 par
->hw
.falcon
.vid_control
|= VCO_HSYPOS
;
1122 if (var
->sync
& FB_SYNC_VERT_HIGH_ACT
)
1123 par
->hw
.falcon
.vid_control
|= VCO_VSYPOS
;
1125 par
->hw
.falcon
.vid_control
|= pclock
->control_mask
;
1126 /* External or internal clock */
1127 par
->hw
.falcon
.sync
= pclock
->sync_mask
| 0x2;
1128 /* Pixellength and prescale */
1129 par
->hw
.falcon
.vid_mode
= (2/plen
) << 2;
1131 par
->hw
.falcon
.vid_mode
|= VMO_DOUBLE
;
1133 par
->hw
.falcon
.vid_mode
|= VMO_INTER
;
1135 /*********************
1136 Horizontal timing: unit = [master clock cycles]
1137 unit of hxx-registers: [master clock cycles * prescale]
1138 Hxx-registers are 9 bit wide
1140 1 line = ((hht + 2) * 2 * prescale) clock cycles
1142 graphic output = hdb & 0x200 ?
1143 ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
1144 ( hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1145 (this must be a multiple of plen*128/bpp, on VGA pixels
1146 to the right may be cut off with a bigger right margin)
1148 start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1149 (hdb - hht - 2) * prescale + hdboff :
1150 hdb * prescale + hdboff
1152 end of graphics relative to start of 1st halfline =
1153 (hde + hht + 2) * prescale + hdeoff
1154 *********************/
1155 /* Calculate VIDEL registers */
1157 int hdb_off
, hde_off
, base_off
;
1158 int gstart
, gend1
, gend2
, align
;
1160 prescale
= hxx_prescale(&par
->hw
.falcon
);
1161 base_off
= par
->hw
.falcon
.vid_control
& VCO_SHORTOFFS
? 64 : 128;
1163 /* Offsets depend on video mode */
1164 /* Offsets are in clock cycles, divide by prescale to
1165 * calculate hd[be]-registers
1167 if (par
->hw
.falcon
.f_shift
& 0x100) {
1170 hdb_off
= (base_off
+ 16 * plen
) + prescale
;
1174 hde_off
= ((128 / bpp
+ 2) * plen
);
1175 if (par
->hw
.falcon
.ste_mode
)
1176 hdb_off
= (64 + base_off
+ (128 / bpp
+ 2) * plen
) + prescale
;
1178 hdb_off
= (base_off
+ (128 / bpp
+ 18) * plen
) + prescale
;
1181 gstart
= (prescale
/2 + plen
* left_margin
) / prescale
;
1182 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1183 gend1
= gstart
+ ((xres
+ align
-1) / align
)*align
* plen
/ prescale
;
1184 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1185 gend2
= gstart
+ xres
* plen
/ prescale
;
1186 par
->HHT
= plen
* (left_margin
+ xres
+ right_margin
) /
1188 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1190 par
->HDB
= gstart
- hdb_off
/prescale
;
1192 if (par
->HDB
< 0) par
->HDB
+= par
->HHT
+ 2 + 0x200;
1193 par
->HDE
= gend1
- par
->HHT
- 2 - hde_off
/prescale
;
1194 par
->HBB
= gend2
- par
->HHT
- 2;
1196 /* One more Videl constraint: data fetch of two lines must not overlap */
1197 if (par
->HDB
& 0x200 && par
->HDB
& ~0x200 - par
->HDE
<= 5) {
1198 /* if this happens increase margins, decrease hfreq. */
1201 if (hde_off
% prescale
)
1202 par
->HBB
++; /* compensate for non matching hde and hbb */
1203 par
->HSS
= par
->HHT
+ 2 - plen
* hsync_len
/ prescale
;
1204 if (par
->HSS
< par
->HBB
)
1205 par
->HSS
= par
->HBB
;
1208 /* check hor. frequency */
1209 hfreq
= pclock
->f
/ ((par
->HHT
+2)*prescale
*2);
1210 if (hfreq
> fb_info
.monspecs
.hfmax
&& mon_type
!=F_MON_VGA
) {
1211 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1212 /* Too high -> enlarge margin */
1217 if (hfreq
> fb_info
.monspecs
.hfmax
|| hfreq
< fb_info
.monspecs
.hfmin
)
1221 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1222 * of the first displayed line!
1223 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1224 * non-interlace, odd in interlace mode for synchronisation.
1225 * Vxx-registers are 11 bit wide
1227 par
->VBE
= (upper_margin
* 2 + 1); /* must begin on odd halfline */
1228 par
->VDB
= par
->VBE
;
1230 if (!interlace
) par
->VDE
<<= 1;
1231 if (doubleline
) par
->VDE
<<= 1; /* VDE now half lines per (half-)frame */
1232 par
->VDE
+= par
->VDB
;
1233 par
->VBB
= par
->VDE
;
1234 par
->VFT
= par
->VBB
+ (lower_margin
* 2 - 1) - 1;
1235 par
->VSS
= par
->VFT
+1 - (vsync_len
* 2 - 1);
1236 /* vbb,vss,vft must be even in interlace mode */
1243 /* V-frequency check, hope I didn't create any loop here. */
1244 /* Interlace and doubleline are mutually exclusive. */
1245 vfreq
= (hfreq
* 2) / (par
->VFT
+ 1);
1246 if (vfreq
> fb_info
.monspecs
.vfmax
&& !doubleline
&& !interlace
) {
1247 /* Too high -> try again with doubleline */
1251 else if (vfreq
< fb_info
.monspecs
.vfmin
&& !interlace
&& !doubleline
) {
1252 /* Too low -> try again with interlace */
1256 else if (vfreq
< fb_info
.monspecs
.vfmin
&& doubleline
) {
1257 /* Doubleline too low -> clear doubleline and enlarge margins */
1261 (hfreq
*2)/(par
->VFT
+1+4*lines
-2*yres
)>fb_info
.monspecs
.vfmax
;
1264 upper_margin
+= lines
;
1265 lower_margin
+= lines
;
1268 else if (vfreq
> fb_info
.monspecs
.vfmax
&& doubleline
) {
1269 /* Doubleline too high -> enlarge margins */
1272 (hfreq
*2)/(par
->VFT
+1+4*lines
)>fb_info
.monspecs
.vfmax
;
1275 upper_margin
+= lines
;
1276 lower_margin
+= lines
;
1279 else if (vfreq
> fb_info
.monspecs
.vfmax
&& interlace
) {
1280 /* Interlace, too high -> enlarge margins */
1283 (hfreq
*2)/(par
->VFT
+1+4*lines
)>fb_info
.monspecs
.vfmax
;
1286 upper_margin
+= lines
;
1287 lower_margin
+= lines
;
1290 else if (vfreq
< fb_info
.monspecs
.vfmin
||
1291 vfreq
> fb_info
.monspecs
.vfmax
)
1295 linelen
= xres_virtual
* bpp
/ 8;
1296 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
1298 if (yres
* linelen
> screen_len
&& screen_len
)
1300 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
1302 par
->yres_virtual
= yres_virtual
;
1303 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
1304 par
->hw
.falcon
.xoffset
= 0;
1309 static int falcon_encode_var( struct fb_var_screeninfo
*var
,
1310 struct atafb_par
*par
)
1312 /* !!! only for VGA !!! */
1315 int hdb_off
, hde_off
, base_off
;
1316 struct falcon_hw
*hw
= &par
->hw
.falcon
;
1318 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
1319 /* possible frequencies: 25.175 or 32MHz */
1320 var
->pixclock
= hw
->sync
& 0x1 ? fext
.t
:
1321 hw
->vid_control
& VCO_CLOCK25
? f25
.t
: f32
.t
;
1327 if (hw
->vid_control
& VCO_HSYPOS
)
1328 var
->sync
|= FB_SYNC_HOR_HIGH_ACT
;
1329 if (hw
->vid_control
& VCO_VSYPOS
)
1330 var
->sync
|= FB_SYNC_VERT_HIGH_ACT
;
1332 var
->vmode
= FB_VMODE_NONINTERLACED
;
1333 if (hw
->vid_mode
& VMO_INTER
)
1334 var
->vmode
|= FB_VMODE_INTERLACED
;
1335 if (hw
->vid_mode
& VMO_DOUBLE
)
1336 var
->vmode
|= FB_VMODE_DOUBLE
;
1338 /* visible y resolution:
1339 * Graphics display starts at line VDB and ends at line
1340 * VDE. If interlace mode off unit of VC-registers is
1341 * half lines, else lines.
1343 var
->yres
= hw
->vde
- hw
->vdb
;
1344 if (!(var
->vmode
& FB_VMODE_INTERLACED
))
1346 if (var
->vmode
& FB_VMODE_DOUBLE
)
1349 /* to get bpp, we must examine f_shift and st_shift.
1350 * f_shift is valid if any of bits no. 10, 8 or 4
1351 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1352 * if bit 10 set then bit 8 and bit 4 don't care...
1353 * If all these bits are 0 get display depth from st_shift
1354 * (as for ST and STE)
1356 if (hw
->f_shift
& 0x400) /* 2 colors */
1357 var
->bits_per_pixel
= 1;
1358 else if (hw
->f_shift
& 0x100) /* hicolor */
1359 var
->bits_per_pixel
= 16;
1360 else if (hw
->f_shift
& 0x010) /* 8 bitplanes */
1361 var
->bits_per_pixel
= 8;
1362 else if (hw
->st_shift
== 0)
1363 var
->bits_per_pixel
= 4;
1364 else if (hw
->st_shift
== 0x100)
1365 var
->bits_per_pixel
= 2;
1366 else /* if (hw->st_shift == 0x200) */
1367 var
->bits_per_pixel
= 1;
1369 var
->xres
= hw
->line_width
* 16 / var
->bits_per_pixel
;
1370 var
->xres_virtual
= var
->xres
+ hw
->line_offset
* 16 / var
->bits_per_pixel
;
1372 var
->xres_virtual
+= 16;
1374 if (var
->bits_per_pixel
== 16) {
1377 var
->red
.msb_right
=0;
1378 var
->green
.offset
=5;
1379 var
->green
.length
=6;
1380 var
->green
.msb_right
=0;
1383 var
->blue
.msb_right
=0;
1387 var
->red
.length
= hw
->ste_mode
? 4 : 6;
1388 var
->red
.msb_right
=0;
1390 var
->blue
=var
->green
=var
->red
;
1392 var
->transp
.offset
=0;
1393 var
->transp
.length
=0;
1394 var
->transp
.msb_right
=0;
1396 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
1398 if (par
->yres_virtual
)
1399 var
->yres_virtual
= par
->yres_virtual
;
1401 /* yres_virtual==0 means use maximum */
1402 var
->yres_virtual
= screen_len
/ linelen
;
1406 var
->yres_virtual
= 2 * var
->yres
;
1408 var
->yres_virtual
=var
->yres
+hwscroll
* 16;
1410 var
->xoffset
=0; /* TODO change this */
1413 prescale
= hxx_prescale(hw
);
1414 plen
= 4 >> (hw
->vid_mode
>> 2 & 0x3);
1415 base_off
= hw
->vid_control
& VCO_SHORTOFFS
? 64 : 128;
1416 if (hw
->f_shift
& 0x100) {
1418 hdb_off
= (base_off
+ 16 * plen
) + prescale
;
1421 hde_off
= ((128 / var
->bits_per_pixel
+ 2) * plen
);
1423 hdb_off
= (64 + base_off
+ (128 / var
->bits_per_pixel
+ 2) * plen
)
1426 hdb_off
= (base_off
+ (128 / var
->bits_per_pixel
+ 18) * plen
)
1430 /* Right margin includes hsync */
1431 var
->left_margin
= hdb_off
+ prescale
* ((hw
->hdb
& 0x1ff) -
1432 (hw
->hdb
& 0x200 ? 2+hw
->hht
: 0));
1433 if (hw
->ste_mode
|| mon_type
!=F_MON_VGA
)
1434 var
->right_margin
= prescale
* (hw
->hht
+ 2 - hw
->hde
) - hde_off
;
1436 /* can't use this in ste_mode, because hbb is +1 off */
1437 var
->right_margin
= prescale
* (hw
->hht
+ 2 - hw
->hbb
);
1438 var
->hsync_len
= prescale
* (hw
->hht
+ 2 - hw
->hss
);
1440 /* Lower margin includes vsync */
1441 var
->upper_margin
= hw
->vdb
/ 2 ; /* round down to full lines */
1442 var
->lower_margin
= (hw
->vft
+1 - hw
->vde
+ 1) / 2; /* round up */
1443 var
->vsync_len
= (hw
->vft
+1 - hw
->vss
+ 1) / 2; /* round up */
1444 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1445 var
->upper_margin
*= 2;
1446 var
->lower_margin
*= 2;
1447 var
->vsync_len
*= 2;
1449 else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1450 var
->upper_margin
= (var
->upper_margin
+ 1) / 2;
1451 var
->lower_margin
= (var
->lower_margin
+ 1) / 2;
1452 var
->vsync_len
= (var
->vsync_len
+ 1) / 2;
1455 var
->pixclock
*= plen
;
1456 var
->left_margin
/= plen
;
1457 var
->right_margin
/= plen
;
1458 var
->hsync_len
/= plen
;
1460 var
->right_margin
-= var
->hsync_len
;
1461 var
->lower_margin
-= var
->vsync_len
;
1464 var
->yoffset
=(par
->screen_base
- screen_base
)/linelen
;
1467 var
->nonstd
=0; /* what is this for? */
1473 static int f_change_mode
= 0;
1474 static struct falcon_hw f_new_mode
;
1475 static int f_pan_display
= 0;
1477 static void falcon_get_par( struct atafb_par
*par
)
1480 struct falcon_hw
*hw
= &par
->hw
.falcon
;
1482 hw
->line_width
= shifter_f030
.scn_width
;
1483 hw
->line_offset
= shifter_f030
.off_next
;
1484 hw
->st_shift
= videl
.st_shift
& 0x300;
1485 hw
->f_shift
= videl
.f_shift
;
1486 hw
->vid_control
= videl
.control
;
1487 hw
->vid_mode
= videl
.mode
;
1488 hw
->sync
= shifter
.syncmode
& 0x1;
1489 hw
->xoffset
= videl
.xoffset
& 0xf;
1490 hw
->hht
= videl
.hht
;
1491 hw
->hbb
= videl
.hbb
;
1492 hw
->hbe
= videl
.hbe
;
1493 hw
->hdb
= videl
.hdb
;
1494 hw
->hde
= videl
.hde
;
1495 hw
->hss
= videl
.hss
;
1496 hw
->vft
= videl
.vft
;
1497 hw
->vbb
= videl
.vbb
;
1498 hw
->vbe
= videl
.vbe
;
1499 hw
->vdb
= videl
.vdb
;
1500 hw
->vde
= videl
.vde
;
1501 hw
->vss
= videl
.vss
;
1503 addr
= (shifter
.bas_hi
& 0xff) << 16 |
1504 (shifter
.bas_md
& 0xff) << 8 |
1505 (shifter
.bas_lo
& 0xff);
1506 par
->screen_base
= phys_to_virt(addr
);
1508 /* derived parameters */
1509 hw
->ste_mode
= (hw
->f_shift
& 0x510)==0 && hw
->st_shift
==0x100;
1510 hw
->mono
= (hw
->f_shift
& 0x400) ||
1511 ((hw
->f_shift
& 0x510)==0 && hw
->st_shift
==0x200);
1514 static void falcon_set_par( struct atafb_par
*par
)
1518 /* only set screen_base if really necessary */
1519 if (current_par
.screen_base
!= par
->screen_base
)
1520 fbhw
->set_screen_base(par
->screen_base
);
1522 /* Don't touch any other registers if we keep the default resolution */
1526 /* Tell vbl-handler to change video mode.
1527 * We change modes only on next VBL, to avoid desynchronisation
1528 * (a shift to the right and wrap around by a random number of pixels
1529 * in all monochrome modes).
1530 * This seems to work on my Falcon.
1532 f_new_mode
= par
->hw
.falcon
;
1537 static void falcon_vbl_switcher( int irq
, void *dummy
, struct pt_regs
*fp
)
1539 struct falcon_hw
*hw
= &f_new_mode
;
1541 if (f_change_mode
) {
1544 if (hw
->sync
& 0x1) {
1545 /* Enable external pixelclock. This code only for ScreenWonder */
1546 *(volatile unsigned short*)0xffff9202 = 0xffbf;
1549 /* Turn off external clocks. Read sets all output bits to 1. */
1550 *(volatile unsigned short*)0xffff9202;
1552 shifter
.syncmode
= hw
->sync
;
1554 videl
.hht
= hw
->hht
;
1555 videl
.hbb
= hw
->hbb
;
1556 videl
.hbe
= hw
->hbe
;
1557 videl
.hdb
= hw
->hdb
;
1558 videl
.hde
= hw
->hde
;
1559 videl
.hss
= hw
->hss
;
1560 videl
.vft
= hw
->vft
;
1561 videl
.vbb
= hw
->vbb
;
1562 videl
.vbe
= hw
->vbe
;
1563 videl
.vdb
= hw
->vdb
;
1564 videl
.vde
= hw
->vde
;
1565 videl
.vss
= hw
->vss
;
1567 videl
.f_shift
= 0; /* write enables Falcon palette, 0: 4 planes */
1569 videl
.st_shift
= hw
->st_shift
; /* write enables STE palette */
1573 * set st_shift 0, so we can tell the screen-depth if f_shift==0.
1574 * Writing 0 to f_shift enables 4 plane Falcon mode but
1575 * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
1576 * with Falcon palette.
1579 /* now back to Falcon palette mode */
1580 videl
.f_shift
= hw
->f_shift
;
1582 /* writing to st_shift changed scn_width and vid_mode */
1583 videl
.xoffset
= hw
->xoffset
;
1584 shifter_f030
.scn_width
= hw
->line_width
;
1585 shifter_f030
.off_next
= hw
->line_offset
;
1586 videl
.control
= hw
->vid_control
;
1587 videl
.mode
= hw
->vid_mode
;
1589 if (f_pan_display
) {
1591 videl
.xoffset
= current_par
.hw
.falcon
.xoffset
;
1592 shifter_f030
.off_next
= current_par
.hw
.falcon
.line_offset
;
1597 static int falcon_pan_display( struct fb_var_screeninfo
*var
,
1598 struct atafb_par
*par
)
1601 int bpp
= fb_display
[currcon
].var
.bits_per_pixel
;
1604 var
->xoffset
= up(var
->xoffset
, 32);
1606 par
->hw
.falcon
.xoffset
= var
->xoffset
& 15;
1608 par
->hw
.falcon
.xoffset
= 0;
1609 var
->xoffset
= up(var
->xoffset
, 2);
1611 par
->hw
.falcon
.line_offset
= bpp
*
1612 (fb_display
[currcon
].var
.xres_virtual
- fb_display
[currcon
].var
.xres
) / 16;
1613 if (par
->hw
.falcon
.xoffset
)
1614 par
->hw
.falcon
.line_offset
-= bpp
;
1615 xoffset
= var
->xoffset
- par
->hw
.falcon
.xoffset
;
1617 par
->screen_base
= screen_base
+
1618 (var
->yoffset
* fb_display
[currcon
].var
.xres_virtual
+ xoffset
) * bpp
/ 8;
1619 if (fbhw
->set_screen_base
)
1620 fbhw
->set_screen_base (par
->screen_base
);
1622 return -EINVAL
; /* shouldn't happen */
1628 static int falcon_getcolreg( unsigned regno
, unsigned *red
,
1629 unsigned *green
, unsigned *blue
,
1630 unsigned *transp
, struct fb_info
*info
)
1631 { unsigned long col
;
1635 /* This works in STE-mode (with 4bit/color) since f030_col-registers
1636 * hold up to 6bit/color.
1637 * Even with hicolor r/g/b=5/6/5 bit!
1639 col
= f030_col
[regno
];
1640 *red
= (col
>> 16) & 0xff00;
1641 *green
= (col
>> 8) & 0xff00;
1642 *blue
= (col
<< 8) & 0xff00;
1648 static int falcon_setcolreg( unsigned regno
, unsigned red
,
1649 unsigned green
, unsigned blue
,
1650 unsigned transp
, struct fb_info
*info
)
1654 f030_col
[regno
] = (((red
& 0xfc00) << 16) |
1655 ((green
& 0xfc00) << 8) |
1656 ((blue
& 0xfc00) >> 8));
1658 shifter_tt
.color_reg
[regno
] =
1659 (((red
& 0xe000) >> 13) | ((red
& 0x1000) >> 12) << 8) |
1660 (((green
& 0xe000) >> 13) | ((green
& 0x1000) >> 12) << 4) |
1661 ((blue
& 0xe000) >> 13) | ((blue
& 0x1000) >> 12);
1662 #ifdef FBCON_HAS_CFB16
1663 fbcon_cfb16_cmap
[regno
] = ((red
& 0xf800) |
1664 ((green
& 0xfc00) >> 5) |
1665 ((blue
& 0xf800) >> 11));
1672 static int falcon_blank( int blank_mode
)
1674 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1675 * so VIDEL doesn't hog the bus while saving.
1676 * (this may affect usleep()).
1678 int vdb
, vss
, hbe
, hss
;
1680 if (mon_type
== F_MON_SM
) /* this doesn't work on SM124 */
1683 vdb
= current_par
.VDB
;
1684 vss
= current_par
.VSS
;
1685 hbe
= current_par
.HBE
;
1686 hss
= current_par
.HSS
;
1688 if (blank_mode
>= 1) {
1689 /* disable graphics output (this speeds up the CPU) ... */
1690 vdb
= current_par
.VFT
+ 1;
1691 /* ... and blank all lines */
1692 hbe
= current_par
.HHT
+ 2;
1694 /* use VESA suspend modes on VGA monitors */
1695 if (mon_type
== F_MON_VGA
) {
1696 if (blank_mode
== 2 || blank_mode
== 4)
1697 vss
= current_par
.VFT
+ 1;
1698 if (blank_mode
== 3 || blank_mode
== 4)
1699 hss
= current_par
.HHT
+ 2;
1711 static int falcon_detect( void )
1713 struct atafb_par par
;
1716 /* Determine connected monitor and set monitor parameters */
1717 fhw
= *(unsigned char*)0xffff8006;
1718 mon_type
= fhw
>> 6 & 0x3;
1719 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1720 f030_bus_width
= fhw
<< 6 & 0x80;
1723 fb_info
.monspecs
.vfmin
= 70;
1724 fb_info
.monspecs
.vfmax
= 72;
1725 fb_info
.monspecs
.hfmin
= 35713;
1726 fb_info
.monspecs
.hfmax
= 35715;
1731 fb_info
.monspecs
.vfmin
= 49; /* not 50, since TOS defaults to 49.9x Hz */
1732 fb_info
.monspecs
.vfmax
= 60;
1733 fb_info
.monspecs
.hfmin
= 15620;
1734 fb_info
.monspecs
.hfmax
= 15755;
1737 /* initialize hsync-len */
1738 f25
.hsync
= h_syncs
[mon_type
] / f25
.t
;
1739 f32
.hsync
= h_syncs
[mon_type
] / f32
.t
;
1741 fext
.hsync
= h_syncs
[mon_type
] / fext
.t
;
1743 falcon_get_par(&par
);
1744 falcon_encode_var(&atafb_predefined
[0], &par
);
1746 /* Detected mode is always the "autodetect" slot */
1750 #endif /* ATAFB_FALCON */
1752 /* ------------------- ST(E) specific functions ---------------------- */
1756 static int stste_encode_fix( struct fb_fix_screeninfo
*fix
,
1757 struct atafb_par
*par
)
1762 strcpy(fix
->id
,"Atari Builtin");
1763 fix
->smem_start
= (char *)real_screen_base
;
1764 fix
->smem_len
= screen_len
;
1765 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
1767 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
1768 mode
= par
->hw
.st
.mode
& 3;
1769 if (mode
== ST_HIGH
) {
1770 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1772 fix
->visual
= FB_VISUAL_MONO10
;
1774 if (ATARIHW_PRESENT(EXTD_SHIFTER
)) {
1782 fix
->line_length
= 0;
1783 fix
->accel
= FB_ACCEL_ATARIBLITT
;
1788 static int stste_decode_var( struct fb_var_screeninfo
*var
,
1789 struct atafb_par
*par
)
1793 int bpp
=var
->bits_per_pixel
;
1795 int yres_virtual
= var
->yres_virtual
;
1798 if (bpp
> 1 || xres
> sttt_xres
|| yres
> st_yres
)
1800 par
->hw
.st
.mode
=ST_HIGH
;
1805 if (bpp
> 4 || xres
> sttt_xres
|| yres
> st_yres
)
1808 if (xres
> sttt_xres
/2 || yres
> st_yres
/2)
1810 par
->hw
.st
.mode
=ST_LOW
;
1816 if (xres
> sttt_xres
|| yres
> st_yres
/2)
1818 par
->hw
.st
.mode
=ST_MID
;
1826 if (yres_virtual
<= 0)
1828 else if (yres_virtual
< yres
)
1829 yres_virtual
= yres
;
1830 if (var
->sync
& FB_SYNC_EXT
)
1831 par
->hw
.st
.sync
=(par
->hw
.st
.sync
& ~1) | 1;
1833 par
->hw
.st
.sync
=(par
->hw
.st
.sync
& ~1);
1835 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
1837 if (yres
* linelen
> screen_len
&& screen_len
)
1839 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
1841 par
->yres_virtual
= yres_virtual
;
1842 par
->screen_base
=screen_base
+ var
->yoffset
*linelen
;
1846 static int stste_encode_var( struct fb_var_screeninfo
*var
,
1847 struct atafb_par
*par
)
1850 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
1852 var
->red
.length
= ATARIHW_PRESENT(EXTD_SHIFTER
) ? 4 : 3;
1853 var
->red
.msb_right
=0;
1856 var
->pixclock
=31041;
1857 var
->left_margin
=120; /* these are incorrect */
1858 var
->right_margin
=100;
1859 var
->upper_margin
=8;
1860 var
->lower_margin
=16;
1867 if (!(par
->hw
.st
.sync
& 1))
1870 var
->sync
=FB_SYNC_EXT
;
1872 switch (par
->hw
.st
.mode
& 3) {
1874 var
->xres
=sttt_xres
/2;
1875 var
->yres
=st_yres
/2;
1876 var
->bits_per_pixel
=4;
1879 var
->xres
=sttt_xres
;
1880 var
->yres
=st_yres
/2;
1881 var
->bits_per_pixel
=2;
1884 var
->xres
=sttt_xres
;
1886 var
->bits_per_pixel
=1;
1889 var
->blue
=var
->green
=var
->red
;
1890 var
->transp
.offset
=0;
1891 var
->transp
.length
=0;
1892 var
->transp
.msb_right
=0;
1893 var
->xres_virtual
=sttt_xres_virtual
;
1894 linelen
=var
->xres_virtual
* var
->bits_per_pixel
/ 8;
1895 ovsc_addlen
=linelen
*(sttt_yres_virtual
- st_yres
);
1898 var
->yres_virtual
=var
->yres
;
1899 else if (screen_len
) {
1900 if (par
->yres_virtual
)
1901 var
->yres_virtual
= par
->yres_virtual
;
1903 /* yres_virtual==0 means use maximum */
1904 var
->yres_virtual
= screen_len
/ linelen
;
1908 var
->yres_virtual
= 2 * var
->yres
;
1910 var
->yres_virtual
=var
->yres
+hwscroll
* 16;
1914 var
->yoffset
=(par
->screen_base
- screen_base
)/linelen
;
1919 var
->vmode
=FB_VMODE_NONINTERLACED
;
1924 static void stste_get_par( struct atafb_par
*par
)
1927 par
->hw
.st
.mode
=shifter_tt
.st_shiftmode
;
1928 par
->hw
.st
.sync
=shifter
.syncmode
;
1929 addr
= ((shifter
.bas_hi
& 0xff) << 16) |
1930 ((shifter
.bas_md
& 0xff) << 8);
1931 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
1932 addr
|= (shifter
.bas_lo
& 0xff);
1933 par
->screen_base
= phys_to_virt(addr
);
1936 static void stste_set_par( struct atafb_par
*par
)
1938 shifter_tt
.st_shiftmode
=par
->hw
.st
.mode
;
1939 shifter
.syncmode
=par
->hw
.st
.sync
;
1940 /* only set screen_base if really necessary */
1941 if (current_par
.screen_base
!= par
->screen_base
)
1942 fbhw
->set_screen_base(par
->screen_base
);
1946 static int stste_getcolreg(unsigned regno
, unsigned *red
,
1947 unsigned *green
, unsigned *blue
,
1948 unsigned *transp
, struct fb_info
*info
)
1954 col
= shifter_tt
.color_reg
[regno
];
1955 if (ATARIHW_PRESENT(EXTD_SHIFTER
)) {
1956 t
= ((col
>> 7) & 0xe) | ((col
>> 11) & 1);
1958 *red
= t
| (t
<< 8);
1959 t
= ((col
>> 3) & 0xe) | ((col
>> 7) & 1);
1961 *green
= t
| (t
<< 8);
1962 t
= ((col
<< 1) & 0xe) | ((col
>> 3) & 1);
1964 *blue
= t
| (t
<< 8);
1967 t
= (col
>> 7) & 0xe;
1969 *red
= t
| (t
<< 8);
1970 t
= (col
>> 3) & 0xe;
1972 *green
= t
| (t
<< 8);
1973 t
= (col
<< 1) & 0xe;
1975 *blue
= t
| (t
<< 8);
1982 static int stste_setcolreg(unsigned regno
, unsigned red
,
1983 unsigned green
, unsigned blue
,
1984 unsigned transp
, struct fb_info
*info
)
1991 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
1992 shifter_tt
.color_reg
[regno
] =
1993 (((red
& 0xe) >> 1) | ((red
& 1) << 3) << 8) |
1994 (((green
& 0xe) >> 1) | ((green
& 1) << 3) << 4) |
1995 ((blue
& 0xe) >> 1) | ((blue
& 1) << 3);
1997 shifter_tt
.color_reg
[regno
] =
1998 ((red
& 0xe) << 7) |
1999 ((green
& 0xe) << 3) |
2000 ((blue
& 0xe) >> 1);
2005 static int stste_detect( void )
2007 { struct atafb_par par
;
2009 /* Determine the connected monitor: The DMA sound must be
2010 * disabled before reading the MFP GPIP, because the Sound
2011 * Done Signal and the Monochrome Detect are XORed together!
2013 if (ATARIHW_PRESENT(PCM_8BIT
)) {
2014 tt_dmasnd
.ctrl
= DMASND_CTRL_OFF
;
2015 udelay(20); /* wait a while for things to settle down */
2017 mono_moni
= (mfp
.par_dt_reg
& 0x80) == 0;
2019 stste_get_par(&par
);
2020 stste_encode_var(&atafb_predefined
[0], &par
);
2022 if (!ATARIHW_PRESENT(EXTD_SHIFTER
))
2027 static void stste_set_screen_base(unsigned long s_base
)
2030 addr
= virt_to_phys(s_base
);
2031 /* Setup Screen Memory */
2032 shifter
.bas_hi
=(unsigned char) ((addr
& 0xff0000) >> 16);
2033 shifter
.bas_md
=(unsigned char) ((addr
& 0x00ff00) >> 8);
2034 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
2035 shifter
.bas_lo
=(unsigned char) (addr
& 0x0000ff);
2038 #endif /* ATAFB_STE */
2040 /* Switching the screen size should be done during vsync, otherwise
2041 * the margins may get messed up. This is a well known problem of
2042 * the ST's video system.
2044 * Unfortunately there is hardly any way to find the vsync, as the
2045 * vertical blank interrupt is no longer in time on machines with
2046 * overscan type modifications.
2048 * We can, however, use Timer B to safely detect the black shoulder,
2049 * but then we've got to guess an appropriate delay to find the vsync.
2050 * This might not work on every machine.
2052 * martin_rogge @ ki.maus.de, 8th Aug 1995
2055 #define LINE_DELAY (mono_moni ? 30 : 70)
2056 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2058 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2059 static void st_ovsc_switch(void)
2061 unsigned long flags
;
2062 register unsigned char old
, new;
2064 if (!(atari_switches
& ATARI_SWITCH_OVSC_MASK
))
2069 mfp
.tim_ct_b
= 0x10;
2070 mfp
.active_edge
|= 8;
2072 mfp
.tim_dt_b
= 0xf0;
2074 while (mfp
.tim_dt_b
> 1) /* TOS does it this way, don't ask why */
2081 } while (old
!= new);
2082 mfp
.tim_ct_b
= 0x10;
2085 if (atari_switches
& ATARI_SWITCH_OVSC_IKBD
)
2086 acia
.key_ctrl
= ACIA_DIV64
| ACIA_D8N1S
| ACIA_RHTID
| ACIA_RIE
;
2087 if (atari_switches
& ATARI_SWITCH_OVSC_MIDI
)
2088 acia
.mid_ctrl
= ACIA_DIV16
| ACIA_D8N1S
| ACIA_RHTID
;
2089 if (atari_switches
& (ATARI_SWITCH_OVSC_SND6
|ATARI_SWITCH_OVSC_SND7
)) {
2090 sound_ym
.rd_data_reg_sel
= 14;
2091 sound_ym
.wd_data
= sound_ym
.rd_data_reg_sel
|
2092 ((atari_switches
&ATARI_SWITCH_OVSC_SND6
) ? 0x40:0) |
2093 ((atari_switches
&ATARI_SWITCH_OVSC_SND7
) ? 0x80:0);
2095 restore_flags(flags
);
2098 /* ------------------- External Video ---------------------- */
2102 static int ext_encode_fix( struct fb_fix_screeninfo
*fix
,
2103 struct atafb_par
*par
)
2106 strcpy(fix
->id
,"Unknown Extern");
2107 fix
->smem_start
=(char *)external_addr
;
2108 fix
->smem_len
=(external_len
+ PAGE_SIZE
-1) & PAGE_MASK
;
2109 if (external_depth
== 1) {
2110 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2111 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2112 * for "normal" and "inverted", rsp., in the monochrome case */
2114 (external_pmode
== FB_TYPE_INTERLEAVED_PLANES
||
2115 external_pmode
== FB_TYPE_PACKED_PIXELS
) ?
2120 /* Use STATIC if we don't know how to access color registers */
2121 int visual
= external_vgaiobase
?
2122 FB_VISUAL_PSEUDOCOLOR
:
2123 FB_VISUAL_STATIC_PSEUDOCOLOR
;
2124 switch (external_pmode
) {
2125 case -1: /* truecolor */
2126 fix
->type
=FB_TYPE_PACKED_PIXELS
;
2127 fix
->visual
=FB_VISUAL_TRUECOLOR
;
2129 case FB_TYPE_PACKED_PIXELS
:
2130 fix
->type
=FB_TYPE_PACKED_PIXELS
;
2133 case FB_TYPE_PLANES
:
2134 fix
->type
=FB_TYPE_PLANES
;
2137 case FB_TYPE_INTERLEAVED_PLANES
:
2138 fix
->type
=FB_TYPE_INTERLEAVED_PLANES
;
2147 fix
->line_length
= 0;
2152 static int ext_decode_var( struct fb_var_screeninfo
*var
,
2153 struct atafb_par
*par
)
2155 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
2157 if (var
->bits_per_pixel
> myvar
->bits_per_pixel
||
2158 var
->xres
> myvar
->xres
||
2159 var
->xres_virtual
> myvar
->xres_virtual
||
2160 var
->yres
> myvar
->yres
||
2168 static int ext_encode_var( struct fb_var_screeninfo
*var
,
2169 struct atafb_par
*par
)
2171 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
2173 var
->red
.length
=(external_pmode
== -1) ? external_depth
/3 :
2174 (external_vgaiobase
? external_bitspercol
: 0);
2175 var
->red
.msb_right
=0;
2178 var
->pixclock
=31041;
2179 var
->left_margin
=120; /* these are surely incorrect */
2180 var
->right_margin
=100;
2181 var
->upper_margin
=8;
2182 var
->lower_margin
=16;
2191 var
->xres
= external_xres
;
2192 var
->yres
= external_yres
;
2193 var
->xres_virtual
= external_xres_virtual
;
2194 var
->bits_per_pixel
= external_depth
;
2196 var
->blue
=var
->green
=var
->red
;
2197 var
->transp
.offset
=0;
2198 var
->transp
.length
=0;
2199 var
->transp
.msb_right
=0;
2200 var
->yres_virtual
=var
->yres
;
2205 var
->vmode
=FB_VMODE_NONINTERLACED
;
2210 static void ext_get_par( struct atafb_par
*par
)
2212 par
->screen_base
= external_addr
;
2215 static void ext_set_par( struct atafb_par
*par
)
2219 #define OUTB(port,val) \
2220 *((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
2222 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2225 unsigned char tmp=INB(0x3da); \
2229 static int ext_getcolreg( unsigned regno
, unsigned *red
,
2230 unsigned *green
, unsigned *blue
,
2231 unsigned *transp
, struct fb_info
*info
)
2233 if (! external_vgaiobase
)
2236 *red
= ext_color
[regno
].red
;
2237 *green
= ext_color
[regno
].green
;
2238 *blue
= ext_color
[regno
].blue
;
2243 static int ext_setcolreg( unsigned regno
, unsigned red
,
2244 unsigned green
, unsigned blue
,
2245 unsigned transp
, struct fb_info
*info
)
2247 { unsigned char colmask
= (1 << external_bitspercol
) - 1;
2249 if (! external_vgaiobase
)
2252 ext_color
[regno
].red
= red
;
2253 ext_color
[regno
].green
= green
;
2254 ext_color
[regno
].blue
= blue
;
2256 switch (external_card_type
) {
2260 OUTB(0x3c9, red
& colmask
);
2262 OUTB(0x3c9, green
& colmask
);
2264 OUTB(0x3c9, blue
& colmask
);
2269 OUTB((MV300_reg
[regno
] << 2)+1, red
);
2270 OUTB((MV300_reg
[regno
] << 2)+1, green
);
2271 OUTB((MV300_reg
[regno
] << 2)+1, blue
);
2280 static int ext_detect( void )
2283 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
2284 struct atafb_par dummy_par
;
2286 myvar
->xres
= external_xres
;
2287 myvar
->xres_virtual
= external_xres_virtual
;
2288 myvar
->yres
= external_yres
;
2289 myvar
->bits_per_pixel
= external_depth
;
2290 ext_encode_var(myvar
, &dummy_par
);
2294 #endif /* ATAFB_EXT */
2296 /* ------ This is the same for most hardware types -------- */
2298 static void set_screen_base(unsigned long s_base
)
2301 addr
= virt_to_phys(s_base
);
2302 /* Setup Screen Memory */
2303 shifter
.bas_hi
=(unsigned char) ((addr
& 0xff0000) >> 16);
2304 shifter
.bas_md
=(unsigned char) ((addr
& 0x00ff00) >> 8);
2305 shifter
.bas_lo
=(unsigned char) (addr
& 0x0000ff);
2309 static int pan_display( struct fb_var_screeninfo
*var
,
2310 struct atafb_par
*par
)
2312 if (!fbhw
->set_screen_base
||
2313 (!ATARIHW_PRESENT(EXTD_SHIFTER
) && var
->xoffset
))
2315 var
->xoffset
= up(var
->xoffset
, 16);
2316 par
->screen_base
= screen_base
+
2317 (var
->yoffset
* fb_display
[currcon
].var
.xres_virtual
+ var
->xoffset
)
2318 * fb_display
[currcon
].var
.bits_per_pixel
/ 8;
2319 fbhw
->set_screen_base (par
->screen_base
);
2324 /* ------------ Interfaces to hardware functions ------------ */
2328 static struct fb_hwswitch tt_switch
= {
2329 tt_detect
, tt_encode_fix
, tt_decode_var
, tt_encode_var
,
2330 tt_get_par
, tt_set_par
, tt_getcolreg
, tt_setcolreg
,
2331 set_screen_base
, NULL
, pan_display
2336 static struct fb_hwswitch falcon_switch
= {
2337 falcon_detect
, falcon_encode_fix
, falcon_decode_var
, falcon_encode_var
,
2338 falcon_get_par
, falcon_set_par
, falcon_getcolreg
,
2339 falcon_setcolreg
, set_screen_base
, falcon_blank
, falcon_pan_display
2344 static struct fb_hwswitch st_switch
= {
2345 stste_detect
, stste_encode_fix
, stste_decode_var
, stste_encode_var
,
2346 stste_get_par
, stste_set_par
, stste_getcolreg
, stste_setcolreg
,
2347 stste_set_screen_base
, NULL
, pan_display
2352 static struct fb_hwswitch ext_switch
= {
2353 ext_detect
, ext_encode_fix
, ext_decode_var
, ext_encode_var
,
2354 ext_get_par
, ext_set_par
, ext_getcolreg
, ext_setcolreg
, NULL
, NULL
, NULL
2360 static void atafb_get_par( struct atafb_par
*par
)
2362 if (current_par_valid
) {
2370 static void atafb_set_par( struct atafb_par
*par
)
2374 current_par_valid
=1;
2379 /* =========================================================== */
2380 /* ============== Hardware Independent Functions ============= */
2381 /* =========================================================== */
2384 /* used for hardware scrolling */
2387 fb_update_var(int con
, struct fb_info
*info
)
2389 int off
=fb_display
[con
].var
.yoffset
*fb_display
[con
].var
.xres_virtual
*
2390 fb_display
[con
].var
.bits_per_pixel
>>3;
2392 current_par
.screen_base
=screen_base
+ off
;
2394 if (fbhw
->set_screen_base
)
2395 fbhw
->set_screen_base(current_par
.screen_base
);
2400 do_fb_set_var(struct fb_var_screeninfo
*var
, int isactive
)
2403 struct atafb_par par
;
2404 if ((err
=fbhw
->decode_var(var
, &par
)))
2406 activate
=var
->activate
;
2407 if (((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) && isactive
)
2408 atafb_set_par(&par
);
2409 fbhw
->encode_var(var
, &par
);
2410 var
->activate
=activate
;
2414 /* Functions for handling colormap */
2417 do_install_cmap(int con
, struct fb_info
*info
)
2421 if (fb_display
[con
].cmap
.len
)
2422 fb_set_cmap(&fb_display
[con
].cmap
, 1, fbhw
->setcolreg
, info
);
2424 fb_set_cmap(fb_default_cmap(1<<fb_display
[con
].var
.bits_per_pixel
),
2425 1, fbhw
->setcolreg
, info
);
2430 * Open/Release the frame buffer device
2433 static int atafb_open(struct fb_info
*info
, int user
)
2436 * Nothing, only a usage count for the moment
2443 static int atafb_release(struct fb_info
*info
, int user
)
2451 atafb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
2453 struct atafb_par par
;
2455 atafb_get_par(&par
);
2457 fbhw
->decode_var(&fb_display
[con
].var
,&par
);
2458 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
2459 return fbhw
->encode_fix(fix
, &par
);
2463 atafb_get_var(struct fb_var_screeninfo
*var
, int con
, struct fb_info
*info
)
2465 struct atafb_par par
;
2467 atafb_get_par(&par
);
2468 fbhw
->encode_var(var
, &par
);
2471 *var
=fb_display
[con
].var
;
2476 atafb_set_disp(int con
, struct fb_info
*info
)
2478 struct fb_fix_screeninfo fix
;
2479 struct fb_var_screeninfo var
;
2480 struct display
*display
;
2483 display
= &fb_display
[con
];
2485 display
= &disp
; /* used during initialization */
2487 atafb_get_fix(&fix
, con
, info
);
2488 atafb_get_var(&var
, con
, info
);
2491 display
->screen_base
= fix
.smem_start
;
2492 display
->visual
= fix
.visual
;
2493 display
->type
= fix
.type
;
2494 display
->type_aux
= fix
.type_aux
;
2495 display
->ypanstep
= fix
.ypanstep
;
2496 display
->ywrapstep
= fix
.ywrapstep
;
2497 display
->line_length
= fix
.line_length
;
2498 if (fix
.visual
!= FB_VISUAL_PSEUDOCOLOR
&&
2499 fix
.visual
!= FB_VISUAL_DIRECTCOLOR
)
2500 display
->can_soft_blank
= 0;
2502 display
->can_soft_blank
= 1;
2504 (fix
.visual
== FB_VISUAL_MONO01
? !inverse
: inverse
);
2506 case FB_TYPE_INTERLEAVED_PLANES
:
2507 switch (var
.bits_per_pixel
) {
2508 #ifdef FBCON_HAS_IPLAN2P2
2510 display
->dispsw
= &fbcon_iplan2p2
;
2513 #ifdef FBCON_HAS_IPLAN2P4
2515 display
->dispsw
= &fbcon_iplan2p4
;
2518 #ifdef FBCON_HAS_IPLAN2P8
2520 display
->dispsw
= &fbcon_iplan2p8
;
2525 case FB_TYPE_PACKED_PIXELS
:
2526 switch (var
.bits_per_pixel
) {
2527 #ifdef FBCON_HAS_MFB
2529 display
->dispsw
= &fbcon_mfb
;
2532 #ifdef FBCON_HAS_CFB8
2534 display
->dispsw
= &fbcon_cfb8
;
2537 #ifdef FBCON_HAS_CFB16
2539 display
->dispsw
= &fbcon_cfb16
;
2540 display
->dispsw_data
= fbcon_cfb16_cmap
;
2549 atafb_set_var(struct fb_var_screeninfo
*var
, int con
, struct fb_info
*info
)
2551 int err
,oldxres
,oldyres
,oldbpp
,oldxres_virtual
,
2552 oldyres_virtual
,oldyoffset
;
2553 if ((err
=do_fb_set_var(var
, con
==currcon
)))
2555 if ((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) {
2556 oldxres
=fb_display
[con
].var
.xres
;
2557 oldyres
=fb_display
[con
].var
.yres
;
2558 oldxres_virtual
=fb_display
[con
].var
.xres_virtual
;
2559 oldyres_virtual
=fb_display
[con
].var
.yres_virtual
;
2560 oldbpp
=fb_display
[con
].var
.bits_per_pixel
;
2561 oldyoffset
=fb_display
[con
].var
.yoffset
;
2562 fb_display
[con
].var
=*var
;
2563 if (oldxres
!= var
->xres
|| oldyres
!= var
->yres
2564 || oldxres_virtual
!= var
->xres_virtual
2565 || oldyres_virtual
!= var
->yres_virtual
2566 || oldbpp
!= var
->bits_per_pixel
2567 || oldyoffset
!= var
->yoffset
) {
2568 atafb_set_disp(con
, info
);
2569 (*fb_info
.changevar
)(con
);
2570 fb_alloc_cmap(&fb_display
[con
].cmap
, 0, 0);
2571 do_install_cmap(con
, info
);
2581 atafb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
, struct fb_info
*info
)
2583 if (con
== currcon
) /* current console ? */
2584 return fb_get_cmap(cmap
, kspc
, fbhw
->getcolreg
, info
);
2586 if (fb_display
[con
].cmap
.len
) /* non default colormap ? */
2587 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
2589 fb_copy_cmap(fb_default_cmap(1<<fb_display
[con
].var
.bits_per_pixel
),
2590 cmap
, kspc
? 0 : 2);
2595 atafb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
, struct fb_info
*info
)
2598 if (! fb_display
[con
].cmap
.len
) { /* no colormap allocated ? */
2599 if ((err
= fb_alloc_cmap(&fb_display
[con
].cmap
,
2600 1 << fb_display
[con
].var
.bits_per_pixel
,
2604 if (con
== currcon
) /* current console ? */
2605 return fb_set_cmap(cmap
, kspc
, fbhw
->setcolreg
, info
);
2607 fb_copy_cmap(cmap
, &fb_display
[con
].cmap
, kspc
? 0 : 1);
2612 atafb_pan_display(struct fb_var_screeninfo
*var
, int con
, struct fb_info
*info
)
2614 int xoffset
= var
->xoffset
;
2615 int yoffset
= var
->yoffset
;
2618 if ( xoffset
< 0 || xoffset
+ fb_display
[con
].var
.xres
> fb_display
[con
].var
.xres_virtual
2619 || yoffset
< 0 || yoffset
+ fb_display
[con
].var
.yres
> fb_display
[con
].var
.yres_virtual
)
2622 if (con
== currcon
) {
2623 if (fbhw
->pan_display
) {
2624 if ((err
= fbhw
->pan_display(var
, ¤t_par
)))
2630 fb_display
[con
].var
.xoffset
= var
->xoffset
;
2631 fb_display
[con
].var
.yoffset
= var
->yoffset
;
2636 atafb_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
,
2637 unsigned long arg
, int con
, struct fb_info
*info
)
2640 #ifdef FBCMD_GET_CURRENTPAR
2641 case FBCMD_GET_CURRENTPAR
:
2642 if (copy_to_user((void *)arg
, (void *)¤t_par
,
2643 sizeof(struct atafb_par
)))
2647 #ifdef FBCMD_SET_CURRENTPAR
2648 case FBCMD_SET_CURRENTPAR
:
2649 if (copy_from_user((void *)¤t_par
, (void *)arg
,
2650 sizeof(struct atafb_par
)))
2652 atafb_set_par(¤t_par
);
2659 static struct fb_ops atafb_ops
= {
2660 atafb_open
, atafb_release
, atafb_get_fix
, atafb_get_var
,
2661 atafb_set_var
, atafb_get_cmap
, atafb_set_cmap
,
2662 atafb_pan_display
, atafb_ioctl
2666 check_default_par( int detected_mode
)
2668 char default_name
[10];
2670 struct fb_var_screeninfo var
;
2671 unsigned long min_mem
;
2673 /* First try the user supplied mode */
2675 var
=atafb_predefined
[default_par
-1];
2676 var
.activate
= FB_ACTIVATE_TEST
;
2677 if (do_fb_set_var(&var
,1))
2678 default_par
=0; /* failed */
2680 /* Next is the autodetected one */
2681 if (! default_par
) {
2682 var
=atafb_predefined
[detected_mode
-1]; /* autodetect */
2683 var
.activate
= FB_ACTIVATE_TEST
;
2684 if (!do_fb_set_var(&var
,1))
2685 default_par
=detected_mode
;
2687 /* If that also failed, try some default modes... */
2688 if (! default_par
) {
2689 /* try default1, default2... */
2690 for (i
=1 ; i
< 10 ; i
++) {
2691 sprintf(default_name
,"default%d",i
);
2692 default_par
=get_video_mode(default_name
);
2694 panic("can't set default video mode");
2695 var
=atafb_predefined
[default_par
-1];
2696 var
.activate
= FB_ACTIVATE_TEST
;
2697 if (! do_fb_set_var(&var
,1))
2701 min_mem
=var
.xres_virtual
* var
.yres_virtual
* var
.bits_per_pixel
/8;
2702 if (default_mem_req
< min_mem
)
2703 default_mem_req
=min_mem
;
2707 atafb_switch(int con
, struct fb_info
*info
)
2709 /* Do we have to save the colormap ? */
2710 if (fb_display
[currcon
].cmap
.len
)
2711 fb_get_cmap(&fb_display
[currcon
].cmap
, 1, fbhw
->getcolreg
,
2713 do_fb_set_var(&fb_display
[con
].var
,1);
2715 /* Install new colormap */
2716 do_install_cmap(con
, info
);
2720 /* (un)blank/poweroff
2728 atafb_blank(int blank
, struct fb_info
*info
)
2730 unsigned short black
[16];
2731 struct fb_cmap cmap
;
2732 if (fbhw
->blank
&& !fbhw
->blank(blank
))
2735 memset(black
, 0, 16*sizeof(unsigned short));
2742 fb_set_cmap(&cmap
, 1, fbhw
->setcolreg
, info
);
2745 do_install_cmap(currcon
, info
);
2748 __initfunc(void atafb_init(void))
2752 unsigned long mem_req
;
2759 if (external_addr
) {
2765 if (ATARIHW_PRESENT(TT_SHIFTER
)) {
2771 if (ATARIHW_PRESENT(VIDEL_SHIFTER
)) {
2772 fbhw
= &falcon_switch
;
2773 request_irq(IRQ_AUTO_4
, falcon_vbl_switcher
, IRQ_TYPE_PRIO
,
2774 "framebuffer/modeswitch", falcon_vbl_switcher
);
2779 if (ATARIHW_PRESENT(STND_SHIFTER
) ||
2780 ATARIHW_PRESENT(EXTD_SHIFTER
)) {
2785 printk("Cannot determine video hardware; defaulting to ST(e)\n");
2786 #else /* ATAFB_STE */
2787 /* no default driver included */
2788 /* Nobody will ever see this message :-) */
2789 panic("Cannot initialize video hardware");
2793 /* Multisync monitor capabilities */
2794 /* Atari-TOS defaults if no boot option present */
2795 if (fb_info
.monspecs
.hfmin
== 0) {
2796 fb_info
.monspecs
.hfmin
= 31000;
2797 fb_info
.monspecs
.hfmax
= 32000;
2798 fb_info
.monspecs
.vfmin
= 58;
2799 fb_info
.monspecs
.vfmax
= 62;
2802 detected_mode
= fbhw
->detect();
2803 check_default_par(detected_mode
);
2805 if (!external_addr
) {
2806 #endif /* ATAFB_EXT */
2807 mem_req
= default_mem_req
+ ovsc_offset
+
2809 mem_req
= ((mem_req
+ PAGE_SIZE
- 1) & PAGE_MASK
) + PAGE_SIZE
;
2810 screen_base
= (unsigned long)atari_stram_alloc(mem_req
, NULL
,
2813 panic("Cannot allocate screen memory");
2814 memset((char *) screen_base
, 0, mem_req
);
2815 pad
= ((screen_base
+ PAGE_SIZE
-1) & PAGE_MASK
) - screen_base
;
2817 real_screen_base
=screen_base
+ovsc_offset
;
2818 screen_len
= (mem_req
- pad
- ovsc_offset
) & PAGE_MASK
;
2820 if (CPU_IS_040_OR_060
) {
2821 /* On a '040+, the cache mode of video RAM must be set to
2822 * write-through also for internal video hardware! */
2823 cache_push( virt_to_phys(screen_base
), screen_len
);
2824 kernel_set_cachemode( screen_base
, screen_len
,
2825 IOMAP_WRITETHROUGH
);
2830 /* Map the video memory (physical address given) to somewhere
2831 * in the kernel address space.
2833 external_addr
= ioremap_writethrough(external_addr
, external_len
);
2834 if (external_vgaiobase
)
2835 external_vgaiobase
= ioremap(external_vgaiobase
, 0x10000 );
2837 real_screen_base
= external_addr
;
2838 screen_len
= external_len
& PAGE_MASK
;
2839 memset ((char *) screen_base
, 0, external_len
);
2841 #endif /* ATAFB_EXT */
2843 strcpy(fb_info
.modename
, "Atari Builtin ");
2844 fb_info
.changevar
= NULL
;
2846 fb_info
.fbops
= &atafb_ops
;
2847 fb_info
.disp
= &disp
;
2848 fb_info
.switch_con
= &atafb_switch
;
2849 fb_info
.updatevar
= &fb_update_var
;
2850 fb_info
.blank
= &atafb_blank
;
2851 fb_info
.flags
= FBINFO_FLAG_DEFAULT
;
2852 do_fb_set_var(&atafb_predefined
[default_par
-1], 1);
2853 strcat(fb_info
.modename
, fb_var_names
[default_par
-1][0]);
2855 atafb_get_var(&disp
.var
, -1, &fb_info
);
2856 atafb_set_disp(-1, &fb_info
);
2857 do_install_cmap(0, &fb_info
);
2859 if (register_framebuffer(&fb_info
) < 0)
2862 printk("Determined %dx%d, depth %d\n",
2863 disp
.var
.xres
, disp
.var
.yres
, disp
.var
.bits_per_pixel
);
2864 if ((disp
.var
.xres
!= disp
.var
.xres_virtual
) ||
2865 (disp
.var
.yres
!= disp
.var
.yres_virtual
))
2866 printk(" virtual %dx%d\n",
2867 disp
.var
.xres_virtual
, disp
.var
.yres_virtual
);
2868 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2869 GET_FB_IDX(fb_info
.node
), fb_info
.modename
, screen_len
>>10);
2871 /* TODO: This driver cannot be unloaded yet */
2875 /* a strtok which returns empty strings, too */
2877 static char * strtoke(char * s
,const char * ct
)
2879 char *sbegin
, *send
;
2880 static char *ssave
= NULL
;
2882 sbegin
= s
? s
: ssave
;
2886 if (*sbegin
== '\0') {
2890 send
= strpbrk(sbegin
, ct
);
2891 if (send
&& *send
!= '\0')
2897 __initfunc(void atafb_setup( char *options
, int *ints
))
2901 char ext_str
[80], int_str
[100];
2909 fb_info
.fontname
[0] = '\0';
2911 if (!options
|| !*options
)
2914 for(this_opt
=strtok(options
,","); this_opt
; this_opt
=strtok(NULL
,",")) {
2915 if (!*this_opt
) continue;
2916 if ((temp
=get_video_mode(this_opt
)))
2918 else if (! strcmp(this_opt
, "inverse"))
2920 else if (!strncmp(this_opt
, "font:", 5))
2921 strcpy(fb_info
.fontname
, this_opt
+5);
2922 else if (! strncmp(this_opt
, "hwscroll_",9)) {
2923 hwscroll
=simple_strtoul(this_opt
+9, NULL
, 10);
2930 else if (!strcmp(this_opt
,"mv300")) {
2931 external_bitspercol
= 8;
2932 external_card_type
= IS_MV300
;
2934 else if (!strncmp(this_opt
,"external:",9))
2935 strcpy(ext_str
, this_opt
+9);
2937 else if (!strncmp(this_opt
,"internal:",9))
2938 strcpy(int_str
, this_opt
+9);
2940 else if (!strncmp(this_opt
, "eclock:", 7)) {
2941 fext
.f
= simple_strtoul(this_opt
+7, NULL
, 10);
2942 /* external pixelclock in kHz --> ps */
2943 fext
.t
= 1000000000/fext
.f
;
2946 else if (!strncmp(this_opt
, "monitorcap:", 11))
2947 strcpy(mcap_spec
, this_opt
+11);
2949 else if (!strcmp(this_opt
, "keep"))
2951 else if (!strncmp(this_opt
, "R", 1))
2952 strcpy(user_mode
, this_opt
+1);
2956 /* Format to config extended internal video hardware like OverScan:
2957 "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2959 <xres>: x-resolution
2960 <yres>: y-resolution
2961 The following are only needed if you have an overscan which
2962 needs a black border:
2963 <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2964 <yres_max>: max. number of lines your OverScan hardware would allow
2965 <offset>: Offset from physical beginning to visible beginning
2971 if (!(p
= strtoke(int_str
, ";")) ||!*p
) goto int_invalid
;
2972 xres
= simple_strtoul(p
, NULL
, 10);
2973 if (!(p
= strtoke(NULL
, ";")) || !*p
) goto int_invalid
;
2975 tt_yres
=st_yres
=simple_strtoul(p
, NULL
, 10);
2976 if ((p
=strtoke(NULL
, ";")) && *p
) {
2977 sttt_xres_virtual
=simple_strtoul(p
, NULL
, 10);
2979 if ((p
=strtoke(NULL
, ";")) && *p
) {
2980 sttt_yres_virtual
=simple_strtoul(p
, NULL
, 0);
2982 if ((p
=strtoke(NULL
, ";")) && *p
) {
2983 ovsc_offset
=simple_strtoul(p
, NULL
, 0);
2986 if (ovsc_offset
|| (sttt_yres_virtual
!= st_yres
))
2994 int xres
, xres_virtual
, yres
, depth
, planes
;
2995 unsigned long addr
, len
;
2998 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
3000 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
3001 * [;<xres-virtual>]]]]]
3004 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
3006 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
3008 if (!(p
= strtoke(ext_str
, ";")) ||!*p
) goto ext_invalid
;
3009 xres_virtual
= xres
= simple_strtoul(p
, NULL
, 10);
3010 if (xres
<= 0) goto ext_invalid
;
3012 if (!(p
= strtoke(NULL
, ";")) ||!*p
) goto ext_invalid
;
3013 yres
= simple_strtoul(p
, NULL
, 10);
3014 if (yres
<= 0) goto ext_invalid
;
3016 if (!(p
= strtoke(NULL
, ";")) ||!*p
) goto ext_invalid
;
3017 depth
= simple_strtoul(p
, NULL
, 10);
3018 if (depth
!= 1 && depth
!= 2 && depth
!= 4 && depth
!= 8 &&
3019 depth
!= 16 && depth
!= 24) goto ext_invalid
;
3021 if (!(p
= strtoke(NULL
, ";")) ||!*p
) goto ext_invalid
;
3023 planes
= FB_TYPE_INTERLEAVED_PLANES
;
3025 planes
= FB_TYPE_PACKED_PIXELS
;
3027 planes
= FB_TYPE_PLANES
;
3029 planes
= -1; /* true color */
3034 if (!(p
= strtoke(NULL
, ";")) ||!*p
) goto ext_invalid
;
3035 addr
= simple_strtoul(p
, NULL
, 0);
3037 if (!(p
= strtoke(NULL
, ";")) ||!*p
)
3038 len
= xres
*yres
*depth
/8;
3040 len
= simple_strtoul(p
, NULL
, 0);
3042 if ((p
= strtoke(NULL
, ";")) && *p
) {
3043 external_vgaiobase
=simple_strtoul(p
, NULL
, 0);
3046 if ((p
= strtoke(NULL
, ";")) && *p
) {
3047 external_bitspercol
= simple_strtoul(p
, NULL
, 0);
3048 if (external_bitspercol
> 8)
3049 external_bitspercol
= 8;
3050 else if (external_bitspercol
< 1)
3051 external_bitspercol
= 1;
3054 if ((p
= strtoke(NULL
, ";")) && *p
) {
3055 if (!strcmp(p
, "vga"))
3056 external_card_type
= IS_VGA
;
3057 if (!strcmp(p
, "mv300"))
3058 external_card_type
= IS_MV300
;
3061 if ((p
= strtoke(NULL
, ";")) && *p
) {
3062 xres_virtual
= simple_strtoul(p
, NULL
, 10);
3063 if (xres_virtual
< xres
)
3064 xres_virtual
= xres
;
3065 if (xres_virtual
*yres
*depth
/8 > len
)
3066 len
=xres_virtual
*yres
*depth
/8;
3069 external_xres
= xres
;
3070 external_xres_virtual
= xres_virtual
;
3071 external_yres
= yres
;
3072 external_depth
= depth
;
3073 external_pmode
= planes
;
3074 external_addr
= addr
;
3077 if (external_card_type
== IS_MV300
)
3078 switch (external_depth
) {
3080 MV300_reg
= MV300_reg_1bit
;
3083 MV300_reg
= MV300_reg_4bit
;
3086 MV300_reg
= MV300_reg_8bit
;
3093 #endif /* ATAFB_EXT */
3098 int vmin
, vmax
, hmin
, hmax
;
3100 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
3101 * <V*> vertical freq. in Hz
3102 * <H*> horizontal freq. in kHz
3104 if (!(p
= strtoke(mcap_spec
, ";")) || !*p
) goto cap_invalid
;
3105 vmin
= simple_strtoul(p
, NULL
, 10);
3106 if (vmin
<= 0) goto cap_invalid
;
3107 if (!(p
= strtoke(NULL
, ";")) || !*p
) goto cap_invalid
;
3108 vmax
= simple_strtoul(p
, NULL
, 10);
3109 if (vmax
<= 0 || vmax
<= vmin
) goto cap_invalid
;
3110 if (!(p
= strtoke(NULL
, ";")) || !*p
) goto cap_invalid
;
3111 hmin
= 1000 * simple_strtoul(p
, NULL
, 10);
3112 if (hmin
<= 0) goto cap_invalid
;
3113 if (!(p
= strtoke(NULL
, "")) || !*p
) goto cap_invalid
;
3114 hmax
= 1000 * simple_strtoul(p
, NULL
, 10);
3115 if (hmax
<= 0 || hmax
<= hmin
) goto cap_invalid
;
3117 fb_info
.monspecs
.vfmin
= vmin
;
3118 fb_info
.monspecs
.vfmax
= vmax
;
3119 fb_info
.monspecs
.hfmin
= hmin
;
3120 fb_info
.monspecs
.hfmax
= hmax
;
3127 /* Format of user defined video mode is: <xres>;<yres>;<depth>
3130 int xres
, yres
, depth
, temp
;
3132 if (!(p
= strtoke(user_mode
, ";")) || !*p
) goto user_invalid
;
3133 xres
= simple_strtoul(p
, NULL
, 10);
3134 if (!(p
= strtoke(NULL
, ";")) || !*p
) goto user_invalid
;
3135 yres
= simple_strtoul(p
, NULL
, 10);
3136 if (!(p
= strtoke(NULL
, "")) || !*p
) goto user_invalid
;
3137 depth
= simple_strtoul(p
, NULL
, 10);
3138 if ((temp
=get_video_mode("user0"))) {
3140 atafb_predefined
[default_par
-1].xres
= xres
;
3141 atafb_predefined
[default_par
-1].yres
= yres
;
3142 atafb_predefined
[default_par
-1].bits_per_pixel
= depth
;
3151 int init_module(void)
3157 void cleanup_module(void)
3159 /* Not reached because the usecount will never
3160 be decremented to zero */
3161 unregister_framebuffer(&fb_info
);
3162 /* atari_stram_free( screen_base ); */
3163 /* TODO: further clean up ... */