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