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