1 /*
2 * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
3 *
4 * Copyright (C) 1994 Martin Schaller & Roman Hodek
5 *
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
8 * for more details.
9 *
10 * History:
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
31 * supported.
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
38 *
39 * To do:
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.
42 *
43 */
44
45 #define ATAFB_TT
46 #define ATAFB_STE
47 #define ATAFB_EXT
48 #define ATAFB_FALCON
49
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>
55 #include <linux/mm.h>
56 #include <linux/tty.h>
57 #include <linux/slab.h>
58 #include <linux/delay.h>
59 #include <linux/init.h>
60
61 #include <asm/setup.h>
62 #include <asm/uaccess.h>
63 #include <asm/pgtable.h>
64 #include <asm/irq.h>
65 #include <asm/io.h>
66
67 #include <asm/atarihw.h>
68 #include <asm/atariints.h>
69 #include <asm/atari_stram.h>
70
71 #include <linux/fb.h>
72 #include <asm/atarikb.h>
73
74 #include <video/fbcon.h>
75 #include <video/fbcon-cfb8.h>
76 #include <video/fbcon-cfb16.h>
77 #include <video/fbcon-iplan2p2.h>
78 #include <video/fbcon-iplan2p4.h>
79 #include <video/fbcon-iplan2p8.h>
80 #include <video/fbcon-mfb.h>
81
82
83 #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
84 #define SWITCH_SND6 0x40
85 #define SWITCH_SND7 0x80
86 #define SWITCH_NONE 0x00
87
88
89 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
90
91
92 static int default_par=0; /* default resolution (0=none) */
93
94 static unsigned long default_mem_req=0;
95
96 static int hwscroll=-1;
97
98 static int use_hwscroll = 1;
99
100 static int sttt_xres=640,st_yres=400,tt_yres=480;
101 static int sttt_xres_virtual=640,sttt_yres_virtual=400;
102 static int ovsc_offset=0, ovsc_addlen=0;
103
104 static struct atafb_par {
105 void *screen_base;
106 int yres_virtual;
107 #if defined ATAFB_TT || defined ATAFB_STE
108 union {
109 struct {
110 int mode;
111 int sync;
112 } tt, st;
113 #endif
114 #ifdef ATAFB_FALCON
115 struct falcon_hw {
116 /* Here are fields for storing a video mode, as direct
117 * parameters for the hardware.
118 */
119 short sync;
120 short line_width;
121 short line_offset;
122 short st_shift;
123 short f_shift;
124 short vid_control;
125 short vid_mode;
126 short xoffset;
127 short hht, hbb, hbe, hdb, hde, hss;
128 short vft, vbb, vbe, vdb, vde, vss;
129 /* auxiliary information */
130 short mono;
131 short ste_mode;
132 short bpp;
133 } falcon;
134 #endif
135 /* Nothing needed for external mode */
136 } hw;
137 } current_par;
138
139 /* Don't calculate an own resolution, and thus don't change the one found when
140 * booting (currently used for the Falcon to keep settings for internal video
141 * hardware extensions (e.g. ScreenBlaster) */
142 static int DontCalcRes = 0;
143
144 #ifdef ATAFB_FALCON
145 #define HHT hw.falcon.hht
146 #define HBB hw.falcon.hbb
147 #define HBE hw.falcon.hbe
148 #define HDB hw.falcon.hdb
149 #define HDE hw.falcon.hde
150 #define HSS hw.falcon.hss
151 #define VFT hw.falcon.vft
152 #define VBB hw.falcon.vbb
153 #define VBE hw.falcon.vbe
154 #define VDB hw.falcon.vdb
155 #define VDE hw.falcon.vde
156 #define VSS hw.falcon.vss
157 #define VCO_CLOCK25 0x04
158 #define VCO_CSYPOS 0x10
159 #define VCO_VSYPOS 0x20
160 #define VCO_HSYPOS 0x40
161 #define VCO_SHORTOFFS 0x100
162 #define VMO_DOUBLE 0x01
163 #define VMO_INTER 0x02
164 #define VMO_PREMASK 0x0c
165 #endif
166
167 static struct fb_info fb_info;
168
169 static void *screen_base; /* base address of screen */
170 static void *real_screen_base; /* (only for Overscan) */
171
172 static int screen_len;
173
174 static int current_par_valid=0;
175
176 static int currcon=0;
177
178 static int mono_moni=0;
179
180 static struct display disp;
181
182
183 #ifdef ATAFB_EXT
184 /* external video handling */
185
186 static unsigned external_xres;
187 static unsigned external_xres_virtual;
188 static unsigned external_yres;
189 /* not needed - atafb will never support panning/hardwarescroll with external
190 * static unsigned external_yres_virtual;
191 */
192
193 static unsigned external_depth;
194 static int external_pmode;
195 static void *external_addr = 0;
196 static unsigned long external_len;
197 static unsigned long external_vgaiobase = 0;
198 static unsigned int external_bitspercol = 6;
199
200 /*
201 JOE <joe@amber.dinoco.de>:
202 added card type for external driver, is only needed for
203 colormap handling.
204 */
205
206 enum cardtype { IS_VGA, IS_MV300 };
207 static enum cardtype external_card_type = IS_VGA;
208
209 /*
210 The MV300 mixes the color registers. So we need an array of munged
211 indices in order to access the correct reg.
212 */
213 static int MV300_reg_1bit[2]={0,1};
214 static int MV300_reg_4bit[16]={
215 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
216 static int MV300_reg_8bit[256]={
217 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
218 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
219 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
220 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
221 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
222 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
223 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
224 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
225 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
226 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
227 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
228 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
229 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
230 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
231 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
232 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 };
233
234 static int *MV300_reg = MV300_reg_8bit;
235
236 /*
237 And on the MV300 it's difficult to read out the hardware palette. So we
238 just keep track of the set colors in our own array here, and use that!
239 */
240
241 static struct { unsigned char red,green,blue,pad; } ext_color[256];
242 #endif /* ATAFB_EXT */
243
244
245 static int inverse=0;
246
247 extern int fontheight_8x8;
248 extern int fontwidth_8x8;
249 extern unsigned char fontdata_8x8[];
250
251 extern int fontheight_8x16;
252 extern int fontwidth_8x16;
253 extern unsigned char fontdata_8x16[];
254
255 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
256 * TT, or Falcon.
257 *
258 * int (*detect)( void )
259 * This function should detect the current video mode settings and
260 * store them in atafb_predefined[0] for later reference by the
261 * user. Return the index+1 of an equivalent predefined mode or 0
262 * if there is no such.
263 *
264 * int (*encode_fix)( struct fb_fix_screeninfo *fix,
265 * struct atafb_par *par )
266 * This function should fill in the 'fix' structure based on the
267 * values in the 'par' structure.
268 *
269 * int (*decode_var)( struct fb_var_screeninfo *var,
270 * struct atafb_par *par )
271 * Get the video params out of 'var'. If a value doesn't fit, round
272 * it up, if it's too big, return EINVAL.
273 * Round up in the following order: bits_per_pixel, xres, yres,
274 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
275 * horizontal timing, vertical timing.
276 *
277 * int (*encode_var)( struct fb_var_screeninfo *var,
278 * struct atafb_par *par );
279 * Fill the 'var' structure based on the values in 'par' and maybe
280 * other values read out of the hardware.
281 *
282 * void (*get_par)( struct atafb_par *par )
283 * Fill the hardware's 'par' structure.
284 *
285 * void (*set_par)( struct atafb_par *par )
286 * Set the hardware according to 'par'.
287 *
288 * int (*setcolreg)( unsigned regno, unsigned red,
289 * unsigned green, unsigned blue,
290 * unsigned transp, struct fb_info *info )
291 * Set a single color register. The values supplied are already
292 * rounded down to the hardware's capabilities (according to the
293 * entries in the var structure). Return != 0 for invalid regno.
294 *
295 * int (*getcolreg)( unsigned regno, unsigned *red,
296 * unsigned *green, unsigned *blue,
297 * unsigned *transp, struct fb_info *info )
298 * Read a single color register and split it into
299 * colors/transparent. Return != 0 for invalid regno.
300 *
301 * void (*set_screen_base)(void *s_base)
302 * Set the base address of the displayed frame buffer. Only called
303 * if yres_virtual > yres or xres_virtual > xres.
304 *
305 * int (*blank)( int blank_mode )
306 * Blank the screen if blank_mode!=0, else unblank. If blank==NULL then
307 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
308 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
309 * doesn't support it. Implements VESA suspend and powerdown modes on
310 * hardware that supports disabling hsync/vsync:
311 * blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown.
312 */
313
314 static struct fb_hwswitch {
315 int (*detect)( void );
316 int (*encode_fix)( struct fb_fix_screeninfo *fix,
317 struct atafb_par *par );
318 int (*decode_var)( struct fb_var_screeninfo *var,
319 struct atafb_par *par );
320 int (*encode_var)( struct fb_var_screeninfo *var,
321 struct atafb_par *par );
322 void (*get_par)( struct atafb_par *par );
323 void (*set_par)( struct atafb_par *par );
324 int (*getcolreg)( unsigned regno, unsigned *red,
325 unsigned *green, unsigned *blue,
326 unsigned *transp, struct fb_info *info );
327 int (*setcolreg)( unsigned regno, unsigned red,
328 unsigned green, unsigned blue,
329 unsigned transp, struct fb_info *info );
330 void (*set_screen_base)(void *s_base);
331 int (*blank)( int blank_mode );
332 int (*pan_display)( struct fb_var_screeninfo *var,
333 struct atafb_par *par);
334 } *fbhw;
335
336 static char *autodetect_names[] = {"autodetect", NULL};
337 static char *stlow_names[] = {"stlow", NULL};
338 static char *stmid_names[] = {"stmid", "default5", NULL};
339 static char *sthigh_names[] = {"sthigh", "default4", NULL};
340 static char *ttlow_names[] = {"ttlow", NULL};
341 static char *ttmid_names[]= {"ttmid", "default1", NULL};
342 static char *tthigh_names[]= {"tthigh", "default2", NULL};
343 static char *vga2_names[] = {"vga2", NULL};
344 static char *vga4_names[] = {"vga4", NULL};
345 static char *vga16_names[] = {"vga16", "default3", NULL};
346 static char *vga256_names[] = {"vga256", NULL};
347 static char *falh2_names[] = {"falh2", NULL};
348 static char *falh16_names[] = {"falh16", NULL};
349
350 static char **fb_var_names[] = {
351 /* Writing the name arrays directly in this array (via "(char *[]){...}")
352 * crashes gcc 2.5.8 (sigsegv) if the inner array
353 * contains more than two items. I've also seen that all elements
354 * were identical to the last (my cross-gcc) :-(*/
355 autodetect_names,
356 stlow_names,
357 stmid_names,
358 sthigh_names,
359 ttlow_names,
360 ttmid_names,
361 tthigh_names,
362 vga2_names,
363 vga4_names,
364 vga16_names,
365 vga256_names,
366 falh2_names,
367 falh16_names,
368 NULL
369 /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
370 };
371
372 static struct fb_var_screeninfo atafb_predefined[] = {
373 /*
374 * yres_virtual==0 means use hw-scrolling if possible, else yres
375 */
376 { /* autodetect */
377 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
378 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
379 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
380 { /* st low */
381 320, 200, 320, 0, 0, 0, 4, 0,
382 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
383 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
384 { /* st mid */
385 640, 200, 640, 0, 0, 0, 2, 0,
386 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
387 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
388 { /* st high */
389 640, 400, 640, 0, 0, 0, 1, 0,
390 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
391 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
392 { /* tt low */
393 320, 480, 320, 0, 0, 0, 8, 0,
394 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
395 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
396 { /* tt mid */
397 640, 480, 640, 0, 0, 0, 4, 0,
398 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
399 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
400 { /* tt high */
401 1280, 960, 1280, 0, 0, 0, 1, 0,
402 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
403 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
404 { /* vga2 */
405 640, 480, 640, 0, 0, 0, 1, 0,
406 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
407 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
408 { /* vga4 */
409 640, 480, 640, 0, 0, 0, 2, 0,
410 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
411 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
412 { /* vga16 */
413 640, 480, 640, 0, 0, 0, 4, 0,
414 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
415 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
416 { /* vga256 */
417 640, 480, 640, 0, 0, 0, 8, 0,
418 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
419 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
420 { /* falh2 */
421 896, 608, 896, 0, 0, 0, 1, 0,
422 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
423 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
424 { /* falh16 */
425 896, 608, 896, 0, 0, 0, 4, 0,
426 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
427 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
428 };
429
430 static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined);
431
432
433 static int
get_video_mode(char * vname)434 get_video_mode(char *vname)
435 {
436 char ***name_list;
437 char **name;
438 int i;
439 name_list=fb_var_names;
440 for (i = 0 ; i < num_atafb_predefined ; i++) {
441 name=*(name_list++);
442 if (! name || ! *name)
443 break;
444 while (*name) {
445 if (! strcmp(vname, *name))
446 return i+1;
447 name++;
448 }
449 }
450 return 0;
451 }
452
453
454
455 /* ------------------- TT specific functions ---------------------- */
456
457 #ifdef ATAFB_TT
458
tt_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)459 static int tt_encode_fix( struct fb_fix_screeninfo *fix,
460 struct atafb_par *par )
461
462 {
463 int mode;
464
465 strcpy(fix->id,"Atari Builtin");
466 fix->smem_start = (unsigned long)real_screen_base;
467 fix->smem_len = screen_len;
468 fix->type=FB_TYPE_INTERLEAVED_PLANES;
469 fix->type_aux=2;
470 fix->visual=FB_VISUAL_PSEUDOCOLOR;
471 mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
472 if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
473 fix->type=FB_TYPE_PACKED_PIXELS;
474 fix->type_aux=0;
475 if (mode == TT_SHIFTER_TTHIGH)
476 fix->visual=FB_VISUAL_MONO01;
477 }
478 fix->xpanstep=0;
479 fix->ypanstep=1;
480 fix->ywrapstep=0;
481 fix->line_length = 0;
482 fix->accel = FB_ACCEL_ATARIBLITT;
483 return 0;
484 }
485
486
tt_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)487 static int tt_decode_var( struct fb_var_screeninfo *var,
488 struct atafb_par *par )
489 {
490 int xres=var->xres;
491 int yres=var->yres;
492 int bpp=var->bits_per_pixel;
493 int linelen;
494 int yres_virtual = var->yres_virtual;
495
496 if (mono_moni) {
497 if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
498 return -EINVAL;
499 par->hw.tt.mode=TT_SHIFTER_TTHIGH;
500 xres=sttt_xres*2;
501 yres=tt_yres*2;
502 bpp=1;
503 } else {
504 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
505 return -EINVAL;
506 if (bpp > 4) {
507 if (xres > sttt_xres/2 || yres > tt_yres)
508 return -EINVAL;
509 par->hw.tt.mode=TT_SHIFTER_TTLOW;
510 xres=sttt_xres/2;
511 yres=tt_yres;
512 bpp=8;
513 }
514 else if (bpp > 2) {
515 if (xres > sttt_xres || yres > tt_yres)
516 return -EINVAL;
517 if (xres > sttt_xres/2 || yres > st_yres/2) {
518 par->hw.tt.mode=TT_SHIFTER_TTMID;
519 xres=sttt_xres;
520 yres=tt_yres;
521 bpp=4;
522 }
523 else {
524 par->hw.tt.mode=TT_SHIFTER_STLOW;
525 xres=sttt_xres/2;
526 yres=st_yres/2;
527 bpp=4;
528 }
529 }
530 else if (bpp > 1) {
531 if (xres > sttt_xres || yres > st_yres/2)
532 return -EINVAL;
533 par->hw.tt.mode=TT_SHIFTER_STMID;
534 xres=sttt_xres;
535 yres=st_yres/2;
536 bpp=2;
537 }
538 else if (var->xres > sttt_xres || var->yres > st_yres) {
539 return -EINVAL;
540 }
541 else {
542 par->hw.tt.mode=TT_SHIFTER_STHIGH;
543 xres=sttt_xres;
544 yres=st_yres;
545 bpp=1;
546 }
547 }
548 if (yres_virtual <= 0)
549 yres_virtual = 0;
550 else if (yres_virtual < yres)
551 yres_virtual = yres;
552 if (var->sync & FB_SYNC_EXT)
553 par->hw.tt.sync=0;
554 else
555 par->hw.tt.sync=1;
556 linelen=xres*bpp/8;
557 if (yres_virtual * linelen > screen_len && screen_len)
558 return -EINVAL;
559 if (yres * linelen > screen_len && screen_len)
560 return -EINVAL;
561 if (var->yoffset + yres > yres_virtual && yres_virtual)
562 return -EINVAL;
563 par->yres_virtual = yres_virtual;
564 par->screen_base = screen_base + var->yoffset * linelen;
565 return 0;
566 }
567
tt_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)568 static int tt_encode_var( struct fb_var_screeninfo *var,
569 struct atafb_par *par )
570 {
571 int linelen;
572 memset(var, 0, sizeof(struct fb_var_screeninfo));
573 var->red.offset=0;
574 var->red.length=4;
575 var->red.msb_right=0;
576 var->grayscale=0;
577
578 var->pixclock=31041;
579 var->left_margin=120; /* these may be incorrect */
580 var->right_margin=100;
581 var->upper_margin=8;
582 var->lower_margin=16;
583 var->hsync_len=140;
584 var->vsync_len=30;
585
586 var->height=-1;
587 var->width=-1;
588
589 if (par->hw.tt.sync & 1)
590 var->sync=0;
591 else
592 var->sync=FB_SYNC_EXT;
593
594 switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
595 case TT_SHIFTER_STLOW:
596 var->xres=sttt_xres/2;
597 var->xres_virtual=sttt_xres_virtual/2;
598 var->yres=st_yres/2;
599 var->bits_per_pixel=4;
600 break;
601 case TT_SHIFTER_STMID:
602 var->xres=sttt_xres;
603 var->xres_virtual=sttt_xres_virtual;
604 var->yres=st_yres/2;
605 var->bits_per_pixel=2;
606 break;
607 case TT_SHIFTER_STHIGH:
608 var->xres=sttt_xres;
609 var->xres_virtual=sttt_xres_virtual;
610 var->yres=st_yres;
611 var->bits_per_pixel=1;
612 break;
613 case TT_SHIFTER_TTLOW:
614 var->xres=sttt_xres/2;
615 var->xres_virtual=sttt_xres_virtual/2;
616 var->yres=tt_yres;
617 var->bits_per_pixel=8;
618 break;
619 case TT_SHIFTER_TTMID:
620 var->xres=sttt_xres;
621 var->xres_virtual=sttt_xres_virtual;
622 var->yres=tt_yres;
623 var->bits_per_pixel=4;
624 break;
625 case TT_SHIFTER_TTHIGH:
626 var->red.length=0;
627 var->xres=sttt_xres*2;
628 var->xres_virtual=sttt_xres_virtual*2;
629 var->yres=tt_yres*2;
630 var->bits_per_pixel=1;
631 break;
632 }
633 var->blue=var->green=var->red;
634 var->transp.offset=0;
635 var->transp.length=0;
636 var->transp.msb_right=0;
637 linelen=var->xres_virtual * var->bits_per_pixel / 8;
638 if (! use_hwscroll)
639 var->yres_virtual=var->yres;
640 else if (screen_len) {
641 if (par->yres_virtual)
642 var->yres_virtual = par->yres_virtual;
643 else
644 /* yres_virtual==0 means use maximum */
645 var->yres_virtual = screen_len / linelen;
646 } else {
647 if (hwscroll < 0)
648 var->yres_virtual = 2 * var->yres;
649 else
650 var->yres_virtual=var->yres+hwscroll * 16;
651 }
652 var->xoffset=0;
653 if (screen_base)
654 var->yoffset=(par->screen_base - screen_base)/linelen;
655 else
656 var->yoffset=0;
657 var->nonstd=0;
658 var->activate=0;
659 var->vmode=FB_VMODE_NONINTERLACED;
660 return 0;
661 }
662
663
tt_get_par(struct atafb_par * par)664 static void tt_get_par( struct atafb_par *par )
665 {
666 unsigned long addr;
667 par->hw.tt.mode=shifter_tt.tt_shiftmode;
668 par->hw.tt.sync=shifter.syncmode;
669 addr = ((shifter.bas_hi & 0xff) << 16) |
670 ((shifter.bas_md & 0xff) << 8) |
671 ((shifter.bas_lo & 0xff));
672 par->screen_base = phys_to_virt(addr);
673 }
674
tt_set_par(struct atafb_par * par)675 static void tt_set_par( struct atafb_par *par )
676 {
677 shifter_tt.tt_shiftmode=par->hw.tt.mode;
678 shifter.syncmode=par->hw.tt.sync;
679 /* only set screen_base if really necessary */
680 if (current_par.screen_base != par->screen_base)
681 fbhw->set_screen_base(par->screen_base);
682 }
683
684
tt_getcolreg(unsigned regno,unsigned * red,unsigned * green,unsigned * blue,unsigned * transp,struct fb_info * info)685 static int tt_getcolreg(unsigned regno, unsigned *red,
686 unsigned *green, unsigned *blue,
687 unsigned *transp, struct fb_info *info)
688 {
689 int t, col;
690
691 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
692 regno += 254;
693 if (regno > 255)
694 return 1;
695 t = tt_palette[regno];
696 col = t & 15;
697 col |= col << 4;
698 col |= col << 8;
699 *blue = col;
700 col = (t >> 4) & 15;
701 col |= col << 4;
702 col |= col << 8;
703 *green = col;
704 col = (t >> 8) & 15;
705 col |= col << 4;
706 col |= col << 8;
707 *red = col;
708 *transp = 0;
709 return 0;
710 }
711
712
tt_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)713 static int tt_setcolreg(unsigned regno, unsigned red,
714 unsigned green, unsigned blue,
715 unsigned transp, struct fb_info *info)
716 {
717 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
718 regno += 254;
719 if (regno > 255)
720 return 1;
721 tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
722 (blue >> 12));
723 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
724 TT_SHIFTER_STHIGH && regno == 254)
725 tt_palette[0] = 0;
726 return 0;
727 }
728
729
tt_detect(void)730 static int tt_detect( void )
731
732 { struct atafb_par par;
733
734 /* Determine the connected monitor: The DMA sound must be
735 * disabled before reading the MFP GPIP, because the Sound
736 * Done Signal and the Monochrome Detect are XORed together!
737 *
738 * Even on a TT, we should look if there is a DMA sound. It was
739 * announced that the Eagle is TT compatible, but only the PCM is
740 * missing...
741 */
742 if (ATARIHW_PRESENT(PCM_8BIT)) {
743 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
744 udelay(20); /* wait a while for things to settle down */
745 }
746 mono_moni = (mfp.par_dt_reg & 0x80) == 0;
747
748 tt_get_par(&par);
749 tt_encode_var(&atafb_predefined[0], &par);
750
751 return 1;
752 }
753
754 #endif /* ATAFB_TT */
755
756 /* ------------------- Falcon specific functions ---------------------- */
757
758 #ifdef ATAFB_FALCON
759
760 static int mon_type; /* Falcon connected monitor */
761 static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
762 #define F_MON_SM 0
763 #define F_MON_SC 1
764 #define F_MON_VGA 2
765 #define F_MON_TV 3
766
767 static struct pixel_clock {
768 unsigned long f; /* f/[Hz] */
769 unsigned long t; /* t/[ps] (=1/f) */
770 int right, hsync, left; /* standard timing in clock cycles, not pixel */
771 /* hsync initialized in falcon_detect() */
772 int sync_mask; /* or-mask for hw.falcon.sync to set this clock */
773 int control_mask; /* ditto, for hw.falcon.vid_control */
774 }
775 f25 = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25},
776 f32 = {32000000, 31250, 18, 0, 42, 0x0, 0},
777 fext = { 0, 0, 18, 0, 42, 0x1, 0};
778
779 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
780 static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
781
782 /* Default hsync timing [mon_type] in picoseconds */
783 static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
784
785 #ifdef FBCON_HAS_CFB16
786 static u16 fbcon_cfb16_cmap[16];
787 #endif
788
hxx_prescale(struct falcon_hw * hw)789 static inline int hxx_prescale(struct falcon_hw *hw)
790 {
791 return hw->ste_mode ? 16 :
792 vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
793 }
794
falcon_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)795 static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
796 struct atafb_par *par )
797 {
798 strcpy(fix->id, "Atari Builtin");
799 fix->smem_start = (unsigned long)real_screen_base;
800 fix->smem_len = screen_len;
801 fix->type = FB_TYPE_INTERLEAVED_PLANES;
802 fix->type_aux = 2;
803 fix->visual = FB_VISUAL_PSEUDOCOLOR;
804 fix->xpanstep = 1;
805 fix->ypanstep = 1;
806 fix->ywrapstep = 0;
807 if (par->hw.falcon.mono) {
808 fix->type = FB_TYPE_PACKED_PIXELS;
809 fix->type_aux = 0;
810 /* no smooth scrolling with longword aligned video mem */
811 fix->xpanstep = 32;
812 }
813 else if (par->hw.falcon.f_shift & 0x100) {
814 fix->type = FB_TYPE_PACKED_PIXELS;
815 fix->type_aux = 0;
816 /* Is this ok or should it be DIRECTCOLOR? */
817 fix->visual = FB_VISUAL_TRUECOLOR;
818 fix->xpanstep = 2;
819 }
820 fix->line_length = 0;
821 fix->accel = FB_ACCEL_ATARIBLITT;
822 return 0;
823 }
824
825
falcon_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)826 static int falcon_decode_var( struct fb_var_screeninfo *var,
827 struct atafb_par *par )
828 {
829 int bpp = var->bits_per_pixel;
830 int xres = var->xres;
831 int yres = var->yres;
832 int xres_virtual = var->xres_virtual;
833 int yres_virtual = var->yres_virtual;
834 int left_margin, right_margin, hsync_len;
835 int upper_margin, lower_margin, vsync_len;
836 int linelen;
837 int interlace = 0, doubleline = 0;
838 struct pixel_clock *pclock;
839 int plen; /* width of pixel in clock cycles */
840 int xstretch;
841 int prescale;
842 int longoffset = 0;
843 int hfreq, vfreq;
844
845 /*
846 Get the video params out of 'var'. If a value doesn't fit, round
847 it up, if it's too big, return EINVAL.
848 Round up in the following order: bits_per_pixel, xres, yres,
849 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
850 horizontal timing, vertical timing.
851
852 There is a maximum of screen resolution determined by pixelclock
853 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
854 In interlace mode this is " * " *vfmin <= pixelclock.
855 Additional constraints: hfreq.
856 Frequency range for multisync monitors is given via command line.
857 For TV and SM124 both frequencies are fixed.
858
859 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
860 Y % 16 == 0 to fit 8x16 font
861 Y % 8 == 0 if Y<400
862
863 Currently interlace and doubleline mode in var are ignored.
864 On SM124 and TV only the standard resolutions can be used.
865 */
866
867 /* Reject uninitialized mode */
868 if (!xres || !yres || !bpp)
869 return -EINVAL;
870
871 if (mon_type == F_MON_SM && bpp != 1) {
872 return -EINVAL;
873 }
874 else if (bpp <= 1) {
875 bpp = 1;
876 par->hw.falcon.f_shift = 0x400;
877 par->hw.falcon.st_shift = 0x200;
878 }
879 else if (bpp <= 2) {
880 bpp = 2;
881 par->hw.falcon.f_shift = 0x000;
882 par->hw.falcon.st_shift = 0x100;
883 }
884 else if (bpp <= 4) {
885 bpp = 4;
886 par->hw.falcon.f_shift = 0x000;
887 par->hw.falcon.st_shift = 0x000;
888 }
889 else if (bpp <= 8) {
890 bpp = 8;
891 par->hw.falcon.f_shift = 0x010;
892 }
893 else if (bpp <= 16) {
894 bpp = 16; /* packed pixel mode */
895 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
896 }
897 else
898 return -EINVAL;
899 par->hw.falcon.bpp = bpp;
900
901 if (mon_type == F_MON_SM || DontCalcRes) {
902 /* Skip all calculations. VGA/TV/SC1224 only supported. */
903 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
904
905 if (bpp > myvar->bits_per_pixel ||
906 var->xres > myvar->xres ||
907 var->yres > myvar->yres)
908 return -EINVAL;
909 fbhw->get_par(par); /* Current par will be new par */
910 goto set_screen_base; /* Don't forget this */
911 }
912
913 /* Only some fixed resolutions < 640x400 */
914 if (xres <= 320)
915 xres = 320;
916 else if (xres <= 640 && bpp != 16)
917 xres = 640;
918 if (yres <= 200)
919 yres = 200;
920 else if (yres <= 240)
921 yres = 240;
922 else if (yres <= 400)
923 yres = 400;
924
925 /* 2 planes must use STE compatibility mode */
926 par->hw.falcon.ste_mode = bpp==2;
927 par->hw.falcon.mono = bpp==1;
928
929 /* Total and visible scanline length must be a multiple of one longword,
930 * this and the console fontwidth yields the alignment for xres and
931 * xres_virtual.
932 * TODO: this way "odd" fontheights are not supported
933 *
934 * Special case in STE mode: blank and graphic positions don't align,
935 * avoid trash at right margin
936 */
937 if (par->hw.falcon.ste_mode)
938 xres = (xres + 63) & ~63;
939 else if (bpp == 1)
940 xres = (xres + 31) & ~31;
941 else
942 xres = (xres + 15) & ~15;
943 if (yres >= 400)
944 yres = (yres + 15) & ~15;
945 else
946 yres = (yres + 7) & ~7;
947
948 if (xres_virtual < xres)
949 xres_virtual = xres;
950 else if (bpp == 1)
951 xres_virtual = (xres_virtual + 31) & ~31;
952 else
953 xres_virtual = (xres_virtual + 15) & ~15;
954
955 if (yres_virtual <= 0)
956 yres_virtual = 0;
957 else if (yres_virtual < yres)
958 yres_virtual = yres;
959
960 /* backward bug-compatibility */
961 if (var->pixclock > 1)
962 var->pixclock -= 1;
963
964 par->hw.falcon.line_width = bpp * xres / 16;
965 par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
966
967 /* single or double pixel width */
968 xstretch = (xres < 640) ? 2 : 1;
969
970 #if 0 /* SM124 supports only 640x400, this is rejected above */
971 if (mon_type == F_MON_SM) {
972 if (xres != 640 && yres != 400)
973 return -EINVAL;
974 plen = 1;
975 pclock = &f32;
976 /* SM124-mode is special */
977 par->hw.falcon.ste_mode = 1;
978 par->hw.falcon.f_shift = 0x000;
979 par->hw.falcon.st_shift = 0x200;
980 left_margin = hsync_len = 128 / plen;
981 right_margin = 0;
982 /* TODO set all margins */
983 }
984 else
985 #endif
986 if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
987 plen = 2 * xstretch;
988 if (var->pixclock > f32.t * plen)
989 return -EINVAL;
990 pclock = &f32;
991 if (yres > 240)
992 interlace = 1;
993 if (var->pixclock == 0) {
994 /* set some minimal margins which center the screen */
995 left_margin = 32;
996 right_margin = 18;
997 hsync_len = pclock->hsync / plen;
998 upper_margin = 31;
999 lower_margin = 14;
1000 vsync_len = interlace ? 3 : 4;
1001 } else {
1002 left_margin = var->left_margin;
1003 right_margin = var->right_margin;
1004 hsync_len = var->hsync_len;
1005 upper_margin = var->upper_margin;
1006 lower_margin = var->lower_margin;
1007 vsync_len = var->vsync_len;
1008 if (var->vmode & FB_VMODE_INTERLACED) {
1009 upper_margin = (upper_margin + 1) / 2;
1010 lower_margin = (lower_margin + 1) / 2;
1011 vsync_len = (vsync_len + 1) / 2;
1012 } else if (var->vmode & FB_VMODE_DOUBLE) {
1013 upper_margin *= 2;
1014 lower_margin *= 2;
1015 vsync_len *= 2;
1016 }
1017 }
1018 }
1019 else
1020 { /* F_MON_VGA */
1021 if (bpp == 16)
1022 xstretch = 2; /* Double pixel width only for hicolor */
1023 /* Default values are used for vert./hor. timing if no pixelclock given. */
1024 if (var->pixclock == 0) {
1025 int linesize;
1026
1027 /* Choose master pixelclock depending on hor. timing */
1028 plen = 1 * xstretch;
1029 if ((plen * xres + f25.right+f25.hsync+f25.left) *
1030 fb_info.monspecs.hfmin < f25.f)
1031 pclock = &f25;
1032 else if ((plen * xres + f32.right+f32.hsync+f32.left) *
1033 fb_info.monspecs.hfmin < f32.f)
1034 pclock = &f32;
1035 else if ((plen * xres + fext.right+fext.hsync+fext.left) *
1036 fb_info.monspecs.hfmin < fext.f
1037 && fext.f)
1038 pclock = &fext;
1039 else
1040 return -EINVAL;
1041
1042 left_margin = pclock->left / plen;
1043 right_margin = pclock->right / plen;
1044 hsync_len = pclock->hsync / plen;
1045 linesize = left_margin + xres + right_margin + hsync_len;
1046 upper_margin = 31;
1047 lower_margin = 11;
1048 vsync_len = 3;
1049 }
1050 else {
1051 /* Choose largest pixelclock <= wanted clock */
1052 int i;
1053 unsigned long pcl = ULONG_MAX;
1054 pclock = 0;
1055 for (i=1; i <= 4; i *= 2) {
1056 if (f25.t*i >= var->pixclock && f25.t*i < pcl) {
1057 pcl = f25.t * i;
1058 pclock = &f25;
1059 }
1060 if (f32.t*i >= var->pixclock && f32.t*i < pcl) {
1061 pcl = f32.t * i;
1062 pclock = &f32;
1063 }
1064 if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) {
1065 pcl = fext.t * i;
1066 pclock = &fext;
1067 }
1068 }
1069 if (!pclock)
1070 return -EINVAL;
1071 plen = pcl / pclock->t;
1072
1073 left_margin = var->left_margin;
1074 right_margin = var->right_margin;
1075 hsync_len = var->hsync_len;
1076 upper_margin = var->upper_margin;
1077 lower_margin = var->lower_margin;
1078 vsync_len = var->vsync_len;
1079 /* Internal unit is [single lines per (half-)frame] */
1080 if (var->vmode & FB_VMODE_INTERLACED) {
1081 /* # lines in half frame */
1082 /* External unit is [lines per full frame] */
1083 upper_margin = (upper_margin + 1) / 2;
1084 lower_margin = (lower_margin + 1) / 2;
1085 vsync_len = (vsync_len + 1) / 2;
1086 }
1087 else if (var->vmode & FB_VMODE_DOUBLE) {
1088 /* External unit is [double lines per frame] */
1089 upper_margin *= 2;
1090 lower_margin *= 2;
1091 vsync_len *= 2;
1092 }
1093 }
1094 if (pclock == &fext)
1095 longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1096 }
1097 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1098 /* this is definitely wrong if bus clock != 32MHz */
1099 if (pclock->f / plen / 8 * bpp > 32000000L)
1100 return -EINVAL;
1101
1102 if (vsync_len < 1)
1103 vsync_len = 1;
1104
1105 /* include sync lengths in right/lower margin for all calculations */
1106 right_margin += hsync_len;
1107 lower_margin += vsync_len;
1108
1109 /* ! In all calculations of margins we use # of lines in half frame
1110 * (which is a full frame in non-interlace mode), so we can switch
1111 * between interlace and non-interlace without messing around
1112 * with these.
1113 */
1114 again:
1115 /* Set base_offset 128 and video bus width */
1116 par->hw.falcon.vid_control = mon_type | f030_bus_width;
1117 if (!longoffset)
1118 par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */
1119 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1120 par->hw.falcon.vid_control |= VCO_HSYPOS;
1121 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1122 par->hw.falcon.vid_control |= VCO_VSYPOS;
1123 /* Pixelclock */
1124 par->hw.falcon.vid_control |= pclock->control_mask;
1125 /* External or internal clock */
1126 par->hw.falcon.sync = pclock->sync_mask | 0x2;
1127 /* Pixellength and prescale */
1128 par->hw.falcon.vid_mode = (2/plen) << 2;
1129 if (doubleline)
1130 par->hw.falcon.vid_mode |= VMO_DOUBLE;
1131 if (interlace)
1132 par->hw.falcon.vid_mode |= VMO_INTER;
1133
1134 /*********************
1135 Horizontal timing: unit = [master clock cycles]
1136 unit of hxx-registers: [master clock cycles * prescale]
1137 Hxx-registers are 9 bit wide
1138
1139 1 line = ((hht + 2) * 2 * prescale) clock cycles
1140
1141 graphic output = hdb & 0x200 ?
1142 ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
1143 ( hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1144 (this must be a multiple of plen*128/bpp, on VGA pixels
1145 to the right may be cut off with a bigger right margin)
1146
1147 start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1148 (hdb - hht - 2) * prescale + hdboff :
1149 hdb * prescale + hdboff
1150
1151 end of graphics relative to start of 1st halfline =
1152 (hde + hht + 2) * prescale + hdeoff
1153 *********************/
1154 /* Calculate VIDEL registers */
1155 {
1156 int hdb_off, hde_off, base_off;
1157 int gstart, gend1, gend2, align;
1158
1159 prescale = hxx_prescale(&par->hw.falcon);
1160 base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1161
1162 /* Offsets depend on video mode */
1163 /* Offsets are in clock cycles, divide by prescale to
1164 * calculate hd[be]-registers
1165 */
1166 if (par->hw.falcon.f_shift & 0x100) {
1167 align = 1;
1168 hde_off = 0;
1169 hdb_off = (base_off + 16 * plen) + prescale;
1170 }
1171 else {
1172 align = 128 / bpp;
1173 hde_off = ((128 / bpp + 2) * plen);
1174 if (par->hw.falcon.ste_mode)
1175 hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1176 else
1177 hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1178 }
1179
1180 gstart = (prescale/2 + plen * left_margin) / prescale;
1181 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1182 gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
1183 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1184 gend2 = gstart + xres * plen / prescale;
1185 par->HHT = plen * (left_margin + xres + right_margin) /
1186 (2 * prescale) - 2;
1187 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1188
1189 par->HDB = gstart - hdb_off/prescale;
1190 par->HBE = gstart;
1191 if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
1192 par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
1193 par->HBB = gend2 - par->HHT - 2;
1194 #if 0
1195 /* One more Videl constraint: data fetch of two lines must not overlap */
1196 if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1197 /* if this happens increase margins, decrease hfreq. */
1198 }
1199 #endif
1200 if (hde_off % prescale)
1201 par->HBB++; /* compensate for non matching hde and hbb */
1202 par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1203 if (par->HSS < par->HBB)
1204 par->HSS = par->HBB;
1205 }
1206
1207 /* check hor. frequency */
1208 hfreq = pclock->f / ((par->HHT+2)*prescale*2);
1209 if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) {
1210 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1211 /* Too high -> enlarge margin */
1212 left_margin += 1;
1213 right_margin += 1;
1214 goto again;
1215 }
1216 if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1217 return -EINVAL;
1218
1219 /* Vxx-registers */
1220 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1221 * of the first displayed line!
1222 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1223 * non-interlace, odd in interlace mode for synchronisation.
1224 * Vxx-registers are 11 bit wide
1225 */
1226 par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1227 par->VDB = par->VBE;
1228 par->VDE = yres;
1229 if (!interlace) par->VDE <<= 1;
1230 if (doubleline) par->VDE <<= 1; /* VDE now half lines per (half-)frame */
1231 par->VDE += par->VDB;
1232 par->VBB = par->VDE;
1233 par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1234 par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
1235 /* vbb,vss,vft must be even in interlace mode */
1236 if (interlace) {
1237 par->VBB++;
1238 par->VSS++;
1239 par->VFT++;
1240 }
1241
1242 /* V-frequency check, hope I didn't create any loop here. */
1243 /* Interlace and doubleline are mutually exclusive. */
1244 vfreq = (hfreq * 2) / (par->VFT + 1);
1245 if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1246 /* Too high -> try again with doubleline */
1247 doubleline = 1;
1248 goto again;
1249 }
1250 else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1251 /* Too low -> try again with interlace */
1252 interlace = 1;
1253 goto again;
1254 }
1255 else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1256 /* Doubleline too low -> clear doubleline and enlarge margins */
1257 int lines;
1258 doubleline = 0;
1259 for (lines=0;
1260 (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax;
1261 lines++)
1262 ;
1263 upper_margin += lines;
1264 lower_margin += lines;
1265 goto again;
1266 }
1267 else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1268 /* Doubleline too high -> enlarge margins */
1269 int lines;
1270 for (lines=0;
1271 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1272 lines+=2)
1273 ;
1274 upper_margin += lines;
1275 lower_margin += lines;
1276 goto again;
1277 }
1278 else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1279 /* Interlace, too high -> enlarge margins */
1280 int lines;
1281 for (lines=0;
1282 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1283 lines++)
1284 ;
1285 upper_margin += lines;
1286 lower_margin += lines;
1287 goto again;
1288 }
1289 else if (vfreq < fb_info.monspecs.vfmin ||
1290 vfreq > fb_info.monspecs.vfmax)
1291 return -EINVAL;
1292
1293 set_screen_base:
1294 linelen = xres_virtual * bpp / 8;
1295 if (yres_virtual * linelen > screen_len && screen_len)
1296 return -EINVAL;
1297 if (yres * linelen > screen_len && screen_len)
1298 return -EINVAL;
1299 if (var->yoffset + yres > yres_virtual && yres_virtual)
1300 return -EINVAL;
1301 par->yres_virtual = yres_virtual;
1302 par->screen_base = screen_base + var->yoffset * linelen;
1303 par->hw.falcon.xoffset = 0;
1304
1305 return 0;
1306 }
1307
falcon_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)1308 static int falcon_encode_var( struct fb_var_screeninfo *var,
1309 struct atafb_par *par )
1310 {
1311 /* !!! only for VGA !!! */
1312 int linelen;
1313 int prescale, plen;
1314 int hdb_off, hde_off, base_off;
1315 struct falcon_hw *hw = &par->hw.falcon;
1316
1317 memset(var, 0, sizeof(struct fb_var_screeninfo));
1318 /* possible frequencies: 25.175 or 32MHz */
1319 var->pixclock = hw->sync & 0x1 ? fext.t :
1320 hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1321
1322 var->height=-1;
1323 var->width=-1;
1324
1325 var->sync=0;
1326 if (hw->vid_control & VCO_HSYPOS)
1327 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1328 if (hw->vid_control & VCO_VSYPOS)
1329 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1330
1331 var->vmode = FB_VMODE_NONINTERLACED;
1332 if (hw->vid_mode & VMO_INTER)
1333 var->vmode |= FB_VMODE_INTERLACED;
1334 if (hw->vid_mode & VMO_DOUBLE)
1335 var->vmode |= FB_VMODE_DOUBLE;
1336
1337 /* visible y resolution:
1338 * Graphics display starts at line VDB and ends at line
1339 * VDE. If interlace mode off unit of VC-registers is
1340 * half lines, else lines.
1341 */
1342 var->yres = hw->vde - hw->vdb;
1343 if (!(var->vmode & FB_VMODE_INTERLACED))
1344 var->yres >>= 1;
1345 if (var->vmode & FB_VMODE_DOUBLE)
1346 var->yres >>= 1;
1347
1348 /* to get bpp, we must examine f_shift and st_shift.
1349 * f_shift is valid if any of bits no. 10, 8 or 4
1350 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1351 * if bit 10 set then bit 8 and bit 4 don't care...
1352 * If all these bits are 0 get display depth from st_shift
1353 * (as for ST and STE)
1354 */
1355 if (hw->f_shift & 0x400) /* 2 colors */
1356 var->bits_per_pixel = 1;
1357 else if (hw->f_shift & 0x100) /* hicolor */
1358 var->bits_per_pixel = 16;
1359 else if (hw->f_shift & 0x010) /* 8 bitplanes */
1360 var->bits_per_pixel = 8;
1361 else if (hw->st_shift == 0)
1362 var->bits_per_pixel = 4;
1363 else if (hw->st_shift == 0x100)
1364 var->bits_per_pixel = 2;
1365 else /* if (hw->st_shift == 0x200) */
1366 var->bits_per_pixel = 1;
1367
1368 var->xres = hw->line_width * 16 / var->bits_per_pixel;
1369 var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1370 if (hw->xoffset)
1371 var->xres_virtual += 16;
1372
1373 if (var->bits_per_pixel == 16) {
1374 var->red.offset=11;
1375 var->red.length=5;
1376 var->red.msb_right=0;
1377 var->green.offset=5;
1378 var->green.length=6;
1379 var->green.msb_right=0;
1380 var->blue.offset=0;
1381 var->blue.length=5;
1382 var->blue.msb_right=0;
1383 }
1384 else {
1385 var->red.offset=0;
1386 var->red.length = hw->ste_mode ? 4 : 6;
1387 var->red.msb_right=0;
1388 var->grayscale=0;
1389 var->blue=var->green=var->red;
1390 }
1391 var->transp.offset=0;
1392 var->transp.length=0;
1393 var->transp.msb_right=0;
1394
1395 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1396 if (screen_len) {
1397 if (par->yres_virtual)
1398 var->yres_virtual = par->yres_virtual;
1399 else
1400 /* yres_virtual==0 means use maximum */
1401 var->yres_virtual = screen_len / linelen;
1402 }
1403 else {
1404 if (hwscroll < 0)
1405 var->yres_virtual = 2 * var->yres;
1406 else
1407 var->yres_virtual=var->yres+hwscroll * 16;
1408 }
1409 var->xoffset=0; /* TODO change this */
1410
1411 /* hdX-offsets */
1412 prescale = hxx_prescale(hw);
1413 plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1414 base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1415 if (hw->f_shift & 0x100) {
1416 hde_off = 0;
1417 hdb_off = (base_off + 16 * plen) + prescale;
1418 }
1419 else {
1420 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1421 if (hw->ste_mode)
1422 hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1423 + prescale;
1424 else
1425 hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1426 + prescale;
1427 }
1428
1429 /* Right margin includes hsync */
1430 var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1431 (hw->hdb & 0x200 ? 2+hw->hht : 0));
1432 if (hw->ste_mode || mon_type!=F_MON_VGA)
1433 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1434 else
1435 /* can't use this in ste_mode, because hbb is +1 off */
1436 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1437 var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1438
1439 /* Lower margin includes vsync */
1440 var->upper_margin = hw->vdb / 2 ; /* round down to full lines */
1441 var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
1442 var->vsync_len = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
1443 if (var->vmode & FB_VMODE_INTERLACED) {
1444 var->upper_margin *= 2;
1445 var->lower_margin *= 2;
1446 var->vsync_len *= 2;
1447 }
1448 else if (var->vmode & FB_VMODE_DOUBLE) {
1449 var->upper_margin = (var->upper_margin + 1) / 2;
1450 var->lower_margin = (var->lower_margin + 1) / 2;
1451 var->vsync_len = (var->vsync_len + 1) / 2;
1452 }
1453
1454 var->pixclock *= plen;
1455 var->left_margin /= plen;
1456 var->right_margin /= plen;
1457 var->hsync_len /= plen;
1458
1459 var->right_margin -= var->hsync_len;
1460 var->lower_margin -= var->vsync_len;
1461
1462 if (screen_base)
1463 var->yoffset=(par->screen_base - screen_base)/linelen;
1464 else
1465 var->yoffset=0;
1466 var->nonstd=0; /* what is this for? */
1467 var->activate=0;
1468 return 0;
1469 }
1470
1471
1472 static int f_change_mode = 0;
1473 static struct falcon_hw f_new_mode;
1474 static int f_pan_display = 0;
1475
falcon_get_par(struct atafb_par * par)1476 static void falcon_get_par( struct atafb_par *par )
1477 {
1478 unsigned long addr;
1479 struct falcon_hw *hw = &par->hw.falcon;
1480
1481 hw->line_width = shifter_f030.scn_width;
1482 hw->line_offset = shifter_f030.off_next;
1483 hw->st_shift = videl.st_shift & 0x300;
1484 hw->f_shift = videl.f_shift;
1485 hw->vid_control = videl.control;
1486 hw->vid_mode = videl.mode;
1487 hw->sync = shifter.syncmode & 0x1;
1488 hw->xoffset = videl.xoffset & 0xf;
1489 hw->hht = videl.hht;
1490 hw->hbb = videl.hbb;
1491 hw->hbe = videl.hbe;
1492 hw->hdb = videl.hdb;
1493 hw->hde = videl.hde;
1494 hw->hss = videl.hss;
1495 hw->vft = videl.vft;
1496 hw->vbb = videl.vbb;
1497 hw->vbe = videl.vbe;
1498 hw->vdb = videl.vdb;
1499 hw->vde = videl.vde;
1500 hw->vss = videl.vss;
1501
1502 addr = (shifter.bas_hi & 0xff) << 16 |
1503 (shifter.bas_md & 0xff) << 8 |
1504 (shifter.bas_lo & 0xff);
1505 par->screen_base = phys_to_virt(addr);
1506
1507 /* derived parameters */
1508 hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
1509 hw->mono = (hw->f_shift & 0x400) ||
1510 ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
1511 }
1512
falcon_set_par(struct atafb_par * par)1513 static void falcon_set_par( struct atafb_par *par )
1514 {
1515 f_change_mode = 0;
1516
1517 /* only set screen_base if really necessary */
1518 if (current_par.screen_base != par->screen_base)
1519 fbhw->set_screen_base(par->screen_base);
1520
1521 /* Don't touch any other registers if we keep the default resolution */
1522 if (DontCalcRes)
1523 return;
1524
1525 /* Tell vbl-handler to change video mode.
1526 * We change modes only on next VBL, to avoid desynchronisation
1527 * (a shift to the right and wrap around by a random number of pixels
1528 * in all monochrome modes).
1529 * This seems to work on my Falcon.
1530 */
1531 f_new_mode = par->hw.falcon;
1532 f_change_mode = 1;
1533 }
1534
1535
falcon_vbl_switcher(int irq,void * dummy,struct pt_regs * fp)1536 static void falcon_vbl_switcher( int irq, void *dummy, struct pt_regs *fp )
1537 {
1538 struct falcon_hw *hw = &f_new_mode;
1539
1540 if (f_change_mode) {
1541 f_change_mode = 0;
1542
1543 if (hw->sync & 0x1) {
1544 /* Enable external pixelclock. This code only for ScreenWonder */
1545 *(volatile unsigned short*)0xffff9202 = 0xffbf;
1546 }
1547 else {
1548 /* Turn off external clocks. Read sets all output bits to 1. */
1549 *(volatile unsigned short*)0xffff9202;
1550 }
1551 shifter.syncmode = hw->sync;
1552
1553 videl.hht = hw->hht;
1554 videl.hbb = hw->hbb;
1555 videl.hbe = hw->hbe;
1556 videl.hdb = hw->hdb;
1557 videl.hde = hw->hde;
1558 videl.hss = hw->hss;
1559 videl.vft = hw->vft;
1560 videl.vbb = hw->vbb;
1561 videl.vbe = hw->vbe;
1562 videl.vdb = hw->vdb;
1563 videl.vde = hw->vde;
1564 videl.vss = hw->vss;
1565
1566 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1567 if (hw->ste_mode) {
1568 videl.st_shift = hw->st_shift; /* write enables STE palette */
1569 }
1570 else {
1571 /* IMPORTANT:
1572 * set st_shift 0, so we can tell the screen-depth if f_shift==0.
1573 * Writing 0 to f_shift enables 4 plane Falcon mode but
1574 * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
1575 * with Falcon palette.
1576 */
1577 videl.st_shift = 0;
1578 /* now back to Falcon palette mode */
1579 videl.f_shift = hw->f_shift;
1580 }
1581 /* writing to st_shift changed scn_width and vid_mode */
1582 videl.xoffset = hw->xoffset;
1583 shifter_f030.scn_width = hw->line_width;
1584 shifter_f030.off_next = hw->line_offset;
1585 videl.control = hw->vid_control;
1586 videl.mode = hw->vid_mode;
1587 }
1588 if (f_pan_display) {
1589 f_pan_display = 0;
1590 videl.xoffset = current_par.hw.falcon.xoffset;
1591 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1592 }
1593 }
1594
1595
falcon_pan_display(struct fb_var_screeninfo * var,struct atafb_par * par)1596 static int falcon_pan_display( struct fb_var_screeninfo *var,
1597 struct atafb_par *par )
1598 {
1599 int xoffset;
1600 int bpp = fb_display[currcon].var.bits_per_pixel;
1601
1602 if (bpp == 1)
1603 var->xoffset = up(var->xoffset, 32);
1604 if (bpp != 16)
1605 par->hw.falcon.xoffset = var->xoffset & 15;
1606 else {
1607 par->hw.falcon.xoffset = 0;
1608 var->xoffset = up(var->xoffset, 2);
1609 }
1610 par->hw.falcon.line_offset = bpp *
1611 (fb_display[currcon].var.xres_virtual - fb_display[currcon].var.xres) / 16;
1612 if (par->hw.falcon.xoffset)
1613 par->hw.falcon.line_offset -= bpp;
1614 xoffset = var->xoffset - par->hw.falcon.xoffset;
1615
1616 par->screen_base = screen_base +
1617 (var->yoffset * fb_display[currcon].var.xres_virtual + xoffset) * bpp / 8;
1618 if (fbhw->set_screen_base)
1619 fbhw->set_screen_base (par->screen_base);
1620 else
1621 return -EINVAL; /* shouldn't happen */
1622 f_pan_display = 1;
1623 return 0;
1624 }
1625
1626
falcon_getcolreg(unsigned regno,unsigned * red,unsigned * green,unsigned * blue,unsigned * transp,struct fb_info * info)1627 static int falcon_getcolreg( unsigned regno, unsigned *red,
1628 unsigned *green, unsigned *blue,
1629 unsigned *transp, struct fb_info *info )
1630 { unsigned long col;
1631
1632 if (regno > 255)
1633 return 1;
1634 /* This works in STE-mode (with 4bit/color) since f030_col-registers
1635 * hold up to 6bit/color.
1636 * Even with hicolor r/g/b=5/6/5 bit!
1637 */
1638 col = f030_col[regno];
1639 *red = (col >> 16) & 0xff00;
1640 *green = (col >> 8) & 0xff00;
1641 *blue = (col << 8) & 0xff00;
1642 *transp = 0;
1643 return 0;
1644 }
1645
1646
falcon_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)1647 static int falcon_setcolreg( unsigned regno, unsigned red,
1648 unsigned green, unsigned blue,
1649 unsigned transp, struct fb_info *info )
1650 {
1651 if (regno > 255)
1652 return 1;
1653 f030_col[regno] = (((red & 0xfc00) << 16) |
1654 ((green & 0xfc00) << 8) |
1655 ((blue & 0xfc00) >> 8));
1656 if (regno < 16) {
1657 shifter_tt.color_reg[regno] =
1658 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1659 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1660 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1661 #ifdef FBCON_HAS_CFB16
1662 fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
1663 ((green & 0xfc00) >> 5) |
1664 ((blue & 0xf800) >> 11));
1665 #endif
1666 }
1667 return 0;
1668 }
1669
1670
falcon_blank(int blank_mode)1671 static int falcon_blank( int blank_mode )
1672 {
1673 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1674 * so VIDEL doesn't hog the bus while saving.
1675 * (this may affect usleep()).
1676 */
1677 int vdb, vss, hbe, hss;
1678
1679 if (mon_type == F_MON_SM) /* this doesn't work on SM124 */
1680 return 1;
1681
1682 vdb = current_par.VDB;
1683 vss = current_par.VSS;
1684 hbe = current_par.HBE;
1685 hss = current_par.HSS;
1686
1687 if (blank_mode >= 1) {
1688 /* disable graphics output (this speeds up the CPU) ... */
1689 vdb = current_par.VFT + 1;
1690 /* ... and blank all lines */
1691 hbe = current_par.HHT + 2;
1692 }
1693 /* use VESA suspend modes on VGA monitors */
1694 if (mon_type == F_MON_VGA) {
1695 if (blank_mode == 2 || blank_mode == 4)
1696 vss = current_par.VFT + 1;
1697 if (blank_mode == 3 || blank_mode == 4)
1698 hss = current_par.HHT + 2;
1699 }
1700
1701 videl.vdb = vdb;
1702 videl.vss = vss;
1703 videl.hbe = hbe;
1704 videl.hss = hss;
1705
1706 return 0;
1707 }
1708
1709
falcon_detect(void)1710 static int falcon_detect( void )
1711 {
1712 struct atafb_par par;
1713 unsigned char fhw;
1714
1715 /* Determine connected monitor and set monitor parameters */
1716 fhw = *(unsigned char*)0xffff8006;
1717 mon_type = fhw >> 6 & 0x3;
1718 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1719 f030_bus_width = fhw << 6 & 0x80;
1720 switch (mon_type) {
1721 case F_MON_SM:
1722 fb_info.monspecs.vfmin = 70;
1723 fb_info.monspecs.vfmax = 72;
1724 fb_info.monspecs.hfmin = 35713;
1725 fb_info.monspecs.hfmax = 35715;
1726 break;
1727 case F_MON_SC:
1728 case F_MON_TV:
1729 /* PAL...NTSC */
1730 fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
1731 fb_info.monspecs.vfmax = 60;
1732 fb_info.monspecs.hfmin = 15620;
1733 fb_info.monspecs.hfmax = 15755;
1734 break;
1735 }
1736 /* initialize hsync-len */
1737 f25.hsync = h_syncs[mon_type] / f25.t;
1738 f32.hsync = h_syncs[mon_type] / f32.t;
1739 if (fext.t)
1740 fext.hsync = h_syncs[mon_type] / fext.t;
1741
1742 falcon_get_par(&par);
1743 falcon_encode_var(&atafb_predefined[0], &par);
1744
1745 /* Detected mode is always the "autodetect" slot */
1746 return 1;
1747 }
1748
1749 #endif /* ATAFB_FALCON */
1750
1751 /* ------------------- ST(E) specific functions ---------------------- */
1752
1753 #ifdef ATAFB_STE
1754
stste_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)1755 static int stste_encode_fix( struct fb_fix_screeninfo *fix,
1756 struct atafb_par *par )
1757
1758 {
1759 int mode;
1760
1761 strcpy(fix->id,"Atari Builtin");
1762 fix->smem_start = (unsigned long)real_screen_base;
1763 fix->smem_len = screen_len;
1764 fix->type = FB_TYPE_INTERLEAVED_PLANES;
1765 fix->type_aux = 2;
1766 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1767 mode = par->hw.st.mode & 3;
1768 if (mode == ST_HIGH) {
1769 fix->type = FB_TYPE_PACKED_PIXELS;
1770 fix->type_aux = 0;
1771 fix->visual = FB_VISUAL_MONO10;
1772 }
1773 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1774 fix->xpanstep = 16;
1775 fix->ypanstep = 1;
1776 } else {
1777 fix->xpanstep = 0;
1778 fix->ypanstep = 0;
1779 }
1780 fix->ywrapstep = 0;
1781 fix->line_length = 0;
1782 fix->accel = FB_ACCEL_ATARIBLITT;
1783 return 0;
1784 }
1785
1786
stste_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)1787 static int stste_decode_var( struct fb_var_screeninfo *var,
1788 struct atafb_par *par )
1789 {
1790 int xres=var->xres;
1791 int yres=var->yres;
1792 int bpp=var->bits_per_pixel;
1793 int linelen;
1794 int yres_virtual = var->yres_virtual;
1795
1796 if (mono_moni) {
1797 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1798 return -EINVAL;
1799 par->hw.st.mode=ST_HIGH;
1800 xres=sttt_xres;
1801 yres=st_yres;
1802 bpp=1;
1803 } else {
1804 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1805 return -EINVAL;
1806 if (bpp > 2) {
1807 if (xres > sttt_xres/2 || yres > st_yres/2)
1808 return -EINVAL;
1809 par->hw.st.mode=ST_LOW;
1810 xres=sttt_xres/2;
1811 yres=st_yres/2;
1812 bpp=4;
1813 }
1814 else if (bpp > 1) {
1815 if (xres > sttt_xres || yres > st_yres/2)
1816 return -EINVAL;
1817 par->hw.st.mode=ST_MID;
1818 xres=sttt_xres;
1819 yres=st_yres/2;
1820 bpp=2;
1821 }
1822 else
1823 return -EINVAL;
1824 }
1825 if (yres_virtual <= 0)
1826 yres_virtual = 0;
1827 else if (yres_virtual < yres)
1828 yres_virtual = yres;
1829 if (var->sync & FB_SYNC_EXT)
1830 par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
1831 else
1832 par->hw.st.sync=(par->hw.st.sync & ~1);
1833 linelen=xres*bpp/8;
1834 if (yres_virtual * linelen > screen_len && screen_len)
1835 return -EINVAL;
1836 if (yres * linelen > screen_len && screen_len)
1837 return -EINVAL;
1838 if (var->yoffset + yres > yres_virtual && yres_virtual)
1839 return -EINVAL;
1840 par->yres_virtual = yres_virtual;
1841 par->screen_base=screen_base+ var->yoffset*linelen;
1842 return 0;
1843 }
1844
stste_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)1845 static int stste_encode_var( struct fb_var_screeninfo *var,
1846 struct atafb_par *par )
1847 {
1848 int linelen;
1849 memset(var, 0, sizeof(struct fb_var_screeninfo));
1850 var->red.offset=0;
1851 var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1852 var->red.msb_right=0;
1853 var->grayscale=0;
1854
1855 var->pixclock=31041;
1856 var->left_margin=120; /* these are incorrect */
1857 var->right_margin=100;
1858 var->upper_margin=8;
1859 var->lower_margin=16;
1860 var->hsync_len=140;
1861 var->vsync_len=30;
1862
1863 var->height=-1;
1864 var->width=-1;
1865
1866 if (!(par->hw.st.sync & 1))
1867 var->sync=0;
1868 else
1869 var->sync=FB_SYNC_EXT;
1870
1871 switch (par->hw.st.mode & 3) {
1872 case ST_LOW:
1873 var->xres=sttt_xres/2;
1874 var->yres=st_yres/2;
1875 var->bits_per_pixel=4;
1876 break;
1877 case ST_MID:
1878 var->xres=sttt_xres;
1879 var->yres=st_yres/2;
1880 var->bits_per_pixel=2;
1881 break;
1882 case ST_HIGH:
1883 var->xres=sttt_xres;
1884 var->yres=st_yres;
1885 var->bits_per_pixel=1;
1886 break;
1887 }
1888 var->blue=var->green=var->red;
1889 var->transp.offset=0;
1890 var->transp.length=0;
1891 var->transp.msb_right=0;
1892 var->xres_virtual=sttt_xres_virtual;
1893 linelen=var->xres_virtual * var->bits_per_pixel / 8;
1894 ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
1895
1896 if (! use_hwscroll)
1897 var->yres_virtual=var->yres;
1898 else if (screen_len) {
1899 if (par->yres_virtual)
1900 var->yres_virtual = par->yres_virtual;
1901 else
1902 /* yres_virtual==0 means use maximum */
1903 var->yres_virtual = screen_len / linelen;
1904 }
1905 else {
1906 if (hwscroll < 0)
1907 var->yres_virtual = 2 * var->yres;
1908 else
1909 var->yres_virtual=var->yres+hwscroll * 16;
1910 }
1911 var->xoffset=0;
1912 if (screen_base)
1913 var->yoffset=(par->screen_base - screen_base)/linelen;
1914 else
1915 var->yoffset=0;
1916 var->nonstd=0;
1917 var->activate=0;
1918 var->vmode=FB_VMODE_NONINTERLACED;
1919 return 0;
1920 }
1921
1922
stste_get_par(struct atafb_par * par)1923 static void stste_get_par( struct atafb_par *par )
1924 {
1925 unsigned long addr;
1926 par->hw.st.mode=shifter_tt.st_shiftmode;
1927 par->hw.st.sync=shifter.syncmode;
1928 addr = ((shifter.bas_hi & 0xff) << 16) |
1929 ((shifter.bas_md & 0xff) << 8);
1930 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1931 addr |= (shifter.bas_lo & 0xff);
1932 par->screen_base = phys_to_virt(addr);
1933 }
1934
stste_set_par(struct atafb_par * par)1935 static void stste_set_par( struct atafb_par *par )
1936 {
1937 shifter_tt.st_shiftmode=par->hw.st.mode;
1938 shifter.syncmode=par->hw.st.sync;
1939 /* only set screen_base if really necessary */
1940 if (current_par.screen_base != par->screen_base)
1941 fbhw->set_screen_base(par->screen_base);
1942 }
1943
1944
stste_getcolreg(unsigned regno,unsigned * red,unsigned * green,unsigned * blue,unsigned * transp,struct fb_info * info)1945 static int stste_getcolreg(unsigned regno, unsigned *red,
1946 unsigned *green, unsigned *blue,
1947 unsigned *transp, struct fb_info *info)
1948 {
1949 unsigned col, t;
1950
1951 if (regno > 15)
1952 return 1;
1953 col = shifter_tt.color_reg[regno];
1954 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1955 t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
1956 t |= t << 4;
1957 *red = t | (t << 8);
1958 t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
1959 t |= t << 4;
1960 *green = t | (t << 8);
1961 t = ((col << 1) & 0xe) | ((col >> 3) & 1);
1962 t |= t << 4;
1963 *blue = t | (t << 8);
1964 }
1965 else {
1966 t = (col >> 7) & 0xe;
1967 t |= t << 4;
1968 *red = t | (t << 8);
1969 t = (col >> 3) & 0xe;
1970 t |= t << 4;
1971 *green = t | (t << 8);
1972 t = (col << 1) & 0xe;
1973 t |= t << 4;
1974 *blue = t | (t << 8);
1975 }
1976 *transp = 0;
1977 return 0;
1978 }
1979
1980
stste_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)1981 static int stste_setcolreg(unsigned regno, unsigned red,
1982 unsigned green, unsigned blue,
1983 unsigned transp, struct fb_info *info)
1984 {
1985 if (regno > 15)
1986 return 1;
1987 red >>= 12;
1988 blue >>= 12;
1989 green >>= 12;
1990 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1991 shifter_tt.color_reg[regno] =
1992 (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1993 (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1994 ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1995 else
1996 shifter_tt.color_reg[regno] =
1997 ((red & 0xe) << 7) |
1998 ((green & 0xe) << 3) |
1999 ((blue & 0xe) >> 1);
2000 return 0;
2001 }
2002
2003
stste_detect(void)2004 static int stste_detect( void )
2005
2006 { struct atafb_par par;
2007
2008 /* Determine the connected monitor: The DMA sound must be
2009 * disabled before reading the MFP GPIP, because the Sound
2010 * Done Signal and the Monochrome Detect are XORed together!
2011 */
2012 if (ATARIHW_PRESENT(PCM_8BIT)) {
2013 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2014 udelay(20); /* wait a while for things to settle down */
2015 }
2016 mono_moni = (mfp.par_dt_reg & 0x80) == 0;
2017
2018 stste_get_par(&par);
2019 stste_encode_var(&atafb_predefined[0], &par);
2020
2021 if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2022 use_hwscroll = 0;
2023 return 1;
2024 }
2025
stste_set_screen_base(void * s_base)2026 static void stste_set_screen_base(void *s_base)
2027 {
2028 unsigned long addr;
2029 addr= virt_to_phys(s_base);
2030 /* Setup Screen Memory */
2031 shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2032 shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2033 if (ATARIHW_PRESENT(EXTD_SHIFTER))
2034 shifter.bas_lo=(unsigned char) (addr & 0x0000ff);
2035 }
2036
2037 #endif /* ATAFB_STE */
2038
2039 /* Switching the screen size should be done during vsync, otherwise
2040 * the margins may get messed up. This is a well known problem of
2041 * the ST's video system.
2042 *
2043 * Unfortunately there is hardly any way to find the vsync, as the
2044 * vertical blank interrupt is no longer in time on machines with
2045 * overscan type modifications.
2046 *
2047 * We can, however, use Timer B to safely detect the black shoulder,
2048 * but then we've got to guess an appropriate delay to find the vsync.
2049 * This might not work on every machine.
2050 *
2051 * martin_rogge @ ki.maus.de, 8th Aug 1995
2052 */
2053
2054 #define LINE_DELAY (mono_moni ? 30 : 70)
2055 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2056
2057 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
st_ovsc_switch(void)2058 static void st_ovsc_switch(void)
2059 {
2060 unsigned long flags;
2061 register unsigned char old, new;
2062
2063 if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2064 return;
2065 save_flags(flags);
2066 cli();
2067
2068 mfp.tim_ct_b = 0x10;
2069 mfp.active_edge |= 8;
2070 mfp.tim_ct_b = 0;
2071 mfp.tim_dt_b = 0xf0;
2072 mfp.tim_ct_b = 8;
2073 while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2074 ;
2075 new = mfp.tim_dt_b;
2076 do {
2077 udelay(LINE_DELAY);
2078 old = new;
2079 new = mfp.tim_dt_b;
2080 } while (old != new);
2081 mfp.tim_ct_b = 0x10;
2082 udelay(SYNC_DELAY);
2083
2084 if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2085 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2086 if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2087 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2088 if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2089 sound_ym.rd_data_reg_sel = 14;
2090 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2091 ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2092 ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2093 }
2094 restore_flags(flags);
2095 }
2096
2097 /* ------------------- External Video ---------------------- */
2098
2099 #ifdef ATAFB_EXT
2100
ext_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)2101 static int ext_encode_fix( struct fb_fix_screeninfo *fix,
2102 struct atafb_par *par )
2103
2104 {
2105 strcpy(fix->id,"Unknown Extern");
2106 fix->smem_start = (unsigned long)external_addr;
2107 fix->smem_len = PAGE_ALIGN(external_len);
2108 if (external_depth == 1) {
2109 fix->type = FB_TYPE_PACKED_PIXELS;
2110 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2111 * for "normal" and "inverted", rsp., in the monochrome case */
2112 fix->visual =
2113 (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2114 external_pmode == FB_TYPE_PACKED_PIXELS) ?
2115 FB_VISUAL_MONO10 :
2116 FB_VISUAL_MONO01;
2117 }
2118 else {
2119 /* Use STATIC if we don't know how to access color registers */
2120 int visual = external_vgaiobase ?
2121 FB_VISUAL_PSEUDOCOLOR :
2122 FB_VISUAL_STATIC_PSEUDOCOLOR;
2123 switch (external_pmode) {
2124 case -1: /* truecolor */
2125 fix->type=FB_TYPE_PACKED_PIXELS;
2126 fix->visual=FB_VISUAL_TRUECOLOR;
2127 break;
2128 case FB_TYPE_PACKED_PIXELS:
2129 fix->type=FB_TYPE_PACKED_PIXELS;
2130 fix->visual=visual;
2131 break;
2132 case FB_TYPE_PLANES:
2133 fix->type=FB_TYPE_PLANES;
2134 fix->visual=visual;
2135 break;
2136 case FB_TYPE_INTERLEAVED_PLANES:
2137 fix->type=FB_TYPE_INTERLEAVED_PLANES;
2138 fix->type_aux=2;
2139 fix->visual=visual;
2140 break;
2141 }
2142 }
2143 fix->xpanstep = 0;
2144 fix->ypanstep = 0;
2145 fix->ywrapstep = 0;
2146 fix->line_length = 0;
2147 return 0;
2148 }
2149
2150
ext_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)2151 static int ext_decode_var( struct fb_var_screeninfo *var,
2152 struct atafb_par *par )
2153 {
2154 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2155
2156 if (var->bits_per_pixel > myvar->bits_per_pixel ||
2157 var->xres > myvar->xres ||
2158 var->xres_virtual > myvar->xres_virtual ||
2159 var->yres > myvar->yres ||
2160 var->xoffset > 0 ||
2161 var->yoffset > 0)
2162 return -EINVAL;
2163 return 0;
2164 }
2165
2166
ext_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)2167 static int ext_encode_var( struct fb_var_screeninfo *var,
2168 struct atafb_par *par )
2169 {
2170 memset(var, 0, sizeof(struct fb_var_screeninfo));
2171 var->red.offset=0;
2172 var->red.length=(external_pmode == -1) ? external_depth/3 :
2173 (external_vgaiobase ? external_bitspercol : 0);
2174 var->red.msb_right=0;
2175 var->grayscale=0;
2176
2177 var->pixclock=31041;
2178 var->left_margin=120; /* these are surely incorrect */
2179 var->right_margin=100;
2180 var->upper_margin=8;
2181 var->lower_margin=16;
2182 var->hsync_len=140;
2183 var->vsync_len=30;
2184
2185 var->height=-1;
2186 var->width=-1;
2187
2188 var->sync=0;
2189
2190 var->xres = external_xres;
2191 var->yres = external_yres;
2192 var->xres_virtual = external_xres_virtual;
2193 var->bits_per_pixel = external_depth;
2194
2195 var->blue=var->green=var->red;
2196 var->transp.offset=0;
2197 var->transp.length=0;
2198 var->transp.msb_right=0;
2199 var->yres_virtual=var->yres;
2200 var->xoffset=0;
2201 var->yoffset=0;
2202 var->nonstd=0;
2203 var->activate=0;
2204 var->vmode=FB_VMODE_NONINTERLACED;
2205 return 0;
2206 }
2207
2208
ext_get_par(struct atafb_par * par)2209 static void ext_get_par( struct atafb_par *par )
2210 {
2211 par->screen_base = external_addr;
2212 }
2213
ext_set_par(struct atafb_par * par)2214 static void ext_set_par( struct atafb_par *par )
2215 {
2216 }
2217
2218 #define OUTB(port,val) \
2219 *((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
2220 #define INB(port) \
2221 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2222 #define DACDelay \
2223 do { \
2224 unsigned char tmp=INB(0x3da); \
2225 tmp=INB(0x3da); \
2226 } while (0)
2227
ext_getcolreg(unsigned regno,unsigned * red,unsigned * green,unsigned * blue,unsigned * transp,struct fb_info * info)2228 static int ext_getcolreg( unsigned regno, unsigned *red,
2229 unsigned *green, unsigned *blue,
2230 unsigned *transp, struct fb_info *info )
2231 {
2232 if (! external_vgaiobase)
2233 return 1;
2234
2235 *red = ext_color[regno].red;
2236 *green = ext_color[regno].green;
2237 *blue = ext_color[regno].blue;
2238 *transp=0;
2239 return 0;
2240 }
2241
ext_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)2242 static int ext_setcolreg( unsigned regno, unsigned red,
2243 unsigned green, unsigned blue,
2244 unsigned transp, struct fb_info *info )
2245
2246 { unsigned char colmask = (1 << external_bitspercol) - 1;
2247
2248 if (! external_vgaiobase)
2249 return 1;
2250
2251 ext_color[regno].red = red;
2252 ext_color[regno].green = green;
2253 ext_color[regno].blue = blue;
2254
2255 switch (external_card_type) {
2256 case IS_VGA:
2257 OUTB(0x3c8, regno);
2258 DACDelay;
2259 OUTB(0x3c9, red & colmask);
2260 DACDelay;
2261 OUTB(0x3c9, green & colmask);
2262 DACDelay;
2263 OUTB(0x3c9, blue & colmask);
2264 DACDelay;
2265 return 0;
2266
2267 case IS_MV300:
2268 OUTB((MV300_reg[regno] << 2)+1, red);
2269 OUTB((MV300_reg[regno] << 2)+1, green);
2270 OUTB((MV300_reg[regno] << 2)+1, blue);
2271 return 0;
2272
2273 default:
2274 return 1;
2275 }
2276 }
2277
2278
ext_detect(void)2279 static int ext_detect( void )
2280
2281 {
2282 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2283 struct atafb_par dummy_par;
2284
2285 myvar->xres = external_xres;
2286 myvar->xres_virtual = external_xres_virtual;
2287 myvar->yres = external_yres;
2288 myvar->bits_per_pixel = external_depth;
2289 ext_encode_var(myvar, &dummy_par);
2290 return 1;
2291 }
2292
2293 #endif /* ATAFB_EXT */
2294
2295 /* ------ This is the same for most hardware types -------- */
2296
set_screen_base(void * s_base)2297 static void set_screen_base(void *s_base)
2298 {
2299 unsigned long addr;
2300 addr= virt_to_phys(s_base);
2301 /* Setup Screen Memory */
2302 shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2303 shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2304 shifter.bas_lo=(unsigned char) (addr & 0x0000ff);
2305 }
2306
2307
pan_display(struct fb_var_screeninfo * var,struct atafb_par * par)2308 static int pan_display( struct fb_var_screeninfo *var,
2309 struct atafb_par *par )
2310 {
2311 if (!fbhw->set_screen_base ||
2312 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2313 return -EINVAL;
2314 var->xoffset = up(var->xoffset, 16);
2315 par->screen_base = screen_base +
2316 (var->yoffset * fb_display[currcon].var.xres_virtual + var->xoffset)
2317 * fb_display[currcon].var.bits_per_pixel / 8;
2318 fbhw->set_screen_base (par->screen_base);
2319 return 0;
2320 }
2321
2322
2323 /* ------------ Interfaces to hardware functions ------------ */
2324
2325
2326 #ifdef ATAFB_TT
2327 static struct fb_hwswitch tt_switch = {
2328 tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
2329 tt_get_par, tt_set_par, tt_getcolreg, tt_setcolreg,
2330 set_screen_base, NULL, pan_display
2331 };
2332 #endif
2333
2334 #ifdef ATAFB_FALCON
2335 static struct fb_hwswitch falcon_switch = {
2336 falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
2337 falcon_get_par, falcon_set_par, falcon_getcolreg,
2338 falcon_setcolreg, set_screen_base, falcon_blank, falcon_pan_display
2339 };
2340 #endif
2341
2342 #ifdef ATAFB_STE
2343 static struct fb_hwswitch st_switch = {
2344 stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
2345 stste_get_par, stste_set_par, stste_getcolreg, stste_setcolreg,
2346 stste_set_screen_base, NULL, pan_display
2347 };
2348 #endif
2349
2350 #ifdef ATAFB_EXT
2351 static struct fb_hwswitch ext_switch = {
2352 ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
2353 ext_get_par, ext_set_par, ext_getcolreg, ext_setcolreg, NULL, NULL, NULL
2354 };
2355 #endif
2356
2357
2358
atafb_get_par(struct atafb_par * par)2359 static void atafb_get_par( struct atafb_par *par )
2360 {
2361 if (current_par_valid) {
2362 *par=current_par;
2363 }
2364 else
2365 fbhw->get_par(par);
2366 }
2367
2368
atafb_set_par(struct atafb_par * par)2369 static void atafb_set_par( struct atafb_par *par )
2370 {
2371 fbhw->set_par(par);
2372 current_par=*par;
2373 current_par_valid=1;
2374 }
2375
2376
2377
2378 /* =========================================================== */
2379 /* ============== Hardware Independent Functions ============= */
2380 /* =========================================================== */
2381
2382
2383 /* used for hardware scrolling */
2384
2385 static int
fb_update_var(int con,struct fb_info * info)2386 fb_update_var(int con, struct fb_info *info)
2387 {
2388 int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual*
2389 fb_display[con].var.bits_per_pixel>>3;
2390
2391 current_par.screen_base=screen_base + off;
2392
2393 if (fbhw->set_screen_base)
2394 fbhw->set_screen_base(current_par.screen_base);
2395 return 0;
2396 }
2397
2398 static int
do_fb_set_var(struct fb_var_screeninfo * var,int isactive)2399 do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2400 {
2401 int err,activate;
2402 struct atafb_par par;
2403 if ((err=fbhw->decode_var(var, &par)))
2404 return err;
2405 activate=var->activate;
2406 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2407 atafb_set_par(&par);
2408 fbhw->encode_var(var, &par);
2409 var->activate=activate;
2410 return 0;
2411 }
2412
2413 /* Functions for handling colormap */
2414
2415 static void
do_install_cmap(int con,struct fb_info * info)2416 do_install_cmap(int con, struct fb_info *info)
2417 {
2418 if (con != currcon)
2419 return;
2420 if (fb_display[con].cmap.len)
2421 fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
2422 else
2423 fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
2424 1, fbhw->setcolreg, info);
2425 }
2426
2427 static int
atafb_get_fix(struct fb_fix_screeninfo * fix,int con,struct fb_info * info)2428 atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
2429 {
2430 struct atafb_par par;
2431 if (con == -1)
2432 atafb_get_par(&par);
2433 else {
2434 int err;
2435 if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
2436 return err;
2437 }
2438 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2439 return fbhw->encode_fix(fix, &par);
2440 }
2441
2442 static int
atafb_get_var(struct fb_var_screeninfo * var,int con,struct fb_info * info)2443 atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2444 {
2445 struct atafb_par par;
2446 if (con == -1) {
2447 atafb_get_par(&par);
2448 fbhw->encode_var(var, &par);
2449 }
2450 else
2451 *var=fb_display[con].var;
2452 return 0;
2453 }
2454
2455 static void
atafb_set_disp(int con,struct fb_info * info)2456 atafb_set_disp(int con, struct fb_info *info)
2457 {
2458 struct fb_fix_screeninfo fix;
2459 struct fb_var_screeninfo var;
2460 struct display *display;
2461
2462 if (con >= 0)
2463 display = &fb_display[con];
2464 else
2465 display = &disp; /* used during initialization */
2466
2467 atafb_get_fix(&fix, con, info);
2468 atafb_get_var(&var, con, info);
2469 if (con == -1)
2470 con=0;
2471 display->screen_base = (void *)fix.smem_start;
2472 display->visual = fix.visual;
2473 display->type = fix.type;
2474 display->type_aux = fix.type_aux;
2475 display->ypanstep = fix.ypanstep;
2476 display->ywrapstep = fix.ywrapstep;
2477 display->line_length = fix.line_length;
2478 if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
2479 fix.visual != FB_VISUAL_DIRECTCOLOR)
2480 display->can_soft_blank = 0;
2481 else
2482 display->can_soft_blank = 1;
2483 display->inverse =
2484 (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
2485 switch (fix.type) {
2486 case FB_TYPE_INTERLEAVED_PLANES:
2487 switch (var.bits_per_pixel) {
2488 #ifdef FBCON_HAS_IPLAN2P2
2489 case 2:
2490 display->dispsw = &fbcon_iplan2p2;
2491 break;
2492 #endif
2493 #ifdef FBCON_HAS_IPLAN2P4
2494 case 4:
2495 display->dispsw = &fbcon_iplan2p4;
2496 break;
2497 #endif
2498 #ifdef FBCON_HAS_IPLAN2P8
2499 case 8:
2500 display->dispsw = &fbcon_iplan2p8;
2501 break;
2502 #endif
2503 }
2504 break;
2505 case FB_TYPE_PACKED_PIXELS:
2506 switch (var.bits_per_pixel) {
2507 #ifdef FBCON_HAS_MFB
2508 case 1:
2509 display->dispsw = &fbcon_mfb;
2510 break;
2511 #endif
2512 #ifdef FBCON_HAS_CFB8
2513 case 8:
2514 display->dispsw = &fbcon_cfb8;
2515 break;
2516 #endif
2517 #ifdef FBCON_HAS_CFB16
2518 case 16:
2519 display->dispsw = &fbcon_cfb16;
2520 display->dispsw_data = fbcon_cfb16_cmap;
2521 break;
2522 #endif
2523 }
2524 break;
2525 }
2526 }
2527
2528 static int
atafb_set_var(struct fb_var_screeninfo * var,int con,struct fb_info * info)2529 atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2530 {
2531 int err,oldxres,oldyres,oldbpp,oldxres_virtual,
2532 oldyres_virtual,oldyoffset;
2533 if ((err=do_fb_set_var(var, con==currcon)))
2534 return err;
2535 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2536 oldxres=fb_display[con].var.xres;
2537 oldyres=fb_display[con].var.yres;
2538 oldxres_virtual=fb_display[con].var.xres_virtual;
2539 oldyres_virtual=fb_display[con].var.yres_virtual;
2540 oldbpp=fb_display[con].var.bits_per_pixel;
2541 oldyoffset=fb_display[con].var.yoffset;
2542 fb_display[con].var=*var;
2543 if (oldxres != var->xres || oldyres != var->yres
2544 || oldxres_virtual != var->xres_virtual
2545 || oldyres_virtual != var->yres_virtual
2546 || oldbpp != var->bits_per_pixel
2547 || oldyoffset != var->yoffset) {
2548 atafb_set_disp(con, info);
2549 (*fb_info.changevar)(con);
2550 fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
2551 do_install_cmap(con, info);
2552 }
2553 }
2554 var->activate=0;
2555 return 0;
2556 }
2557
2558
2559
2560 static int
atafb_get_cmap(struct fb_cmap * cmap,int kspc,int con,struct fb_info * info)2561 atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
2562 {
2563 if (con == currcon) /* current console ? */
2564 return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
2565 else
2566 if (fb_display[con].cmap.len) /* non default colormap ? */
2567 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
2568 else
2569 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
2570 cmap, kspc ? 0 : 2);
2571 return 0;
2572 }
2573
2574 static int
atafb_set_cmap(struct fb_cmap * cmap,int kspc,int con,struct fb_info * info)2575 atafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
2576 {
2577 int err;
2578 if (! fb_display[con].cmap.len) { /* no colormap allocated ? */
2579 if ((err = fb_alloc_cmap(&fb_display[con].cmap,
2580 1 << fb_display[con].var.bits_per_pixel,
2581 0)))
2582 return err;
2583 }
2584 if (con == currcon) /* current console ? */
2585 return fb_set_cmap(cmap, kspc, fbhw->setcolreg, info);
2586 else
2587 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
2588 return 0;
2589 }
2590
2591 static int
atafb_pan_display(struct fb_var_screeninfo * var,int con,struct fb_info * info)2592 atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2593 {
2594 int xoffset = var->xoffset;
2595 int yoffset = var->yoffset;
2596 int err;
2597
2598 if ( xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
2599 || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
2600 return -EINVAL;
2601
2602 if (con == currcon) {
2603 if (fbhw->pan_display) {
2604 if ((err = fbhw->pan_display(var, ¤t_par)))
2605 return err;
2606 }
2607 else
2608 return -EINVAL;
2609 }
2610 fb_display[con].var.xoffset = var->xoffset;
2611 fb_display[con].var.yoffset = var->yoffset;
2612 return 0;
2613 }
2614
2615 static int
atafb_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg,int con,struct fb_info * info)2616 atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2617 unsigned long arg, int con, struct fb_info *info)
2618 {
2619 switch (cmd) {
2620 #ifdef FBCMD_GET_CURRENTPAR
2621 case FBCMD_GET_CURRENTPAR:
2622 if (copy_to_user((void *)arg, (void *)¤t_par,
2623 sizeof(struct atafb_par)))
2624 return -EFAULT;
2625 return 0;
2626 #endif
2627 #ifdef FBCMD_SET_CURRENTPAR
2628 case FBCMD_SET_CURRENTPAR:
2629 if (copy_from_user((void *)¤t_par, (void *)arg,
2630 sizeof(struct atafb_par)))
2631 return -EFAULT;
2632 atafb_set_par(¤t_par);
2633 return 0;
2634 #endif
2635 }
2636 return -EINVAL;
2637 }
2638
2639 static struct fb_ops atafb_ops = {
2640 owner: THIS_MODULE,
2641 fb_get_fix: atafb_get_fix,
2642 fb_get_var: atafb_get_var,
2643 fb_set_var: atafb_set_var,
2644 fb_get_cmap: atafb_get_cmap,
2645 fb_set_cmap: atafb_set_cmap,
2646 fb_pan_display: atafb_pan_display,
2647 fb_ioctl: atafb_ioctl,
2648 };
2649
2650 static void
check_default_par(int detected_mode)2651 check_default_par( int detected_mode )
2652 {
2653 char default_name[10];
2654 int i;
2655 struct fb_var_screeninfo var;
2656 unsigned long min_mem;
2657
2658 /* First try the user supplied mode */
2659 if (default_par) {
2660 var=atafb_predefined[default_par-1];
2661 var.activate = FB_ACTIVATE_TEST;
2662 if (do_fb_set_var(&var,1))
2663 default_par=0; /* failed */
2664 }
2665 /* Next is the autodetected one */
2666 if (! default_par) {
2667 var=atafb_predefined[detected_mode-1]; /* autodetect */
2668 var.activate = FB_ACTIVATE_TEST;
2669 if (!do_fb_set_var(&var,1))
2670 default_par=detected_mode;
2671 }
2672 /* If that also failed, try some default modes... */
2673 if (! default_par) {
2674 /* try default1, default2... */
2675 for (i=1 ; i < 10 ; i++) {
2676 sprintf(default_name,"default%d",i);
2677 default_par=get_video_mode(default_name);
2678 if (! default_par)
2679 panic("can't set default video mode");
2680 var=atafb_predefined[default_par-1];
2681 var.activate = FB_ACTIVATE_TEST;
2682 if (! do_fb_set_var(&var,1))
2683 break; /* ok */
2684 }
2685 }
2686 min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
2687 if (default_mem_req < min_mem)
2688 default_mem_req=min_mem;
2689 }
2690
2691 static int
atafb_switch(int con,struct fb_info * info)2692 atafb_switch(int con, struct fb_info *info)
2693 {
2694 /* Do we have to save the colormap ? */
2695 if (fb_display[currcon].cmap.len)
2696 fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
2697 info);
2698 do_fb_set_var(&fb_display[con].var,1);
2699 currcon=con;
2700 /* Install new colormap */
2701 do_install_cmap(con, info);
2702 return 0;
2703 }
2704
2705 /* (un)blank/poweroff
2706 * 0 = unblank
2707 * 1 = blank
2708 * 2 = suspend vsync
2709 * 3 = suspend hsync
2710 * 4 = off
2711 */
2712 static void
atafb_blank(int blank,struct fb_info * info)2713 atafb_blank(int blank, struct fb_info *info)
2714 {
2715 unsigned short black[16];
2716 struct fb_cmap cmap;
2717 if (fbhw->blank && !fbhw->blank(blank))
2718 return;
2719 if (blank) {
2720 memset(black, 0, 16*sizeof(unsigned short));
2721 cmap.red=black;
2722 cmap.green=black;
2723 cmap.blue=black;
2724 cmap.transp=NULL;
2725 cmap.start=0;
2726 cmap.len=16;
2727 fb_set_cmap(&cmap, 1, fbhw->setcolreg, info);
2728 }
2729 else
2730 do_install_cmap(currcon, info);
2731 }
2732
atafb_init(void)2733 int __init atafb_init(void)
2734 {
2735 int pad;
2736 int detected_mode;
2737 unsigned long mem_req;
2738
2739 if (!MACH_IS_ATARI)
2740 return -ENXIO;
2741
2742 do {
2743 #ifdef ATAFB_EXT
2744 if (external_addr) {
2745 fbhw = &ext_switch;
2746 break;
2747 }
2748 #endif
2749 #ifdef ATAFB_TT
2750 if (ATARIHW_PRESENT(TT_SHIFTER)) {
2751 fbhw = &tt_switch;
2752 break;
2753 }
2754 #endif
2755 #ifdef ATAFB_FALCON
2756 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
2757 fbhw = &falcon_switch;
2758 request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
2759 "framebuffer/modeswitch", falcon_vbl_switcher);
2760 break;
2761 }
2762 #endif
2763 #ifdef ATAFB_STE
2764 if (ATARIHW_PRESENT(STND_SHIFTER) ||
2765 ATARIHW_PRESENT(EXTD_SHIFTER)) {
2766 fbhw = &st_switch;
2767 break;
2768 }
2769 fbhw = &st_switch;
2770 printk("Cannot determine video hardware; defaulting to ST(e)\n");
2771 #else /* ATAFB_STE */
2772 /* no default driver included */
2773 /* Nobody will ever see this message :-) */
2774 panic("Cannot initialize video hardware");
2775 #endif
2776 } while (0);
2777
2778 /* Multisync monitor capabilities */
2779 /* Atari-TOS defaults if no boot option present */
2780 if (fb_info.monspecs.hfmin == 0) {
2781 fb_info.monspecs.hfmin = 31000;
2782 fb_info.monspecs.hfmax = 32000;
2783 fb_info.monspecs.vfmin = 58;
2784 fb_info.monspecs.vfmax = 62;
2785 }
2786
2787 detected_mode = fbhw->detect();
2788 check_default_par(detected_mode);
2789 #ifdef ATAFB_EXT
2790 if (!external_addr) {
2791 #endif /* ATAFB_EXT */
2792 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
2793 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
2794 screen_base = atari_stram_alloc(mem_req, "atafb");
2795 if (!screen_base)
2796 panic("Cannot allocate screen memory");
2797 memset(screen_base, 0, mem_req);
2798 pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
2799 screen_base+=pad;
2800 real_screen_base=screen_base+ovsc_offset;
2801 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
2802 st_ovsc_switch();
2803 if (CPU_IS_040_OR_060) {
2804 /* On a '040+, the cache mode of video RAM must be set to
2805 * write-through also for internal video hardware! */
2806 cache_push(virt_to_phys(screen_base), screen_len);
2807 kernel_set_cachemode(screen_base, screen_len,
2808 IOMAP_WRITETHROUGH);
2809 }
2810 #ifdef ATAFB_EXT
2811 }
2812 else {
2813 /* Map the video memory (physical address given) to somewhere
2814 * in the kernel address space.
2815 */
2816 external_addr =
2817 ioremap_writethrough((unsigned long)external_addr,
2818 external_len);
2819 if (external_vgaiobase)
2820 external_vgaiobase =
2821 (unsigned long)ioremap(external_vgaiobase, 0x10000);
2822 screen_base =
2823 real_screen_base = external_addr;
2824 screen_len = external_len & PAGE_MASK;
2825 memset (screen_base, 0, external_len);
2826 }
2827 #endif /* ATAFB_EXT */
2828
2829 strcpy(fb_info.modename, "Atari Builtin ");
2830 fb_info.changevar = NULL;
2831 fb_info.node = -1;
2832 fb_info.fbops = &atafb_ops;
2833 fb_info.disp = &disp;
2834 fb_info.switch_con = &atafb_switch;
2835 fb_info.updatevar = &fb_update_var;
2836 fb_info.blank = &atafb_blank;
2837 fb_info.flags = FBINFO_FLAG_DEFAULT;
2838 do_fb_set_var(&atafb_predefined[default_par-1], 1);
2839 strcat(fb_info.modename, fb_var_names[default_par-1][0]);
2840
2841 atafb_get_var(&disp.var, -1, &fb_info);
2842 atafb_set_disp(-1, &fb_info);
2843 do_install_cmap(0, &fb_info);
2844
2845 if (register_framebuffer(&fb_info) < 0)
2846 return -EINVAL;
2847
2848 printk("Determined %dx%d, depth %d\n",
2849 disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
2850 if ((disp.var.xres != disp.var.xres_virtual) ||
2851 (disp.var.yres != disp.var.yres_virtual))
2852 printk(" virtual %dx%d\n",
2853 disp.var.xres_virtual, disp.var.yres_virtual);
2854 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2855 GET_FB_IDX(fb_info.node), fb_info.modename, screen_len>>10);
2856
2857 /* TODO: This driver cannot be unloaded yet */
2858 MOD_INC_USE_COUNT;
2859
2860 return 0;
2861 }
2862
2863 /* a strtok which returns empty strings, too */
2864
strtoke(char * s,const char * ct)2865 static char * strtoke(char * s,const char * ct)
2866 {
2867 char *sbegin, *send;
2868 static char *ssave = NULL;
2869
2870 sbegin = s ? s : ssave;
2871 if (!sbegin) {
2872 return NULL;
2873 }
2874 if (*sbegin == '\0') {
2875 ssave = NULL;
2876 return NULL;
2877 }
2878 send = strpbrk(sbegin, ct);
2879 if (send && *send != '\0')
2880 *send++ = '\0';
2881 ssave = send;
2882 return sbegin;
2883 }
2884
atafb_setup(char * options)2885 int __init atafb_setup( char *options )
2886 {
2887 char *this_opt;
2888 int temp;
2889 char ext_str[80], int_str[100];
2890 char mcap_spec[80];
2891 char user_mode[80];
2892
2893 ext_str[0] =
2894 int_str[0] =
2895 mcap_spec[0] =
2896 user_mode[0] =
2897 fb_info.fontname[0] = '\0';
2898
2899 if (!options || !*options)
2900 return 0;
2901
2902 for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
2903 if (!*this_opt) continue;
2904 if ((temp=get_video_mode(this_opt)))
2905 default_par=temp;
2906 else if (! strcmp(this_opt, "inverse"))
2907 inverse=1;
2908 else if (!strncmp(this_opt, "font:", 5))
2909 strcpy(fb_info.fontname, this_opt+5);
2910 else if (! strncmp(this_opt, "hwscroll_",9)) {
2911 hwscroll=simple_strtoul(this_opt+9, NULL, 10);
2912 if (hwscroll < 0)
2913 hwscroll = 0;
2914 if (hwscroll > 200)
2915 hwscroll = 200;
2916 }
2917 #ifdef ATAFB_EXT
2918 else if (!strcmp(this_opt,"mv300")) {
2919 external_bitspercol = 8;
2920 external_card_type = IS_MV300;
2921 }
2922 else if (!strncmp(this_opt,"external:",9))
2923 strcpy(ext_str, this_opt+9);
2924 #endif
2925 else if (!strncmp(this_opt,"internal:",9))
2926 strcpy(int_str, this_opt+9);
2927 #ifdef ATAFB_FALCON
2928 else if (!strncmp(this_opt, "eclock:", 7)) {
2929 fext.f = simple_strtoul(this_opt+7, NULL, 10);
2930 /* external pixelclock in kHz --> ps */
2931 fext.t = 1000000000/fext.f;
2932 fext.f *= 1000;
2933 }
2934 else if (!strncmp(this_opt, "monitorcap:", 11))
2935 strcpy(mcap_spec, this_opt+11);
2936 #endif
2937 else if (!strcmp(this_opt, "keep"))
2938 DontCalcRes = 1;
2939 else if (!strncmp(this_opt, "R", 1))
2940 strcpy(user_mode, this_opt+1);
2941 }
2942
2943 if (*int_str) {
2944 /* Format to config extended internal video hardware like OverScan:
2945 "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2946 Explanation:
2947 <xres>: x-resolution
2948 <yres>: y-resolution
2949 The following are only needed if you have an overscan which
2950 needs a black border:
2951 <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2952 <yres_max>: max. number of lines your OverScan hardware would allow
2953 <offset>: Offset from physical beginning to visible beginning
2954 of screen in bytes
2955 */
2956 int xres;
2957 char *p;
2958
2959 if (!(p = strtoke(int_str, ";")) ||!*p) goto int_invalid;
2960 xres = simple_strtoul(p, NULL, 10);
2961 if (!(p = strtoke(NULL, ";")) || !*p) goto int_invalid;
2962 sttt_xres=xres;
2963 tt_yres=st_yres=simple_strtoul(p, NULL, 10);
2964 if ((p=strtoke(NULL, ";")) && *p) {
2965 sttt_xres_virtual=simple_strtoul(p, NULL, 10);
2966 }
2967 if ((p=strtoke(NULL, ";")) && *p) {
2968 sttt_yres_virtual=simple_strtoul(p, NULL, 0);
2969 }
2970 if ((p=strtoke(NULL, ";")) && *p) {
2971 ovsc_offset=simple_strtoul(p, NULL, 0);
2972 }
2973
2974 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2975 use_hwscroll=0;
2976 int_invalid:
2977 ;
2978 }
2979
2980 #ifdef ATAFB_EXT
2981 if (*ext_str) {
2982 int xres, xres_virtual, yres, depth, planes;
2983 unsigned long addr, len;
2984 char *p;
2985
2986 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2987 * <screen mem addr>
2988 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2989 * [;<xres-virtual>]]]]]
2990 *
2991 * 09/23/97 Juergen
2992 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2993 *
2994 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2995 */
2996 if (!(p = strtoke(ext_str, ";")) ||!*p) goto ext_invalid;
2997 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2998 if (xres <= 0) goto ext_invalid;
2999
3000 if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3001 yres = simple_strtoul(p, NULL, 10);
3002 if (yres <= 0) goto ext_invalid;
3003
3004 if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3005 depth = simple_strtoul(p, NULL, 10);
3006 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
3007 depth != 16 && depth != 24) goto ext_invalid;
3008
3009 if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3010 if (*p == 'i')
3011 planes = FB_TYPE_INTERLEAVED_PLANES;
3012 else if (*p == 'p')
3013 planes = FB_TYPE_PACKED_PIXELS;
3014 else if (*p == 'n')
3015 planes = FB_TYPE_PLANES;
3016 else if (*p == 't')
3017 planes = -1; /* true color */
3018 else
3019 goto ext_invalid;
3020
3021
3022 if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3023 addr = simple_strtoul(p, NULL, 0);
3024
3025 if (!(p = strtoke(NULL, ";")) ||!*p)
3026 len = xres*yres*depth/8;
3027 else
3028 len = simple_strtoul(p, NULL, 0);
3029
3030 if ((p = strtoke(NULL, ";")) && *p) {
3031 external_vgaiobase=simple_strtoul(p, NULL, 0);
3032 }
3033
3034 if ((p = strtoke(NULL, ";")) && *p) {
3035 external_bitspercol = simple_strtoul(p, NULL, 0);
3036 if (external_bitspercol > 8)
3037 external_bitspercol = 8;
3038 else if (external_bitspercol < 1)
3039 external_bitspercol = 1;
3040 }
3041
3042 if ((p = strtoke(NULL, ";")) && *p) {
3043 if (!strcmp(p, "vga"))
3044 external_card_type = IS_VGA;
3045 if (!strcmp(p, "mv300"))
3046 external_card_type = IS_MV300;
3047 }
3048
3049 if ((p = strtoke(NULL, ";")) && *p) {
3050 xres_virtual = simple_strtoul(p, NULL, 10);
3051 if (xres_virtual < xres)
3052 xres_virtual = xres;
3053 if (xres_virtual*yres*depth/8 > len)
3054 len=xres_virtual*yres*depth/8;
3055 }
3056
3057 external_xres = xres;
3058 external_xres_virtual = xres_virtual;
3059 external_yres = yres;
3060 external_depth = depth;
3061 external_pmode = planes;
3062 external_addr = (void *)addr;
3063 external_len = len;
3064
3065 if (external_card_type == IS_MV300)
3066 switch (external_depth) {
3067 case 1:
3068 MV300_reg = MV300_reg_1bit;
3069 break;
3070 case 4:
3071 MV300_reg = MV300_reg_4bit;
3072 break;
3073 case 8:
3074 MV300_reg = MV300_reg_8bit;
3075 break;
3076 }
3077
3078 ext_invalid:
3079 ;
3080 }
3081 #endif /* ATAFB_EXT */
3082
3083 #ifdef ATAFB_FALCON
3084 if (*mcap_spec) {
3085 char *p;
3086 int vmin, vmax, hmin, hmax;
3087
3088 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
3089 * <V*> vertical freq. in Hz
3090 * <H*> horizontal freq. in kHz
3091 */
3092 if (!(p = strtoke(mcap_spec, ";")) || !*p) goto cap_invalid;
3093 vmin = simple_strtoul(p, NULL, 10);
3094 if (vmin <= 0) goto cap_invalid;
3095 if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
3096 vmax = simple_strtoul(p, NULL, 10);
3097 if (vmax <= 0 || vmax <= vmin) goto cap_invalid;
3098 if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
3099 hmin = 1000 * simple_strtoul(p, NULL, 10);
3100 if (hmin <= 0) goto cap_invalid;
3101 if (!(p = strtoke(NULL, "")) || !*p) goto cap_invalid;
3102 hmax = 1000 * simple_strtoul(p, NULL, 10);
3103 if (hmax <= 0 || hmax <= hmin) goto cap_invalid;
3104
3105 fb_info.monspecs.vfmin = vmin;
3106 fb_info.monspecs.vfmax = vmax;
3107 fb_info.monspecs.hfmin = hmin;
3108 fb_info.monspecs.hfmax = hmax;
3109 cap_invalid:
3110 ;
3111 }
3112 #endif
3113
3114 if (*user_mode) {
3115 /* Format of user defined video mode is: <xres>;<yres>;<depth>
3116 */
3117 char *p;
3118 int xres, yres, depth, temp;
3119
3120 if (!(p = strtoke(user_mode, ";")) || !*p) goto user_invalid;
3121 xres = simple_strtoul(p, NULL, 10);
3122 if (!(p = strtoke(NULL, ";")) || !*p) goto user_invalid;
3123 yres = simple_strtoul(p, NULL, 10);
3124 if (!(p = strtoke(NULL, "")) || !*p) goto user_invalid;
3125 depth = simple_strtoul(p, NULL, 10);
3126 if ((temp=get_video_mode("user0"))) {
3127 default_par=temp;
3128 atafb_predefined[default_par-1].xres = xres;
3129 atafb_predefined[default_par-1].yres = yres;
3130 atafb_predefined[default_par-1].bits_per_pixel = depth;
3131 }
3132
3133 user_invalid:
3134 ;
3135 }
3136 return 0;
3137 }
3138
3139 #ifdef MODULE
3140 MODULE_LICENSE("GPL");
3141
init_module(void)3142 int init_module(void)
3143 {
3144 return atafb_init();
3145 }
3146
cleanup_module(void)3147 void cleanup_module(void)
3148 {
3149 /* Not reached because the usecount will never
3150 be decremented to zero */
3151 unregister_framebuffer(&fb_info);
3152 /* atari_stram_free( screen_base ); */
3153 /* TODO: further clean up ... */
3154 }
3155 #endif /* MODULE */
3156