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