2 * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
4 * Copyright (C) 1994 Martin Schaller & Roman Hodek
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
11 * - 03 Jan 95: Original version by Martin Schaller: The TT driver and
12 * all the device independent stuff
13 * - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
14 * and wrote the Falcon, ST(E), and External drivers
15 * based on the original TT driver.
16 * - 07 May 95: Martin: Added colormap operations for the external driver
17 * - 21 May 95: Martin: Added support for overscan
18 * Andreas: some bug fixes for this
19 * - Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
20 * Programmable Falcon video modes
21 * (thanks to Christian Cartus for documentation
22 * of VIDEL registers).
23 * - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
24 * on minor 24...31. "user0" may be set on commandline by
25 * "R<x>;<y>;<depth>". (Makes sense only on Falcon)
26 * Video mode switch on Falcon now done at next VBL interrupt
27 * to avoid the annoying right shift of the screen.
28 * - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
29 * The external-part is legacy, therefore hardware-specific
30 * functions like panning/hardwarescrolling/blanking isn't
32 * - 29 Sep 97: Juergen: added Romans suggestion for pan_display
33 * (var->xoffset was changed even if no set_screen_base avail.)
34 * - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
35 * we know how to set the colors
36 * ext_*palette: read from ext_colors (former MV300_colors)
37 * write to ext_colors and RAMDAC
40 * - For the Falcon it is not possible to set random video modes on
41 * SM124 and SC/TV, only the bootup resolution is supported.
50 #include <linux/kernel.h>
51 #include <linux/errno.h>
52 #include <linux/string.h>
54 #include <linux/delay.h>
55 #include <linux/init.h>
56 #include <linux/interrupt.h>
57 #include <linux/platform_device.h>
59 #include <asm/setup.h>
60 #include <linux/uaccess.h>
64 #include <asm/atarihw.h>
65 #include <asm/atariints.h>
66 #include <asm/atari_stram.h>
69 #include <asm/atarikb.h>
74 #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
75 #define SWITCH_SND6 0x40
76 #define SWITCH_SND7 0x80
77 #define SWITCH_NONE 0x00
79 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
82 static int default_par; /* default resolution (0=none) */
84 static unsigned long default_mem_req;
86 static int hwscroll = -1;
88 static int use_hwscroll = 1;
90 static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
91 static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
92 static int ovsc_offset, ovsc_addlen;
95 * Hardware parameters for current mode
98 static struct atafb_par {
102 #if defined ATAFB_TT || defined ATAFB_STE
111 /* Here are fields for storing a video mode, as direct
112 * parameters for the hardware.
122 short hht, hbb, hbe, hdb, hde, hss;
123 short vft, vbb, vbe, vdb, vde, vss;
124 /* auxiliary information */
128 u32 pseudo_palette[16];
131 /* Nothing needed for external mode */
135 /* Don't calculate an own resolution, and thus don't change the one found when
136 * booting (currently used for the Falcon to keep settings for internal video
137 * hardware extensions (e.g. ScreenBlaster) */
138 static int DontCalcRes = 0;
141 #define HHT hw.falcon.hht
142 #define HBB hw.falcon.hbb
143 #define HBE hw.falcon.hbe
144 #define HDB hw.falcon.hdb
145 #define HDE hw.falcon.hde
146 #define HSS hw.falcon.hss
147 #define VFT hw.falcon.vft
148 #define VBB hw.falcon.vbb
149 #define VBE hw.falcon.vbe
150 #define VDB hw.falcon.vdb
151 #define VDE hw.falcon.vde
152 #define VSS hw.falcon.vss
153 #define VCO_CLOCK25 0x04
154 #define VCO_CSYPOS 0x10
155 #define VCO_VSYPOS 0x20
156 #define VCO_HSYPOS 0x40
157 #define VCO_SHORTOFFS 0x100
158 #define VMO_DOUBLE 0x01
159 #define VMO_INTER 0x02
160 #define VMO_PREMASK 0x0c
163 static struct fb_info fb_info = {
166 .visual = FB_VISUAL_PSEUDOCOLOR,
167 .accel = FB_ACCEL_NONE,
171 static void *screen_base; /* base address of screen */
172 static unsigned long phys_screen_base; /* (only for Overscan) */
174 static int screen_len;
176 static int current_par_valid;
178 static int mono_moni;
183 /* external video handling */
184 static unsigned int external_xres;
185 static unsigned int external_xres_virtual;
186 static unsigned int external_yres;
189 * not needed - atafb will never support panning/hardwarescroll with external
190 * static unsigned int external_yres_virtual;
192 static unsigned int external_depth;
193 static int external_pmode;
194 static void *external_screen_base;
195 static unsigned long external_addr;
196 static unsigned long external_len;
197 static unsigned long external_vgaiobase;
198 static unsigned int external_bitspercol = 6;
201 * JOE <joe@amber.dinoco.de>:
202 * added card type for external driver, is only needed for
205 enum cardtype { IS_VGA, IS_MV300 };
206 static enum cardtype external_card_type = IS_VGA;
209 * The MV300 mixes the color registers. So we need an array of munged
210 * indices in order to access the correct reg.
212 static int MV300_reg_1bit[2] = {
215 static int MV300_reg_4bit[16] = {
216 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
218 static int MV300_reg_8bit[256] = {
219 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
220 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
221 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
222 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
223 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
224 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
225 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
226 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
227 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
228 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
229 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
230 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
231 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
232 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
233 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
234 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
237 static int *MV300_reg = MV300_reg_8bit;
238 #endif /* ATAFB_EXT */
243 extern int fontheight_8x8;
244 extern int fontwidth_8x8;
245 extern unsigned char fontdata_8x8[];
247 extern int fontheight_8x16;
248 extern int fontwidth_8x16;
249 extern unsigned char fontdata_8x16[];
253 * * open/release and usage marking
254 * struct module *owner;
255 * int (*fb_open)(struct fb_info *info, int user);
256 * int (*fb_release)(struct fb_info *info, int user);
258 * * For framebuffers with strange non linear layouts or that do not
259 * * work with normal memory mapped access
260 * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
261 * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
263 * * checks var and eventually tweaks it to something supported,
264 * * DOES NOT MODIFY PAR *
265 * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
267 * * set the video mode according to info->var *
268 * int (*fb_set_par)(struct fb_info *info);
270 * * set color register *
271 * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
272 * unsigned int blue, unsigned int transp, struct fb_info *info);
274 * * set color registers in batch *
275 * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
278 * int (*fb_blank)(int blank, struct fb_info *info);
281 * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
283 * *** The meat of the drawing engine ***
284 * * Draws a rectangle *
285 * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
286 * * Copy data from area to another *
287 * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
288 * * Draws a image to the display *
289 * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
292 * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
294 * * wait for blit idle, optional *
295 * int (*fb_sync)(struct fb_info *info);
297 * * perform fb specific ioctl (optional) *
298 * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
299 * unsigned long arg);
301 * * Handle 32bit compat ioctl (optional) *
302 * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
303 * unsigned long arg);
305 * * perform fb specific mmap *
306 * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
311 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
314 * int (*detect)(void)
315 * This function should detect the current video mode settings and
316 * store them in atafb_predefined[0] for later reference by the
317 * user. Return the index+1 of an equivalent predefined mode or 0
318 * if there is no such.
320 * int (*encode_fix)(struct fb_fix_screeninfo *fix,
321 * struct atafb_par *par)
322 * This function should fill in the 'fix' structure based on the
323 * values in the 'par' structure.
324 * !!! Obsolete, perhaps !!!
326 * int (*decode_var)(struct fb_var_screeninfo *var,
327 * struct atafb_par *par)
328 * Get the video params out of 'var'. If a value doesn't fit, round
329 * it up, if it's too big, return EINVAL.
330 * Round up in the following order: bits_per_pixel, xres, yres,
331 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
332 * horizontal timing, vertical timing.
334 * int (*encode_var)(struct fb_var_screeninfo *var,
335 * struct atafb_par *par);
336 * Fill the 'var' structure based on the values in 'par' and maybe
337 * other values read out of the hardware.
339 * void (*get_par)(struct atafb_par *par)
340 * Fill the hardware's 'par' structure.
341 * !!! Used only by detect() !!!
343 * void (*set_par)(struct atafb_par *par)
344 * Set the hardware according to 'par'.
346 * void (*set_screen_base)(void *s_base)
347 * Set the base address of the displayed frame buffer. Only called
348 * if yres_virtual > yres or xres_virtual > xres.
350 * int (*blank)(int blank_mode)
351 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
352 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
353 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
354 * doesn't support it. Implements VESA suspend and powerdown modes on
355 * hardware that supports disabling hsync/vsync:
356 * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
359 static struct fb_hwswitch {
361 int (*encode_fix)(struct fb_fix_screeninfo *fix,
362 struct atafb_par *par);
363 int (*decode_var)(struct fb_var_screeninfo *var,
364 struct atafb_par *par);
365 int (*encode_var)(struct fb_var_screeninfo *var,
366 struct atafb_par *par);
367 void (*get_par)(struct atafb_par *par);
368 void (*set_par)(struct atafb_par *par);
369 void (*set_screen_base)(void *s_base);
370 int (*blank)(int blank_mode);
371 int (*pan_display)(struct fb_var_screeninfo *var,
372 struct fb_info *info);
375 static char *autodetect_names[] = { "autodetect", NULL };
376 static char *stlow_names[] = { "stlow", NULL };
377 static char *stmid_names[] = { "stmid", "default5", NULL };
378 static char *sthigh_names[] = { "sthigh", "default4", NULL };
379 static char *ttlow_names[] = { "ttlow", NULL };
380 static char *ttmid_names[] = { "ttmid", "default1", NULL };
381 static char *tthigh_names[] = { "tthigh", "default2", NULL };
382 static char *vga2_names[] = { "vga2", NULL };
383 static char *vga4_names[] = { "vga4", NULL };
384 static char *vga16_names[] = { "vga16", "default3", NULL };
385 static char *vga256_names[] = { "vga256", NULL };
386 static char *falh2_names[] = { "falh2", NULL };
387 static char *falh16_names[] = { "falh16", NULL };
389 static char **fb_var_names[] = {
406 static struct fb_var_screeninfo atafb_predefined[] = {
408 * yres_virtual == 0 means use hw-scrolling if possible, else yres
411 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
412 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
413 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
415 320, 200, 320, 0, 0, 0, 4, 0,
416 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
417 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
419 640, 200, 640, 0, 0, 0, 2, 0,
420 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
421 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
423 640, 400, 640, 0, 0, 0, 1, 0,
424 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
425 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
427 320, 480, 320, 0, 0, 0, 8, 0,
428 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
429 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
431 640, 480, 640, 0, 0, 0, 4, 0,
432 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
433 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
435 1280, 960, 1280, 0, 0, 0, 1, 0,
436 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
437 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
439 640, 480, 640, 0, 0, 0, 1, 0,
440 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
441 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
443 640, 480, 640, 0, 0, 0, 2, 0,
444 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
445 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
447 640, 480, 640, 0, 0, 0, 4, 0,
448 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
449 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
451 640, 480, 640, 0, 0, 0, 8, 0,
452 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
453 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
455 896, 608, 896, 0, 0, 0, 1, 0,
456 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
457 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
459 896, 608, 896, 0, 0, 0, 4, 0,
460 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
461 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
464 static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
466 static struct fb_videomode atafb_modedb[] __initdata = {
470 * If you change these, make sure to update DEFMODE_* as well!
478 /* 320x200, 15 kHz, 60 Hz (ST low) */
479 "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
480 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
482 /* 640x200, 15 kHz, 60 Hz (ST medium) */
483 "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
484 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
486 /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
487 "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
488 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
490 /* 320x480, 15 kHz, 60 Hz (TT low) */
491 "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
492 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
494 /* 640x480, 29 kHz, 57 Hz (TT medium) */
495 "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
496 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
498 /* 1280x960, 29 kHz, 60 Hz (TT high) */
499 "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
500 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
508 /* 640x480, 31 kHz, 60 Hz (VGA) */
509 "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
510 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
512 /* 640x400, 31 kHz, 70 Hz (VGA) */
513 "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
514 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
518 * Falcon HiRes Video Modes
522 /* 896x608, 31 kHz, 60 Hz (Falcon High) */
523 "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
524 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
528 #define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb)
530 static char *mode_option __initdata = NULL;
534 #define DEFMODE_TT 5 /* "tt-high" for TT */
535 #define DEFMODE_F30 7 /* "vga70" for Falcon */
536 #define DEFMODE_STE 2 /* "st-high" for ST/E */
537 #define DEFMODE_EXT 6 /* "vga" for external */
540 static int get_video_mode(char *vname)
546 name_list = fb_var_names;
547 for (i = 0; i < num_atafb_predefined; i++) {
552 if (!strcmp(vname, *name))
562 /* ------------------- TT specific functions ---------------------- */
566 static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
570 strcpy(fix->id, "Atari Builtin");
571 fix->smem_start = phys_screen_base;
572 fix->smem_len = screen_len;
573 fix->type = FB_TYPE_INTERLEAVED_PLANES;
575 fix->visual = FB_VISUAL_PSEUDOCOLOR;
576 mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
577 if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
578 fix->type = FB_TYPE_PACKED_PIXELS;
580 if (mode == TT_SHIFTER_TTHIGH)
581 fix->visual = FB_VISUAL_MONO01;
586 fix->line_length = par->next_line;
587 fix->accel = FB_ACCEL_ATARIBLITT;
591 static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
593 int xres = var->xres;
594 int yres = var->yres;
595 int bpp = var->bits_per_pixel;
597 int yres_virtual = var->yres_virtual;
600 if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
602 par->hw.tt.mode = TT_SHIFTER_TTHIGH;
603 xres = sttt_xres * 2;
607 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
610 if (xres > sttt_xres / 2 || yres > tt_yres)
612 par->hw.tt.mode = TT_SHIFTER_TTLOW;
613 xres = sttt_xres / 2;
616 } else if (bpp > 2) {
617 if (xres > sttt_xres || yres > tt_yres)
619 if (xres > sttt_xres / 2 || yres > st_yres / 2) {
620 par->hw.tt.mode = TT_SHIFTER_TTMID;
625 par->hw.tt.mode = TT_SHIFTER_STLOW;
626 xres = sttt_xres / 2;
630 } else if (bpp > 1) {
631 if (xres > sttt_xres || yres > st_yres / 2)
633 par->hw.tt.mode = TT_SHIFTER_STMID;
637 } else if (var->xres > sttt_xres || var->yres > st_yres) {
640 par->hw.tt.mode = TT_SHIFTER_STHIGH;
646 if (yres_virtual <= 0)
648 else if (yres_virtual < yres)
650 if (var->sync & FB_SYNC_EXT)
654 linelen = xres * bpp / 8;
655 if (yres_virtual * linelen > screen_len && screen_len)
657 if (yres * linelen > screen_len && screen_len)
659 if (var->yoffset + yres > yres_virtual && yres_virtual)
661 par->yres_virtual = yres_virtual;
662 par->screen_base = screen_base + var->yoffset * linelen;
663 par->next_line = linelen;
667 static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
670 memset(var, 0, sizeof(struct fb_var_screeninfo));
673 var->red.msb_right = 0;
676 var->pixclock = 31041;
677 var->left_margin = 120; /* these may be incorrect */
678 var->right_margin = 100;
679 var->upper_margin = 8;
680 var->lower_margin = 16;
681 var->hsync_len = 140;
687 if (par->hw.tt.sync & 1)
690 var->sync = FB_SYNC_EXT;
692 switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
693 case TT_SHIFTER_STLOW:
694 var->xres = sttt_xres / 2;
695 var->xres_virtual = sttt_xres_virtual / 2;
696 var->yres = st_yres / 2;
697 var->bits_per_pixel = 4;
699 case TT_SHIFTER_STMID:
700 var->xres = sttt_xres;
701 var->xres_virtual = sttt_xres_virtual;
702 var->yres = st_yres / 2;
703 var->bits_per_pixel = 2;
705 case TT_SHIFTER_STHIGH:
706 var->xres = sttt_xres;
707 var->xres_virtual = sttt_xres_virtual;
709 var->bits_per_pixel = 1;
711 case TT_SHIFTER_TTLOW:
712 var->xres = sttt_xres / 2;
713 var->xres_virtual = sttt_xres_virtual / 2;
715 var->bits_per_pixel = 8;
717 case TT_SHIFTER_TTMID:
718 var->xres = sttt_xres;
719 var->xres_virtual = sttt_xres_virtual;
721 var->bits_per_pixel = 4;
723 case TT_SHIFTER_TTHIGH:
725 var->xres = sttt_xres * 2;
726 var->xres_virtual = sttt_xres_virtual * 2;
727 var->yres = tt_yres * 2;
728 var->bits_per_pixel = 1;
731 var->blue = var->green = var->red;
732 var->transp.offset = 0;
733 var->transp.length = 0;
734 var->transp.msb_right = 0;
735 linelen = var->xres_virtual * var->bits_per_pixel / 8;
737 var->yres_virtual = var->yres;
738 else if (screen_len) {
739 if (par->yres_virtual)
740 var->yres_virtual = par->yres_virtual;
742 /* yres_virtual == 0 means use maximum */
743 var->yres_virtual = screen_len / linelen;
746 var->yres_virtual = 2 * var->yres;
748 var->yres_virtual = var->yres + hwscroll * 16;
752 var->yoffset = (par->screen_base - screen_base) / linelen;
757 var->vmode = FB_VMODE_NONINTERLACED;
761 static void tt_get_par(struct atafb_par *par)
764 par->hw.tt.mode = shifter_tt.tt_shiftmode;
765 par->hw.tt.sync = shifter_st.syncmode;
766 addr = ((shifter_st.bas_hi & 0xff) << 16) |
767 ((shifter_st.bas_md & 0xff) << 8) |
768 ((shifter_st.bas_lo & 0xff));
769 par->screen_base = atari_stram_to_virt(addr);
772 static void tt_set_par(struct atafb_par *par)
774 shifter_tt.tt_shiftmode = par->hw.tt.mode;
775 shifter_st.syncmode = par->hw.tt.sync;
776 /* only set screen_base if really necessary */
777 if (current_par.screen_base != par->screen_base)
778 fbhw->set_screen_base(par->screen_base);
781 static int tt_setcolreg(unsigned int regno, unsigned int red,
782 unsigned int green, unsigned int blue,
783 unsigned int transp, struct fb_info *info)
785 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
789 tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
791 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
792 TT_SHIFTER_STHIGH && regno == 254)
797 static int tt_detect(void)
799 struct atafb_par par;
801 /* Determine the connected monitor: The DMA sound must be
802 * disabled before reading the MFP GPIP, because the Sound
803 * Done Signal and the Monochrome Detect are XORed together!
805 * Even on a TT, we should look if there is a DMA sound. It was
806 * announced that the Eagle is TT compatible, but only the PCM is
809 if (ATARIHW_PRESENT(PCM_8BIT)) {
810 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
811 udelay(20); /* wait a while for things to settle down */
813 mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
816 tt_encode_var(&atafb_predefined[0], &par);
821 #endif /* ATAFB_TT */
823 /* ------------------- Falcon specific functions ---------------------- */
827 static int mon_type; /* Falcon connected monitor */
828 static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
834 static struct pixel_clock {
835 unsigned long f; /* f/[Hz] */
836 unsigned long t; /* t/[ps] (=1/f) */
837 int right, hsync, left; /* standard timing in clock cycles, not pixel */
838 /* hsync initialized in falcon_detect() */
839 int sync_mask; /* or-mask for hw.falcon.sync to set this clock */
840 int control_mask; /* ditto, for hw.falcon.vid_control */
842 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
844 32000000, 31250, 18, 0, 42, 0x0, 0
846 0, 0, 18, 0, 42, 0x1, 0
849 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
850 static int vdl_prescale[4][3] = {
851 { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
854 /* Default hsync timing [mon_type] in picoseconds */
855 static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
857 static inline int hxx_prescale(struct falcon_hw *hw)
859 return hw->ste_mode ? 16
860 : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
863 static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
864 struct atafb_par *par)
866 strcpy(fix->id, "Atari Builtin");
867 fix->smem_start = phys_screen_base;
868 fix->smem_len = screen_len;
869 fix->type = FB_TYPE_INTERLEAVED_PLANES;
871 fix->visual = FB_VISUAL_PSEUDOCOLOR;
875 if (par->hw.falcon.mono) {
876 fix->type = FB_TYPE_PACKED_PIXELS;
878 /* no smooth scrolling with longword aligned video mem */
880 } else if (par->hw.falcon.f_shift & 0x100) {
881 fix->type = FB_TYPE_PACKED_PIXELS;
883 /* Is this ok or should it be DIRECTCOLOR? */
884 fix->visual = FB_VISUAL_TRUECOLOR;
887 fix->line_length = par->next_line;
888 fix->accel = FB_ACCEL_ATARIBLITT;
892 static int falcon_decode_var(struct fb_var_screeninfo *var,
893 struct atafb_par *par)
895 int bpp = var->bits_per_pixel;
896 int xres = var->xres;
897 int yres = var->yres;
898 int xres_virtual = var->xres_virtual;
899 int yres_virtual = var->yres_virtual;
900 int left_margin, right_margin, hsync_len;
901 int upper_margin, lower_margin, vsync_len;
903 int interlace = 0, doubleline = 0;
904 struct pixel_clock *pclock;
905 int plen; /* width of pixel in clock cycles */
910 int hdb_off, hde_off, base_off;
911 int gstart, gend1, gend2, align;
914 Get the video params out of 'var'. If a value doesn't fit, round
915 it up, if it's too big, return EINVAL.
916 Round up in the following order: bits_per_pixel, xres, yres,
917 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
918 horizontal timing, vertical timing.
920 There is a maximum of screen resolution determined by pixelclock
921 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
922 In interlace mode this is " * " *vfmin <= pixelclock.
923 Additional constraints: hfreq.
924 Frequency range for multisync monitors is given via command line.
925 For TV and SM124 both frequencies are fixed.
927 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
928 Y % 16 == 0 to fit 8x16 font
931 Currently interlace and doubleline mode in var are ignored.
932 On SM124 and TV only the standard resolutions can be used.
935 /* Reject uninitialized mode */
936 if (!xres || !yres || !bpp)
939 if (mon_type == F_MON_SM && bpp != 1)
944 par->hw.falcon.f_shift = 0x400;
945 par->hw.falcon.st_shift = 0x200;
946 } else if (bpp <= 2) {
948 par->hw.falcon.f_shift = 0x000;
949 par->hw.falcon.st_shift = 0x100;
950 } else if (bpp <= 4) {
952 par->hw.falcon.f_shift = 0x000;
953 par->hw.falcon.st_shift = 0x000;
954 } else if (bpp <= 8) {
956 par->hw.falcon.f_shift = 0x010;
957 } else if (bpp <= 16) {
958 bpp = 16; /* packed pixel mode */
959 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
962 par->hw.falcon.bpp = bpp;
964 if (mon_type == F_MON_SM || DontCalcRes) {
965 /* Skip all calculations. VGA/TV/SC1224 only supported. */
966 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
968 if (bpp > myvar->bits_per_pixel ||
969 var->xres > myvar->xres ||
970 var->yres > myvar->yres)
972 fbhw->get_par(par); /* Current par will be new par */
973 goto set_screen_base; /* Don't forget this */
976 /* Only some fixed resolutions < 640x400 */
979 else if (xres <= 640 && bpp != 16)
983 else if (yres <= 240)
985 else if (yres <= 400)
988 /* 2 planes must use STE compatibility mode */
989 par->hw.falcon.ste_mode = bpp == 2;
990 par->hw.falcon.mono = bpp == 1;
992 /* Total and visible scanline length must be a multiple of one longword,
993 * this and the console fontwidth yields the alignment for xres and
995 * TODO: this way "odd" fontheights are not supported
997 * Special case in STE mode: blank and graphic positions don't align,
998 * avoid trash at right margin
1000 if (par->hw.falcon.ste_mode)
1001 xres = (xres + 63) & ~63;
1003 xres = (xres + 31) & ~31;
1005 xres = (xres + 15) & ~15;
1007 yres = (yres + 15) & ~15;
1009 yres = (yres + 7) & ~7;
1011 if (xres_virtual < xres)
1012 xres_virtual = xres;
1014 xres_virtual = (xres_virtual + 31) & ~31;
1016 xres_virtual = (xres_virtual + 15) & ~15;
1018 if (yres_virtual <= 0)
1020 else if (yres_virtual < yres)
1021 yres_virtual = yres;
1023 /* backward bug-compatibility */
1024 if (var->pixclock > 1)
1027 par->hw.falcon.line_width = bpp * xres / 16;
1028 par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
1030 /* single or double pixel width */
1031 xstretch = (xres < 640) ? 2 : 1;
1033 #if 0 /* SM124 supports only 640x400, this is rejected above */
1034 if (mon_type == F_MON_SM) {
1035 if (xres != 640 && yres != 400)
1039 /* SM124-mode is special */
1040 par->hw.falcon.ste_mode = 1;
1041 par->hw.falcon.f_shift = 0x000;
1042 par->hw.falcon.st_shift = 0x200;
1043 left_margin = hsync_len = 128 / plen;
1045 /* TODO set all margins */
1048 if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
1049 plen = 2 * xstretch;
1050 if (var->pixclock > f32.t * plen)
1055 if (var->pixclock == 0) {
1056 /* set some minimal margins which center the screen */
1059 hsync_len = pclock->hsync / plen;
1062 vsync_len = interlace ? 3 : 4;
1064 left_margin = var->left_margin;
1065 right_margin = var->right_margin;
1066 hsync_len = var->hsync_len;
1067 upper_margin = var->upper_margin;
1068 lower_margin = var->lower_margin;
1069 vsync_len = var->vsync_len;
1070 if (var->vmode & FB_VMODE_INTERLACED) {
1071 upper_margin = (upper_margin + 1) / 2;
1072 lower_margin = (lower_margin + 1) / 2;
1073 vsync_len = (vsync_len + 1) / 2;
1074 } else if (var->vmode & FB_VMODE_DOUBLE) {
1080 } else { /* F_MON_VGA */
1082 xstretch = 2; /* Double pixel width only for hicolor */
1083 /* Default values are used for vert./hor. timing if no pixelclock given. */
1084 if (var->pixclock == 0) {
1087 /* Choose master pixelclock depending on hor. timing */
1088 plen = 1 * xstretch;
1089 if ((plen * xres + f25.right + f25.hsync + f25.left) *
1090 fb_info.monspecs.hfmin < f25.f)
1092 else if ((plen * xres + f32.right + f32.hsync +
1093 f32.left) * fb_info.monspecs.hfmin < f32.f)
1095 else if ((plen * xres + fext.right + fext.hsync +
1096 fext.left) * fb_info.monspecs.hfmin < fext.f &&
1102 left_margin = pclock->left / plen;
1103 right_margin = pclock->right / plen;
1104 hsync_len = pclock->hsync / plen;
1105 linesize = left_margin + xres + right_margin + hsync_len;
1110 /* Choose largest pixelclock <= wanted clock */
1112 unsigned long pcl = ULONG_MAX;
1114 for (i = 1; i <= 4; i *= 2) {
1115 if (f25.t * i >= var->pixclock &&
1120 if (f32.t * i >= var->pixclock &&
1125 if (fext.t && fext.t * i >= var->pixclock &&
1133 plen = pcl / pclock->t;
1135 left_margin = var->left_margin;
1136 right_margin = var->right_margin;
1137 hsync_len = var->hsync_len;
1138 upper_margin = var->upper_margin;
1139 lower_margin = var->lower_margin;
1140 vsync_len = var->vsync_len;
1141 /* Internal unit is [single lines per (half-)frame] */
1142 if (var->vmode & FB_VMODE_INTERLACED) {
1143 /* # lines in half frame */
1144 /* External unit is [lines per full frame] */
1145 upper_margin = (upper_margin + 1) / 2;
1146 lower_margin = (lower_margin + 1) / 2;
1147 vsync_len = (vsync_len + 1) / 2;
1148 } else if (var->vmode & FB_VMODE_DOUBLE) {
1149 /* External unit is [double lines per frame] */
1155 if (pclock == &fext)
1156 longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1158 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1159 /* this is definitely wrong if bus clock != 32MHz */
1160 if (pclock->f / plen / 8 * bpp > 32000000L)
1166 /* include sync lengths in right/lower margin for all calculations */
1167 right_margin += hsync_len;
1168 lower_margin += vsync_len;
1170 /* ! In all calculations of margins we use # of lines in half frame
1171 * (which is a full frame in non-interlace mode), so we can switch
1172 * between interlace and non-interlace without messing around
1176 /* Set base_offset 128 and video bus width */
1177 par->hw.falcon.vid_control = mon_type | f030_bus_width;
1179 par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */
1180 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1181 par->hw.falcon.vid_control |= VCO_HSYPOS;
1182 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1183 par->hw.falcon.vid_control |= VCO_VSYPOS;
1185 par->hw.falcon.vid_control |= pclock->control_mask;
1186 /* External or internal clock */
1187 par->hw.falcon.sync = pclock->sync_mask | 0x2;
1188 /* Pixellength and prescale */
1189 par->hw.falcon.vid_mode = (2 / plen) << 2;
1191 par->hw.falcon.vid_mode |= VMO_DOUBLE;
1193 par->hw.falcon.vid_mode |= VMO_INTER;
1195 /*********************
1196 * Horizontal timing: unit = [master clock cycles]
1197 * unit of hxx-registers: [master clock cycles * prescale]
1198 * Hxx-registers are 9 bit wide
1200 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1202 * graphic output = hdb & 0x200 ?
1203 * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1204 * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1205 * (this must be a multiple of plen*128/bpp, on VGA pixels
1206 * to the right may be cut off with a bigger right margin)
1208 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1209 * (hdb - hht - 2) * prescale + hdboff :
1210 * hdb * prescale + hdboff
1212 * end of graphics relative to start of 1st halfline =
1213 * (hde + hht + 2) * prescale + hdeoff
1214 *********************/
1215 /* Calculate VIDEL registers */
1217 prescale = hxx_prescale(&par->hw.falcon);
1218 base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1220 /* Offsets depend on video mode */
1221 /* Offsets are in clock cycles, divide by prescale to
1222 * calculate hd[be]-registers
1224 if (par->hw.falcon.f_shift & 0x100) {
1227 hdb_off = (base_off + 16 * plen) + prescale;
1230 hde_off = ((128 / bpp + 2) * plen);
1231 if (par->hw.falcon.ste_mode)
1232 hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1234 hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1237 gstart = (prescale / 2 + plen * left_margin) / prescale;
1238 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1239 gend1 = gstart + roundup(xres, align) * plen / prescale;
1240 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1241 gend2 = gstart + xres * plen / prescale;
1242 par->HHT = plen * (left_margin + xres + right_margin) /
1244 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1246 par->HDB = gstart - hdb_off / prescale;
1249 par->HDB += par->HHT + 2 + 0x200;
1250 par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
1251 par->HBB = gend2 - par->HHT - 2;
1253 /* One more Videl constraint: data fetch of two lines must not overlap */
1254 if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1255 /* if this happens increase margins, decrease hfreq. */
1258 if (hde_off % prescale)
1259 par->HBB++; /* compensate for non matching hde and hbb */
1260 par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1261 if (par->HSS < par->HBB)
1262 par->HSS = par->HBB;
1265 /* check hor. frequency */
1266 hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
1267 if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
1268 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1269 /* Too high -> enlarge margin */
1274 if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1278 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1279 * of the first displayed line!
1280 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1281 * non-interlace, odd in interlace mode for synchronisation.
1282 * Vxx-registers are 11 bit wide
1284 par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1285 par->VDB = par->VBE;
1290 par->VDE <<= 1; /* VDE now half lines per (half-)frame */
1291 par->VDE += par->VDB;
1292 par->VBB = par->VDE;
1293 par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1294 par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
1295 /* vbb,vss,vft must be even in interlace mode */
1302 /* V-frequency check, hope I didn't create any loop here. */
1303 /* Interlace and doubleline are mutually exclusive. */
1304 vfreq = (hfreq * 2) / (par->VFT + 1);
1305 if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1306 /* Too high -> try again with doubleline */
1309 } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1310 /* Too low -> try again with interlace */
1313 } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1314 /* Doubleline too low -> clear doubleline and enlarge margins */
1318 (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
1319 fb_info.monspecs.vfmax;
1322 upper_margin += lines;
1323 lower_margin += lines;
1325 } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1326 /* Doubleline too high -> enlarge margins */
1329 (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1330 fb_info.monspecs.vfmax;
1333 upper_margin += lines;
1334 lower_margin += lines;
1336 } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1337 /* Interlace, too high -> enlarge margins */
1340 (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1341 fb_info.monspecs.vfmax;
1344 upper_margin += lines;
1345 lower_margin += lines;
1347 } else if (vfreq < fb_info.monspecs.vfmin ||
1348 vfreq > fb_info.monspecs.vfmax)
1352 linelen = xres_virtual * bpp / 8;
1353 if (yres_virtual * linelen > screen_len && screen_len)
1355 if (yres * linelen > screen_len && screen_len)
1357 if (var->yoffset + yres > yres_virtual && yres_virtual)
1359 par->yres_virtual = yres_virtual;
1360 par->screen_base = screen_base + var->yoffset * linelen;
1361 par->hw.falcon.xoffset = 0;
1363 par->next_line = linelen;
1368 static int falcon_encode_var(struct fb_var_screeninfo *var,
1369 struct atafb_par *par)
1371 /* !!! only for VGA !!! */
1374 int hdb_off, hde_off, base_off;
1375 struct falcon_hw *hw = &par->hw.falcon;
1377 memset(var, 0, sizeof(struct fb_var_screeninfo));
1378 /* possible frequencies: 25.175 or 32MHz */
1379 var->pixclock = hw->sync & 0x1 ? fext.t :
1380 hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1386 if (hw->vid_control & VCO_HSYPOS)
1387 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1388 if (hw->vid_control & VCO_VSYPOS)
1389 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1391 var->vmode = FB_VMODE_NONINTERLACED;
1392 if (hw->vid_mode & VMO_INTER)
1393 var->vmode |= FB_VMODE_INTERLACED;
1394 if (hw->vid_mode & VMO_DOUBLE)
1395 var->vmode |= FB_VMODE_DOUBLE;
1397 /* visible y resolution:
1398 * Graphics display starts at line VDB and ends at line
1399 * VDE. If interlace mode off unit of VC-registers is
1400 * half lines, else lines.
1402 var->yres = hw->vde - hw->vdb;
1403 if (!(var->vmode & FB_VMODE_INTERLACED))
1405 if (var->vmode & FB_VMODE_DOUBLE)
1409 * to get bpp, we must examine f_shift and st_shift.
1410 * f_shift is valid if any of bits no. 10, 8 or 4
1411 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1412 * if bit 10 set then bit 8 and bit 4 don't care...
1413 * If all these bits are 0 get display depth from st_shift
1414 * (as for ST and STE)
1416 if (hw->f_shift & 0x400) /* 2 colors */
1417 var->bits_per_pixel = 1;
1418 else if (hw->f_shift & 0x100) /* hicolor */
1419 var->bits_per_pixel = 16;
1420 else if (hw->f_shift & 0x010) /* 8 bitplanes */
1421 var->bits_per_pixel = 8;
1422 else if (hw->st_shift == 0)
1423 var->bits_per_pixel = 4;
1424 else if (hw->st_shift == 0x100)
1425 var->bits_per_pixel = 2;
1426 else /* if (hw->st_shift == 0x200) */
1427 var->bits_per_pixel = 1;
1429 var->xres = hw->line_width * 16 / var->bits_per_pixel;
1430 var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1432 var->xres_virtual += 16;
1434 if (var->bits_per_pixel == 16) {
1435 var->red.offset = 11;
1436 var->red.length = 5;
1437 var->red.msb_right = 0;
1438 var->green.offset = 5;
1439 var->green.length = 6;
1440 var->green.msb_right = 0;
1441 var->blue.offset = 0;
1442 var->blue.length = 5;
1443 var->blue.msb_right = 0;
1445 var->red.offset = 0;
1446 var->red.length = hw->ste_mode ? 4 : 6;
1447 if (var->red.length > var->bits_per_pixel)
1448 var->red.length = var->bits_per_pixel;
1449 var->red.msb_right = 0;
1451 var->blue = var->green = var->red;
1453 var->transp.offset = 0;
1454 var->transp.length = 0;
1455 var->transp.msb_right = 0;
1457 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1459 if (par->yres_virtual)
1460 var->yres_virtual = par->yres_virtual;
1462 /* yres_virtual == 0 means use maximum */
1463 var->yres_virtual = screen_len / linelen;
1466 var->yres_virtual = 2 * var->yres;
1468 var->yres_virtual = var->yres + hwscroll * 16;
1470 var->xoffset = 0; /* TODO change this */
1473 prescale = hxx_prescale(hw);
1474 plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1475 base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1476 if (hw->f_shift & 0x100) {
1478 hdb_off = (base_off + 16 * plen) + prescale;
1480 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1482 hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1485 hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1489 /* Right margin includes hsync */
1490 var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1491 (hw->hdb & 0x200 ? 2 + hw->hht : 0));
1492 if (hw->ste_mode || mon_type != F_MON_VGA)
1493 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1495 /* can't use this in ste_mode, because hbb is +1 off */
1496 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1497 var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1499 /* Lower margin includes vsync */
1500 var->upper_margin = hw->vdb / 2; /* round down to full lines */
1501 var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2; /* round up */
1502 var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2; /* round up */
1503 if (var->vmode & FB_VMODE_INTERLACED) {
1504 var->upper_margin *= 2;
1505 var->lower_margin *= 2;
1506 var->vsync_len *= 2;
1507 } else if (var->vmode & FB_VMODE_DOUBLE) {
1508 var->upper_margin = (var->upper_margin + 1) / 2;
1509 var->lower_margin = (var->lower_margin + 1) / 2;
1510 var->vsync_len = (var->vsync_len + 1) / 2;
1513 var->pixclock *= plen;
1514 var->left_margin /= plen;
1515 var->right_margin /= plen;
1516 var->hsync_len /= plen;
1518 var->right_margin -= var->hsync_len;
1519 var->lower_margin -= var->vsync_len;
1522 var->yoffset = (par->screen_base - screen_base) / linelen;
1525 var->nonstd = 0; /* what is this for? */
1530 static int f_change_mode;
1531 static struct falcon_hw f_new_mode;
1532 static int f_pan_display;
1534 static void falcon_get_par(struct atafb_par *par)
1537 struct falcon_hw *hw = &par->hw.falcon;
1539 hw->line_width = shifter_f030.scn_width;
1540 hw->line_offset = shifter_f030.off_next;
1541 hw->st_shift = videl.st_shift & 0x300;
1542 hw->f_shift = videl.f_shift;
1543 hw->vid_control = videl.control;
1544 hw->vid_mode = videl.mode;
1545 hw->sync = shifter_st.syncmode & 0x1;
1546 hw->xoffset = videl.xoffset & 0xf;
1547 hw->hht = videl.hht;
1548 hw->hbb = videl.hbb;
1549 hw->hbe = videl.hbe;
1550 hw->hdb = videl.hdb;
1551 hw->hde = videl.hde;
1552 hw->hss = videl.hss;
1553 hw->vft = videl.vft;
1554 hw->vbb = videl.vbb;
1555 hw->vbe = videl.vbe;
1556 hw->vdb = videl.vdb;
1557 hw->vde = videl.vde;
1558 hw->vss = videl.vss;
1560 addr = (shifter_st.bas_hi & 0xff) << 16 |
1561 (shifter_st.bas_md & 0xff) << 8 |
1562 (shifter_st.bas_lo & 0xff);
1563 par->screen_base = atari_stram_to_virt(addr);
1565 /* derived parameters */
1566 hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
1567 hw->mono = (hw->f_shift & 0x400) ||
1568 ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
1571 static void falcon_set_par(struct atafb_par *par)
1575 /* only set screen_base if really necessary */
1576 if (current_par.screen_base != par->screen_base)
1577 fbhw->set_screen_base(par->screen_base);
1579 /* Don't touch any other registers if we keep the default resolution */
1583 /* Tell vbl-handler to change video mode.
1584 * We change modes only on next VBL, to avoid desynchronisation
1585 * (a shift to the right and wrap around by a random number of pixels
1586 * in all monochrome modes).
1587 * This seems to work on my Falcon.
1589 f_new_mode = par->hw.falcon;
1593 static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
1595 struct falcon_hw *hw = &f_new_mode;
1597 if (f_change_mode) {
1600 if (hw->sync & 0x1) {
1601 /* Enable external pixelclock. This code only for ScreenWonder */
1602 *(volatile unsigned short *)0xffff9202 = 0xffbf;
1604 /* Turn off external clocks. Read sets all output bits to 1. */
1605 *(volatile unsigned short *)0xffff9202;
1607 shifter_st.syncmode = hw->sync;
1609 videl.hht = hw->hht;
1610 videl.hbb = hw->hbb;
1611 videl.hbe = hw->hbe;
1612 videl.hdb = hw->hdb;
1613 videl.hde = hw->hde;
1614 videl.hss = hw->hss;
1615 videl.vft = hw->vft;
1616 videl.vbb = hw->vbb;
1617 videl.vbe = hw->vbe;
1618 videl.vdb = hw->vdb;
1619 videl.vde = hw->vde;
1620 videl.vss = hw->vss;
1622 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1624 videl.st_shift = hw->st_shift; /* write enables STE palette */
1627 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1628 * Writing 0 to f_shift enables 4 plane Falcon mode but
1629 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1630 * with Falcon palette.
1633 /* now back to Falcon palette mode */
1634 videl.f_shift = hw->f_shift;
1636 /* writing to st_shift changed scn_width and vid_mode */
1637 videl.xoffset = hw->xoffset;
1638 shifter_f030.scn_width = hw->line_width;
1639 shifter_f030.off_next = hw->line_offset;
1640 videl.control = hw->vid_control;
1641 videl.mode = hw->vid_mode;
1643 if (f_pan_display) {
1645 videl.xoffset = current_par.hw.falcon.xoffset;
1646 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1651 static int falcon_pan_display(struct fb_var_screeninfo *var,
1652 struct fb_info *info)
1654 struct atafb_par *par = (struct atafb_par *)info->par;
1657 int bpp = info->var.bits_per_pixel;
1660 var->xoffset = up(var->xoffset, 32);
1662 par->hw.falcon.xoffset = var->xoffset & 15;
1664 par->hw.falcon.xoffset = 0;
1665 var->xoffset = up(var->xoffset, 2);
1667 par->hw.falcon.line_offset = bpp *
1668 (info->var.xres_virtual - info->var.xres) / 16;
1669 if (par->hw.falcon.xoffset)
1670 par->hw.falcon.line_offset -= bpp;
1671 xoffset = var->xoffset - par->hw.falcon.xoffset;
1673 par->screen_base = screen_base +
1674 (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
1675 if (fbhw->set_screen_base)
1676 fbhw->set_screen_base(par->screen_base);
1678 return -EINVAL; /* shouldn't happen */
1683 static int falcon_setcolreg(unsigned int regno, unsigned int red,
1684 unsigned int green, unsigned int blue,
1685 unsigned int transp, struct fb_info *info)
1689 f030_col[regno] = (((red & 0xfc00) << 16) |
1690 ((green & 0xfc00) << 8) |
1691 ((blue & 0xfc00) >> 8));
1693 shifter_tt.color_reg[regno] =
1694 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1695 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1696 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1697 ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
1698 ((green & 0xfc00) >> 5) |
1699 ((blue & 0xf800) >> 11));
1704 static int falcon_blank(int blank_mode)
1706 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1707 * so VIDEL doesn't hog the bus while saving.
1708 * (this may affect usleep()).
1710 int vdb, vss, hbe, hss;
1712 if (mon_type == F_MON_SM) /* this doesn't work on SM124 */
1715 vdb = current_par.VDB;
1716 vss = current_par.VSS;
1717 hbe = current_par.HBE;
1718 hss = current_par.HSS;
1720 if (blank_mode >= 1) {
1721 /* disable graphics output (this speeds up the CPU) ... */
1722 vdb = current_par.VFT + 1;
1723 /* ... and blank all lines */
1724 hbe = current_par.HHT + 2;
1726 /* use VESA suspend modes on VGA monitors */
1727 if (mon_type == F_MON_VGA) {
1728 if (blank_mode == 2 || blank_mode == 4)
1729 vss = current_par.VFT + 1;
1730 if (blank_mode == 3 || blank_mode == 4)
1731 hss = current_par.HHT + 2;
1742 static int falcon_detect(void)
1744 struct atafb_par par;
1747 /* Determine connected monitor and set monitor parameters */
1748 fhw = *(unsigned char *)0xffff8006;
1749 mon_type = fhw >> 6 & 0x3;
1750 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1751 f030_bus_width = fhw << 6 & 0x80;
1754 fb_info.monspecs.vfmin = 70;
1755 fb_info.monspecs.vfmax = 72;
1756 fb_info.monspecs.hfmin = 35713;
1757 fb_info.monspecs.hfmax = 35715;
1762 fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
1763 fb_info.monspecs.vfmax = 60;
1764 fb_info.monspecs.hfmin = 15620;
1765 fb_info.monspecs.hfmax = 15755;
1768 /* initialize hsync-len */
1769 f25.hsync = h_syncs[mon_type] / f25.t;
1770 f32.hsync = h_syncs[mon_type] / f32.t;
1772 fext.hsync = h_syncs[mon_type] / fext.t;
1774 falcon_get_par(&par);
1775 falcon_encode_var(&atafb_predefined[0], &par);
1777 /* Detected mode is always the "autodetect" slot */
1781 #endif /* ATAFB_FALCON */
1783 /* ------------------- ST(E) specific functions ---------------------- */
1787 static int stste_encode_fix(struct fb_fix_screeninfo *fix,
1788 struct atafb_par *par)
1792 strcpy(fix->id, "Atari Builtin");
1793 fix->smem_start = phys_screen_base;
1794 fix->smem_len = screen_len;
1795 fix->type = FB_TYPE_INTERLEAVED_PLANES;
1797 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1798 mode = par->hw.st.mode & 3;
1799 if (mode == ST_HIGH) {
1800 fix->type = FB_TYPE_PACKED_PIXELS;
1802 fix->visual = FB_VISUAL_MONO10;
1804 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1812 fix->line_length = par->next_line;
1813 fix->accel = FB_ACCEL_ATARIBLITT;
1817 static int stste_decode_var(struct fb_var_screeninfo *var,
1818 struct atafb_par *par)
1820 int xres = var->xres;
1821 int yres = var->yres;
1822 int bpp = var->bits_per_pixel;
1824 int yres_virtual = var->yres_virtual;
1827 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1829 par->hw.st.mode = ST_HIGH;
1834 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1837 if (xres > sttt_xres / 2 || yres > st_yres / 2)
1839 par->hw.st.mode = ST_LOW;
1840 xres = sttt_xres / 2;
1843 } else if (bpp > 1) {
1844 if (xres > sttt_xres || yres > st_yres / 2)
1846 par->hw.st.mode = ST_MID;
1853 if (yres_virtual <= 0)
1855 else if (yres_virtual < yres)
1856 yres_virtual = yres;
1857 if (var->sync & FB_SYNC_EXT)
1858 par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
1860 par->hw.st.sync = (par->hw.st.sync & ~1);
1861 linelen = xres * bpp / 8;
1862 if (yres_virtual * linelen > screen_len && screen_len)
1864 if (yres * linelen > screen_len && screen_len)
1866 if (var->yoffset + yres > yres_virtual && yres_virtual)
1868 par->yres_virtual = yres_virtual;
1869 par->screen_base = screen_base + var->yoffset * linelen;
1870 par->next_line = linelen;
1874 static int stste_encode_var(struct fb_var_screeninfo *var,
1875 struct atafb_par *par)
1878 memset(var, 0, sizeof(struct fb_var_screeninfo));
1879 var->red.offset = 0;
1880 var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1881 var->red.msb_right = 0;
1884 var->pixclock = 31041;
1885 var->left_margin = 120; /* these are incorrect */
1886 var->right_margin = 100;
1887 var->upper_margin = 8;
1888 var->lower_margin = 16;
1889 var->hsync_len = 140;
1890 var->vsync_len = 30;
1895 if (!(par->hw.st.sync & 1))
1898 var->sync = FB_SYNC_EXT;
1900 switch (par->hw.st.mode & 3) {
1902 var->xres = sttt_xres / 2;
1903 var->yres = st_yres / 2;
1904 var->bits_per_pixel = 4;
1907 var->xres = sttt_xres;
1908 var->yres = st_yres / 2;
1909 var->bits_per_pixel = 2;
1912 var->xres = sttt_xres;
1913 var->yres = st_yres;
1914 var->bits_per_pixel = 1;
1917 var->blue = var->green = var->red;
1918 var->transp.offset = 0;
1919 var->transp.length = 0;
1920 var->transp.msb_right = 0;
1921 var->xres_virtual = sttt_xres_virtual;
1922 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1923 ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
1926 var->yres_virtual = var->yres;
1927 else if (screen_len) {
1928 if (par->yres_virtual)
1929 var->yres_virtual = par->yres_virtual;
1931 /* yres_virtual == 0 means use maximum */
1932 var->yres_virtual = screen_len / linelen;
1935 var->yres_virtual = 2 * var->yres;
1937 var->yres_virtual = var->yres + hwscroll * 16;
1941 var->yoffset = (par->screen_base - screen_base) / linelen;
1946 var->vmode = FB_VMODE_NONINTERLACED;
1950 static void stste_get_par(struct atafb_par *par)
1953 par->hw.st.mode = shifter_tt.st_shiftmode;
1954 par->hw.st.sync = shifter_st.syncmode;
1955 addr = ((shifter_st.bas_hi & 0xff) << 16) |
1956 ((shifter_st.bas_md & 0xff) << 8);
1957 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1958 addr |= (shifter_st.bas_lo & 0xff);
1959 par->screen_base = atari_stram_to_virt(addr);
1962 static void stste_set_par(struct atafb_par *par)
1964 shifter_tt.st_shiftmode = par->hw.st.mode;
1965 shifter_st.syncmode = par->hw.st.sync;
1966 /* only set screen_base if really necessary */
1967 if (current_par.screen_base != par->screen_base)
1968 fbhw->set_screen_base(par->screen_base);
1971 static int stste_setcolreg(unsigned int regno, unsigned int red,
1972 unsigned int green, unsigned int blue,
1973 unsigned int transp, struct fb_info *info)
1980 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1981 shifter_tt.color_reg[regno] =
1982 (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1983 (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1984 ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1986 shifter_tt.color_reg[regno] =
1987 ((red & 0xe) << 7) |
1988 ((green & 0xe) << 3) |
1989 ((blue & 0xe) >> 1);
1993 static int stste_detect(void)
1995 struct atafb_par par;
1997 /* Determine the connected monitor: The DMA sound must be
1998 * disabled before reading the MFP GPIP, because the Sound
1999 * Done Signal and the Monochrome Detect are XORed together!
2001 if (ATARIHW_PRESENT(PCM_8BIT)) {
2002 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2003 udelay(20); /* wait a while for things to settle down */
2005 mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
2007 stste_get_par(&par);
2008 stste_encode_var(&atafb_predefined[0], &par);
2010 if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2015 static void stste_set_screen_base(void *s_base)
2018 addr = atari_stram_to_phys(s_base);
2019 /* Setup Screen Memory */
2020 shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2021 shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2022 if (ATARIHW_PRESENT(EXTD_SHIFTER))
2023 shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
2026 #endif /* ATAFB_STE */
2028 /* Switching the screen size should be done during vsync, otherwise
2029 * the margins may get messed up. This is a well known problem of
2030 * the ST's video system.
2032 * Unfortunately there is hardly any way to find the vsync, as the
2033 * vertical blank interrupt is no longer in time on machines with
2034 * overscan type modifications.
2036 * We can, however, use Timer B to safely detect the black shoulder,
2037 * but then we've got to guess an appropriate delay to find the vsync.
2038 * This might not work on every machine.
2040 * martin_rogge @ ki.maus.de, 8th Aug 1995
2043 #define LINE_DELAY (mono_moni ? 30 : 70)
2044 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2046 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2047 static void st_ovsc_switch(void)
2049 unsigned long flags;
2050 register unsigned char old, new;
2052 if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2054 local_irq_save(flags);
2056 st_mfp.tim_ct_b = 0x10;
2057 st_mfp.active_edge |= 8;
2058 st_mfp.tim_ct_b = 0;
2059 st_mfp.tim_dt_b = 0xf0;
2060 st_mfp.tim_ct_b = 8;
2061 while (st_mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2063 new = st_mfp.tim_dt_b;
2067 new = st_mfp.tim_dt_b;
2068 } while (old != new);
2069 st_mfp.tim_ct_b = 0x10;
2072 if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2073 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2074 if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2075 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2076 if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2077 sound_ym.rd_data_reg_sel = 14;
2078 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2079 ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2080 ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2082 local_irq_restore(flags);
2085 /* ------------------- External Video ---------------------- */
2089 static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
2091 strcpy(fix->id, "Unknown Extern");
2092 fix->smem_start = external_addr;
2093 fix->smem_len = PAGE_ALIGN(external_len);
2094 if (external_depth == 1) {
2095 fix->type = FB_TYPE_PACKED_PIXELS;
2096 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2097 * for "normal" and "inverted", rsp., in the monochrome case */
2099 (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2100 external_pmode == FB_TYPE_PACKED_PIXELS) ?
2101 FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
2103 /* Use STATIC if we don't know how to access color registers */
2104 int visual = external_vgaiobase ?
2105 FB_VISUAL_PSEUDOCOLOR :
2106 FB_VISUAL_STATIC_PSEUDOCOLOR;
2107 switch (external_pmode) {
2108 case -1: /* truecolor */
2109 fix->type = FB_TYPE_PACKED_PIXELS;
2110 fix->visual = FB_VISUAL_TRUECOLOR;
2112 case FB_TYPE_PACKED_PIXELS:
2113 fix->type = FB_TYPE_PACKED_PIXELS;
2114 fix->visual = visual;
2116 case FB_TYPE_PLANES:
2117 fix->type = FB_TYPE_PLANES;
2118 fix->visual = visual;
2120 case FB_TYPE_INTERLEAVED_PLANES:
2121 fix->type = FB_TYPE_INTERLEAVED_PLANES;
2123 fix->visual = visual;
2130 fix->line_length = par->next_line;
2134 static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2136 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2138 if (var->bits_per_pixel > myvar->bits_per_pixel ||
2139 var->xres > myvar->xres ||
2140 var->xres_virtual > myvar->xres_virtual ||
2141 var->yres > myvar->yres ||
2146 par->next_line = external_xres_virtual * external_depth / 8;
2150 static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2152 memset(var, 0, sizeof(struct fb_var_screeninfo));
2153 var->red.offset = 0;
2154 var->red.length = (external_pmode == -1) ? external_depth / 3 :
2155 (external_vgaiobase ? external_bitspercol : 0);
2156 var->red.msb_right = 0;
2159 var->pixclock = 31041;
2160 var->left_margin = 120; /* these are surely incorrect */
2161 var->right_margin = 100;
2162 var->upper_margin = 8;
2163 var->lower_margin = 16;
2164 var->hsync_len = 140;
2165 var->vsync_len = 30;
2172 var->xres = external_xres;
2173 var->yres = external_yres;
2174 var->xres_virtual = external_xres_virtual;
2175 var->bits_per_pixel = external_depth;
2177 var->blue = var->green = var->red;
2178 var->transp.offset = 0;
2179 var->transp.length = 0;
2180 var->transp.msb_right = 0;
2181 var->yres_virtual = var->yres;
2186 var->vmode = FB_VMODE_NONINTERLACED;
2190 static void ext_get_par(struct atafb_par *par)
2192 par->screen_base = external_screen_base;
2195 static void ext_set_par(struct atafb_par *par)
2199 #define OUTB(port,val) \
2200 *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2202 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2205 unsigned char tmp = INB(0x3da); \
2209 static int ext_setcolreg(unsigned int regno, unsigned int red,
2210 unsigned int green, unsigned int blue,
2211 unsigned int transp, struct fb_info *info)
2213 unsigned char colmask = (1 << external_bitspercol) - 1;
2215 if (!external_vgaiobase)
2221 switch (external_card_type) {
2225 OUTB(0x3c9, red & colmask);
2227 OUTB(0x3c9, green & colmask);
2229 OUTB(0x3c9, blue & colmask);
2234 OUTB((MV300_reg[regno] << 2) + 1, red);
2235 OUTB((MV300_reg[regno] << 2) + 1, green);
2236 OUTB((MV300_reg[regno] << 2) + 1, blue);
2244 static int ext_detect(void)
2246 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2247 struct atafb_par dummy_par;
2249 myvar->xres = external_xres;
2250 myvar->xres_virtual = external_xres_virtual;
2251 myvar->yres = external_yres;
2252 myvar->bits_per_pixel = external_depth;
2253 ext_encode_var(myvar, &dummy_par);
2257 #endif /* ATAFB_EXT */
2259 /* ------ This is the same for most hardware types -------- */
2261 static void set_screen_base(void *s_base)
2265 addr = atari_stram_to_phys(s_base);
2266 /* Setup Screen Memory */
2267 shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2268 shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2269 shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
2272 static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2274 struct atafb_par *par = (struct atafb_par *)info->par;
2276 if (!fbhw->set_screen_base ||
2277 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2279 var->xoffset = up(var->xoffset, 16);
2280 par->screen_base = screen_base +
2281 (var->yoffset * info->var.xres_virtual + var->xoffset)
2282 * info->var.bits_per_pixel / 8;
2283 fbhw->set_screen_base(par->screen_base);
2287 /* ------------ Interfaces to hardware functions ------------ */
2290 static struct fb_hwswitch tt_switch = {
2291 .detect = tt_detect,
2292 .encode_fix = tt_encode_fix,
2293 .decode_var = tt_decode_var,
2294 .encode_var = tt_encode_var,
2295 .get_par = tt_get_par,
2296 .set_par = tt_set_par,
2297 .set_screen_base = set_screen_base,
2298 .pan_display = pan_display,
2303 static struct fb_hwswitch falcon_switch = {
2304 .detect = falcon_detect,
2305 .encode_fix = falcon_encode_fix,
2306 .decode_var = falcon_decode_var,
2307 .encode_var = falcon_encode_var,
2308 .get_par = falcon_get_par,
2309 .set_par = falcon_set_par,
2310 .set_screen_base = set_screen_base,
2311 .blank = falcon_blank,
2312 .pan_display = falcon_pan_display,
2317 static struct fb_hwswitch st_switch = {
2318 .detect = stste_detect,
2319 .encode_fix = stste_encode_fix,
2320 .decode_var = stste_decode_var,
2321 .encode_var = stste_encode_var,
2322 .get_par = stste_get_par,
2323 .set_par = stste_set_par,
2324 .set_screen_base = stste_set_screen_base,
2325 .pan_display = pan_display
2330 static struct fb_hwswitch ext_switch = {
2331 .detect = ext_detect,
2332 .encode_fix = ext_encode_fix,
2333 .decode_var = ext_decode_var,
2334 .encode_var = ext_encode_var,
2335 .get_par = ext_get_par,
2336 .set_par = ext_set_par,
2340 static void ata_get_par(struct atafb_par *par)
2342 if (current_par_valid)
2348 static void ata_set_par(struct atafb_par *par)
2352 current_par_valid = 1;
2356 /* =========================================================== */
2357 /* ============== Hardware Independent Functions ============= */
2358 /* =========================================================== */
2360 /* used for hardware scrolling */
2362 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2365 struct atafb_par par;
2367 err = fbhw->decode_var(var, &par);
2370 activate = var->activate;
2371 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2373 fbhw->encode_var(var, &par);
2374 var->activate = activate;
2378 /* fbhw->encode_fix() must be called with fb_info->mm_lock held
2379 * if it is called after the register_framebuffer() - not a case here
2381 static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2383 struct atafb_par par;
2385 // Get fix directly (case con == -1 before)??
2386 err = fbhw->decode_var(&info->var, &par);
2389 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2390 err = fbhw->encode_fix(fix, &par);
2394 static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
2396 struct atafb_par par;
2399 fbhw->encode_var(var, &par);
2404 // No longer called by fbcon!
2405 // Still called by set_var internally
2407 static void atafb_set_disp(struct fb_info *info)
2409 atafb_get_var(&info->var, info);
2410 atafb_get_fix(&info->fix, info);
2412 /* Note: smem_start derives from phys_screen_base, not screen_base! */
2413 info->screen_base = (external_addr ? external_screen_base :
2414 atari_stram_to_virt(info->fix.smem_start));
2417 static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2418 u_int transp, struct fb_info *info)
2424 return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
2428 atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2430 int xoffset = var->xoffset;
2431 int yoffset = var->yoffset;
2434 if (var->vmode & FB_VMODE_YWRAP) {
2435 if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
2438 if (xoffset + info->var.xres > info->var.xres_virtual ||
2439 yoffset + info->var.yres > info->var.yres_virtual)
2443 if (fbhw->pan_display) {
2444 err = fbhw->pan_display(var, info);
2450 info->var.xoffset = xoffset;
2451 info->var.yoffset = yoffset;
2453 if (var->vmode & FB_VMODE_YWRAP)
2454 info->var.vmode |= FB_VMODE_YWRAP;
2456 info->var.vmode &= ~FB_VMODE_YWRAP;
2462 * generic drawing routines; imageblit needs updating for image depth > 1
2465 #if BITS_PER_LONG == 32
2466 #define BYTES_PER_LONG 4
2467 #define SHIFT_PER_LONG 5
2468 #elif BITS_PER_LONG == 64
2469 #define BYTES_PER_LONG 8
2470 #define SHIFT_PER_LONG 6
2472 #define Please update me
2476 static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
2478 struct atafb_par *par = (struct atafb_par *)info->par;
2482 if (!rect->width || !rect->height)
2486 if (info->var.bits_per_pixel == 16) {
2487 cfb_fillrect(info, rect);
2493 * We could use hardware clipping but on many cards you get around
2494 * hardware clipping by writing to framebuffer directly.
2496 x2 = rect->dx + rect->width;
2497 y2 = rect->dy + rect->height;
2498 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2499 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2500 width = x2 - rect->dx;
2501 height = y2 - rect->dy;
2503 if (info->var.bits_per_pixel == 1)
2504 atafb_mfb_fillrect(info, par->next_line, rect->color,
2505 rect->dy, rect->dx, height, width);
2506 else if (info->var.bits_per_pixel == 2)
2507 atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
2508 rect->dy, rect->dx, height, width);
2509 else if (info->var.bits_per_pixel == 4)
2510 atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
2511 rect->dy, rect->dx, height, width);
2513 atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
2514 rect->dy, rect->dx, height, width);
2519 static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2521 struct atafb_par *par = (struct atafb_par *)info->par;
2523 u32 dx, dy, sx, sy, width, height;
2527 if (info->var.bits_per_pixel == 16) {
2528 cfb_copyarea(info, area);
2533 /* clip the destination */
2534 x2 = area->dx + area->width;
2535 y2 = area->dy + area->height;
2536 dx = area->dx > 0 ? area->dx : 0;
2537 dy = area->dy > 0 ? area->dy : 0;
2538 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2539 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2543 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2547 sx = area->sx + (dx - area->dx);
2548 sy = area->sy + (dy - area->dy);
2550 /* the source must be completely inside the virtual screen */
2551 if (sx + width > info->var.xres_virtual ||
2552 sy + height > info->var.yres_virtual)
2555 if (dy > sy || (dy == sy && dx > sx)) {
2561 if (info->var.bits_per_pixel == 1)
2562 atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2563 else if (info->var.bits_per_pixel == 2)
2564 atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2565 else if (info->var.bits_per_pixel == 4)
2566 atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2568 atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2573 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2575 struct atafb_par *par = (struct atafb_par *)info->par;
2580 u32 dx, dy, width, height, pitch;
2583 if (info->var.bits_per_pixel == 16) {
2584 cfb_imageblit(info, image);
2590 * We could use hardware clipping but on many cards you get around
2591 * hardware clipping by writing to framebuffer directly like we are
2594 x2 = image->dx + image->width;
2595 y2 = image->dy + image->height;
2598 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2599 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2603 if (image->depth == 1) {
2604 // used for font data
2605 dst = (unsigned long *)
2606 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2607 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2608 dst_idx += dy * par->next_line * 8 + dx;
2610 pitch = (image->width + 7) / 8;
2613 if (info->var.bits_per_pixel == 1)
2614 atafb_mfb_linefill(info, par->next_line,
2616 image->bg_color, image->fg_color);
2617 else if (info->var.bits_per_pixel == 2)
2618 atafb_iplan2p2_linefill(info, par->next_line,
2620 image->bg_color, image->fg_color);
2621 else if (info->var.bits_per_pixel == 4)
2622 atafb_iplan2p4_linefill(info, par->next_line,
2624 image->bg_color, image->fg_color);
2626 atafb_iplan2p8_linefill(info, par->next_line,
2628 image->bg_color, image->fg_color);
2633 c2p_iplan2(info->screen_base, image->data, dx, dy, width,
2634 height, par->next_line, image->width,
2635 info->var.bits_per_pixel);
2640 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2643 #ifdef FBCMD_GET_CURRENTPAR
2644 case FBCMD_GET_CURRENTPAR:
2645 if (copy_to_user((void *)arg, (void *)¤t_par,
2646 sizeof(struct atafb_par)))
2650 #ifdef FBCMD_SET_CURRENTPAR
2651 case FBCMD_SET_CURRENTPAR:
2652 if (copy_from_user((void *)¤t_par, (void *)arg,
2653 sizeof(struct atafb_par)))
2655 ata_set_par(¤t_par);
2662 /* (un)blank/poweroff
2669 static int atafb_blank(int blank, struct fb_info *info)
2671 unsigned short black[16];
2672 struct fb_cmap cmap;
2673 if (fbhw->blank && !fbhw->blank(blank))
2676 memset(black, 0, 16 * sizeof(unsigned short));
2683 fb_set_cmap(&cmap, info);
2687 do_install_cmap(info);
2693 * New fbcon interface ...
2696 /* check var by decoding var into hw par, rounding if necessary,
2697 * then encoding hw par back into new, validated var */
2698 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2701 struct atafb_par par;
2703 /* Validate wanted screen parameters */
2704 // if ((err = ata_decode_var(var, &par)))
2705 err = fbhw->decode_var(var, &par);
2709 /* Encode (possibly rounded) screen parameters */
2710 fbhw->encode_var(var, &par);
2714 /* actually set hw par by decoding var, then setting hardware from
2715 * hw par just decoded */
2716 static int atafb_set_par(struct fb_info *info)
2718 struct atafb_par *par = (struct atafb_par *)info->par;
2720 /* Decode wanted screen parameters */
2721 fbhw->decode_var(&info->var, par);
2722 mutex_lock(&info->mm_lock);
2723 fbhw->encode_fix(&info->fix, par);
2724 mutex_unlock(&info->mm_lock);
2726 /* Set new videomode */
2733 static struct fb_ops atafb_ops = {
2734 .owner = THIS_MODULE,
2735 .fb_check_var = atafb_check_var,
2736 .fb_set_par = atafb_set_par,
2737 .fb_setcolreg = atafb_setcolreg,
2738 .fb_blank = atafb_blank,
2739 .fb_pan_display = atafb_pan_display,
2740 .fb_fillrect = atafb_fillrect,
2741 .fb_copyarea = atafb_copyarea,
2742 .fb_imageblit = atafb_imageblit,
2743 .fb_ioctl = atafb_ioctl,
2746 static void check_default_par(int detected_mode)
2748 char default_name[10];
2750 struct fb_var_screeninfo var;
2751 unsigned long min_mem;
2753 /* First try the user supplied mode */
2755 var = atafb_predefined[default_par - 1];
2756 var.activate = FB_ACTIVATE_TEST;
2757 if (do_fb_set_var(&var, 1))
2758 default_par = 0; /* failed */
2760 /* Next is the autodetected one */
2762 var = atafb_predefined[detected_mode - 1]; /* autodetect */
2763 var.activate = FB_ACTIVATE_TEST;
2764 if (!do_fb_set_var(&var, 1))
2765 default_par = detected_mode;
2767 /* If that also failed, try some default modes... */
2769 /* try default1, default2... */
2770 for (i = 1; i < 10; i++) {
2771 sprintf(default_name,"default%d", i);
2772 default_par = get_video_mode(default_name);
2774 panic("can't set default video mode");
2775 var = atafb_predefined[default_par - 1];
2776 var.activate = FB_ACTIVATE_TEST;
2777 if (!do_fb_set_var(&var,1))
2781 min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
2782 if (default_mem_req < min_mem)
2783 default_mem_req = min_mem;
2787 static void __init atafb_setup_ext(char *spec)
2789 int xres, xres_virtual, yres, depth, planes;
2790 unsigned long addr, len;
2793 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2795 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2796 * [;<xres-virtual>]]]]]
2799 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2801 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2803 p = strsep(&spec, ";");
2806 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2810 p = strsep(&spec, ";");
2813 yres = simple_strtoul(p, NULL, 10);
2817 p = strsep(&spec, ";");
2820 depth = simple_strtoul(p, NULL, 10);
2821 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2822 depth != 16 && depth != 24)
2825 p = strsep(&spec, ";");
2829 planes = FB_TYPE_INTERLEAVED_PLANES;
2831 planes = FB_TYPE_PACKED_PIXELS;
2833 planes = FB_TYPE_PLANES;
2835 planes = -1; /* true color */
2839 p = strsep(&spec, ";");
2842 addr = simple_strtoul(p, NULL, 0);
2844 p = strsep(&spec, ";");
2846 len = xres * yres * depth / 8;
2848 len = simple_strtoul(p, NULL, 0);
2850 p = strsep(&spec, ";");
2852 external_vgaiobase = simple_strtoul(p, NULL, 0);
2854 p = strsep(&spec, ";");
2856 external_bitspercol = simple_strtoul(p, NULL, 0);
2857 if (external_bitspercol > 8)
2858 external_bitspercol = 8;
2859 else if (external_bitspercol < 1)
2860 external_bitspercol = 1;
2863 p = strsep(&spec, ";");
2865 if (!strcmp(p, "vga"))
2866 external_card_type = IS_VGA;
2867 if (!strcmp(p, "mv300"))
2868 external_card_type = IS_MV300;
2871 p = strsep(&spec, ";");
2873 xres_virtual = simple_strtoul(p, NULL, 10);
2874 if (xres_virtual < xres)
2875 xres_virtual = xres;
2876 if (xres_virtual * yres * depth / 8 > len)
2877 len = xres_virtual * yres * depth / 8;
2880 external_xres = xres;
2881 external_xres_virtual = xres_virtual;
2882 external_yres = yres;
2883 external_depth = depth;
2884 external_pmode = planes;
2885 external_addr = addr;
2888 if (external_card_type == IS_MV300) {
2889 switch (external_depth) {
2891 MV300_reg = MV300_reg_1bit;
2894 MV300_reg = MV300_reg_4bit;
2897 MV300_reg = MV300_reg_8bit;
2902 #endif /* ATAFB_EXT */
2904 static void __init atafb_setup_int(char *spec)
2906 /* Format to config extended internal video hardware like OverScan:
2907 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2909 * <xres>: x-resolution
2910 * <yres>: y-resolution
2911 * The following are only needed if you have an overscan which
2912 * needs a black border:
2913 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2914 * <yres_max>: max. number of lines your OverScan hardware would allow
2915 * <offset>: Offset from physical beginning to visible beginning
2916 * of screen in bytes
2921 if (!(p = strsep(&spec, ";")) || !*p)
2923 xres = simple_strtoul(p, NULL, 10);
2924 if (!(p = strsep(&spec, ";")) || !*p)
2927 tt_yres = st_yres = simple_strtoul(p, NULL, 10);
2928 if ((p = strsep(&spec, ";")) && *p)
2929 sttt_xres_virtual = simple_strtoul(p, NULL, 10);
2930 if ((p = strsep(&spec, ";")) && *p)
2931 sttt_yres_virtual = simple_strtoul(p, NULL, 0);
2932 if ((p = strsep(&spec, ";")) && *p)
2933 ovsc_offset = simple_strtoul(p, NULL, 0);
2935 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2940 static void __init atafb_setup_mcap(char *spec)
2943 int vmin, vmax, hmin, hmax;
2945 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2946 * <V*> vertical freq. in Hz
2947 * <H*> horizontal freq. in kHz
2949 if (!(p = strsep(&spec, ";")) || !*p)
2951 vmin = simple_strtoul(p, NULL, 10);
2954 if (!(p = strsep(&spec, ";")) || !*p)
2956 vmax = simple_strtoul(p, NULL, 10);
2957 if (vmax <= 0 || vmax <= vmin)
2959 if (!(p = strsep(&spec, ";")) || !*p)
2961 hmin = 1000 * simple_strtoul(p, NULL, 10);
2964 if (!(p = strsep(&spec, "")) || !*p)
2966 hmax = 1000 * simple_strtoul(p, NULL, 10);
2967 if (hmax <= 0 || hmax <= hmin)
2970 fb_info.monspecs.vfmin = vmin;
2971 fb_info.monspecs.vfmax = vmax;
2972 fb_info.monspecs.hfmin = hmin;
2973 fb_info.monspecs.hfmax = hmax;
2975 #endif /* ATAFB_FALCON */
2977 static void __init atafb_setup_user(char *spec)
2979 /* Format of user defined video mode is: <xres>;<yres>;<depth>
2982 int xres, yres, depth, temp;
2984 p = strsep(&spec, ";");
2987 xres = simple_strtoul(p, NULL, 10);
2988 p = strsep(&spec, ";");
2991 yres = simple_strtoul(p, NULL, 10);
2992 p = strsep(&spec, "");
2995 depth = simple_strtoul(p, NULL, 10);
2996 temp = get_video_mode("user0");
2999 atafb_predefined[default_par - 1].xres = xres;
3000 atafb_predefined[default_par - 1].yres = yres;
3001 atafb_predefined[default_par - 1].bits_per_pixel = depth;
3005 int __init atafb_setup(char *options)
3010 if (!options || !*options)
3013 while ((this_opt = strsep(&options, ",")) != NULL) {
3016 if ((temp = get_video_mode(this_opt))) {
3018 mode_option = this_opt;
3019 } else if (!strcmp(this_opt, "inverse"))
3021 else if (!strncmp(this_opt, "hwscroll_", 9)) {
3022 hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
3029 else if (!strcmp(this_opt, "mv300")) {
3030 external_bitspercol = 8;
3031 external_card_type = IS_MV300;
3032 } else if (!strncmp(this_opt, "external:", 9))
3033 atafb_setup_ext(this_opt + 9);
3035 else if (!strncmp(this_opt, "internal:", 9))
3036 atafb_setup_int(this_opt + 9);
3038 else if (!strncmp(this_opt, "eclock:", 7)) {
3039 fext.f = simple_strtoul(this_opt + 7, NULL, 10);
3040 /* external pixelclock in kHz --> ps */
3041 fext.t = 1000000000 / fext.f;
3043 } else if (!strncmp(this_opt, "monitorcap:", 11))
3044 atafb_setup_mcap(this_opt + 11);
3046 else if (!strcmp(this_opt, "keep"))
3048 else if (!strncmp(this_opt, "R", 1))
3049 atafb_setup_user(this_opt + 1);
3054 static int __init atafb_probe(struct platform_device *pdev)
3056 int pad, detected_mode, error;
3057 unsigned int defmode = 0;
3058 unsigned long mem_req;
3059 char *option = NULL;
3061 if (fb_get_options("atafb", &option))
3063 atafb_setup(option);
3064 dev_dbg(&pdev->dev, "%s: start\n", __func__);
3068 if (external_addr) {
3069 dev_dbg(&pdev->dev, "initializing external hw\n");
3071 atafb_ops.fb_setcolreg = &ext_setcolreg;
3072 defmode = DEFMODE_EXT;
3077 if (ATARIHW_PRESENT(TT_SHIFTER)) {
3078 dev_dbg(&pdev->dev, "initializing TT hw\n");
3080 atafb_ops.fb_setcolreg = &tt_setcolreg;
3081 defmode = DEFMODE_TT;
3086 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
3087 dev_dbg(&pdev->dev, "initializing Falcon hw\n");
3088 fbhw = &falcon_switch;
3089 atafb_ops.fb_setcolreg = &falcon_setcolreg;
3090 error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 0,
3091 "framebuffer:modeswitch",
3092 falcon_vbl_switcher);
3095 defmode = DEFMODE_F30;
3100 if (ATARIHW_PRESENT(STND_SHIFTER) ||
3101 ATARIHW_PRESENT(EXTD_SHIFTER)) {
3102 dev_dbg(&pdev->dev, "initializing ST/E hw\n");
3104 atafb_ops.fb_setcolreg = &stste_setcolreg;
3105 defmode = DEFMODE_STE;
3109 atafb_ops.fb_setcolreg = &stste_setcolreg;
3110 dev_warn(&pdev->dev,
3111 "Cannot determine video hardware; defaulting to ST(e)\n");
3112 #else /* ATAFB_STE */
3113 /* no default driver included */
3114 /* Nobody will ever see this message :-) */
3115 panic("Cannot initialize video hardware");
3119 /* Multisync monitor capabilities */
3120 /* Atari-TOS defaults if no boot option present */
3121 if (fb_info.monspecs.hfmin == 0) {
3122 fb_info.monspecs.hfmin = 31000;
3123 fb_info.monspecs.hfmax = 32000;
3124 fb_info.monspecs.vfmin = 58;
3125 fb_info.monspecs.vfmax = 62;
3128 detected_mode = fbhw->detect();
3129 check_default_par(detected_mode);
3131 if (!external_addr) {
3132 #endif /* ATAFB_EXT */
3133 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
3134 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
3135 screen_base = atari_stram_alloc(mem_req, "atafb");
3137 panic("Cannot allocate screen memory");
3138 memset(screen_base, 0, mem_req);
3139 pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
3141 phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
3142 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
3144 if (CPU_IS_040_OR_060) {
3145 /* On a '040+, the cache mode of video RAM must be set to
3146 * write-through also for internal video hardware! */
3147 cache_push(atari_stram_to_phys(screen_base), screen_len);
3148 kernel_set_cachemode(screen_base, screen_len,
3149 IOMAP_WRITETHROUGH);
3151 dev_info(&pdev->dev, "phys_screen_base %lx screen_len %d\n",
3152 phys_screen_base, screen_len);
3155 /* Map the video memory (physical address given) to somewhere
3156 * in the kernel address space.
3158 external_screen_base = ioremap_wt(external_addr, external_len);
3159 if (external_vgaiobase)
3160 external_vgaiobase =
3161 (unsigned long)ioremap(external_vgaiobase, 0x10000);
3162 screen_base = external_screen_base;
3163 phys_screen_base = external_addr;
3164 screen_len = external_len & PAGE_MASK;
3165 memset (screen_base, 0, external_len);
3167 #endif /* ATAFB_EXT */
3169 // strcpy(fb_info.mode->name, "Atari Builtin ");
3170 fb_info.fbops = &atafb_ops;
3171 // try to set default (detected; requested) var
3172 do_fb_set_var(&atafb_predefined[default_par - 1], 1);
3173 // reads hw state into current par, which may not be sane yet
3174 ata_get_par(¤t_par);
3175 fb_info.par = ¤t_par;
3176 // tries to read from HW which may not be initialized yet
3177 // so set sane var first, then call atafb_set_par
3178 atafb_get_var(&fb_info.var, &fb_info);
3181 fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
3183 fb_info.flags = FBINFO_FLAG_DEFAULT;
3185 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
3186 NUM_TOTAL_MODES, &atafb_modedb[defmode],
3187 fb_info.var.bits_per_pixel)) {
3191 fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
3194 atafb_set_disp(&fb_info);
3196 fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
3199 dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
3200 fb_info.var.yres, fb_info.var.bits_per_pixel);
3201 if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
3202 (fb_info.var.yres != fb_info.var.yres_virtual))
3203 dev_info(&pdev->dev, " virtual %dx%d\n",
3204 fb_info.var.xres_virtual, fb_info.var.yres_virtual);
3206 if (register_framebuffer(&fb_info) < 0) {
3208 if (external_addr) {
3209 iounmap(external_screen_base);
3212 if (external_vgaiobase) {
3213 iounmap((void*)external_vgaiobase);
3214 external_vgaiobase = 0;
3220 fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
3223 /* TODO: This driver cannot be unloaded yet */
3227 static void atafb_shutdown(struct platform_device *pdev)
3229 /* Unblank before kexec */
3234 static struct platform_driver atafb_driver = {
3235 .shutdown = atafb_shutdown,
3241 static int __init atafb_init(void)
3243 struct platform_device *pdev;
3248 pdev = platform_device_register_simple("atafb", -1, NULL, 0);
3250 return PTR_ERR(pdev);
3252 return platform_driver_probe(&atafb_driver, atafb_probe);
3255 device_initcall(atafb_init);