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
80 static int default_par; /* default resolution (0=none) */
82 static unsigned long default_mem_req;
84 static int hwscroll = -1;
86 static int use_hwscroll = 1;
88 static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
89 static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
90 static int ovsc_offset, ovsc_addlen;
93 * Hardware parameters for current mode
96 static struct atafb_par {
100 #if defined ATAFB_TT || defined ATAFB_STE
109 /* Here are fields for storing a video mode, as direct
110 * parameters for the hardware.
120 short hht, hbb, hbe, hdb, hde, hss;
121 short vft, vbb, vbe, vdb, vde, vss;
122 /* auxiliary information */
126 u32 pseudo_palette[16];
129 /* Nothing needed for external mode */
133 /* Don't calculate an own resolution, and thus don't change the one found when
134 * booting (currently used for the Falcon to keep settings for internal video
135 * hardware extensions (e.g. ScreenBlaster) */
136 static int DontCalcRes = 0;
139 #define HHT hw.falcon.hht
140 #define HBB hw.falcon.hbb
141 #define HBE hw.falcon.hbe
142 #define HDB hw.falcon.hdb
143 #define HDE hw.falcon.hde
144 #define HSS hw.falcon.hss
145 #define VFT hw.falcon.vft
146 #define VBB hw.falcon.vbb
147 #define VBE hw.falcon.vbe
148 #define VDB hw.falcon.vdb
149 #define VDE hw.falcon.vde
150 #define VSS hw.falcon.vss
151 #define VCO_CLOCK25 0x04
152 #define VCO_CSYPOS 0x10
153 #define VCO_VSYPOS 0x20
154 #define VCO_HSYPOS 0x40
155 #define VCO_SHORTOFFS 0x100
156 #define VMO_DOUBLE 0x01
157 #define VMO_INTER 0x02
158 #define VMO_PREMASK 0x0c
161 static struct fb_info fb_info = {
164 .visual = FB_VISUAL_PSEUDOCOLOR,
165 .accel = FB_ACCEL_NONE,
169 static void *screen_base; /* base address of screen */
170 static unsigned long phys_screen_base; /* (only for Overscan) */
172 static int screen_len;
174 static int current_par_valid;
176 static int mono_moni;
181 /* external video handling */
182 static unsigned int external_xres;
183 static unsigned int external_xres_virtual;
184 static unsigned int external_yres;
187 * not needed - atafb will never support panning/hardwarescroll with external
188 * static unsigned int external_yres_virtual;
190 static unsigned int external_depth;
191 static int external_pmode;
192 static void *external_screen_base;
193 static unsigned long external_addr;
194 static unsigned long external_len;
195 static unsigned long external_vgaiobase;
196 static unsigned int external_bitspercol = 6;
199 * JOE <joe@amber.dinoco.de>:
200 * added card type for external driver, is only needed for
203 enum cardtype { IS_VGA, IS_MV300 };
204 static enum cardtype external_card_type = IS_VGA;
207 * The MV300 mixes the color registers. So we need an array of munged
208 * indices in order to access the correct reg.
210 static int MV300_reg_1bit[2] = {
213 static int MV300_reg_4bit[16] = {
214 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
216 static int MV300_reg_8bit[256] = {
217 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
218 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
219 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
220 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
221 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
222 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
223 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
224 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
225 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
226 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
227 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
228 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
229 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
230 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
231 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
232 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
235 static int *MV300_reg = MV300_reg_8bit;
236 #endif /* ATAFB_EXT */
243 * * open/release and usage marking
244 * struct module *owner;
245 * int (*fb_open)(struct fb_info *info, int user);
246 * int (*fb_release)(struct fb_info *info, int user);
248 * * For framebuffers with strange non linear layouts or that do not
249 * * work with normal memory mapped access
250 * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
251 * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
253 * * checks var and eventually tweaks it to something supported,
254 * * DOES NOT MODIFY PAR *
255 * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
257 * * set the video mode according to info->var *
258 * int (*fb_set_par)(struct fb_info *info);
260 * * set color register *
261 * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
262 * unsigned int blue, unsigned int transp, struct fb_info *info);
264 * * set color registers in batch *
265 * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
268 * int (*fb_blank)(int blank, struct fb_info *info);
271 * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
273 * *** The meat of the drawing engine ***
274 * * Draws a rectangle *
275 * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
276 * * Copy data from area to another *
277 * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
278 * * Draws a image to the display *
279 * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
282 * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
284 * * wait for blit idle, optional *
285 * int (*fb_sync)(struct fb_info *info);
287 * * perform fb specific ioctl (optional) *
288 * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
289 * unsigned long arg);
291 * * Handle 32bit compat ioctl (optional) *
292 * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
293 * unsigned long arg);
295 * * perform fb specific mmap *
296 * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
301 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
304 * int (*detect)(void)
305 * This function should detect the current video mode settings and
306 * store them in atafb_predefined[0] for later reference by the
307 * user. Return the index+1 of an equivalent predefined mode or 0
308 * if there is no such.
310 * int (*encode_fix)(struct fb_fix_screeninfo *fix,
311 * struct atafb_par *par)
312 * This function should fill in the 'fix' structure based on the
313 * values in the 'par' structure.
314 * !!! Obsolete, perhaps !!!
316 * int (*decode_var)(struct fb_var_screeninfo *var,
317 * struct atafb_par *par)
318 * Get the video params out of 'var'. If a value doesn't fit, round
319 * it up, if it's too big, return EINVAL.
320 * Round up in the following order: bits_per_pixel, xres, yres,
321 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
322 * horizontal timing, vertical timing.
324 * int (*encode_var)(struct fb_var_screeninfo *var,
325 * struct atafb_par *par);
326 * Fill the 'var' structure based on the values in 'par' and maybe
327 * other values read out of the hardware.
329 * void (*get_par)(struct atafb_par *par)
330 * Fill the hardware's 'par' structure.
331 * !!! Used only by detect() !!!
333 * void (*set_par)(struct atafb_par *par)
334 * Set the hardware according to 'par'.
336 * void (*set_screen_base)(void *s_base)
337 * Set the base address of the displayed frame buffer. Only called
338 * if yres_virtual > yres or xres_virtual > xres.
340 * int (*blank)(int blank_mode)
341 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
342 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
343 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
344 * doesn't support it. Implements VESA suspend and powerdown modes on
345 * hardware that supports disabling hsync/vsync:
346 * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
349 static struct fb_hwswitch {
351 int (*encode_fix)(struct fb_fix_screeninfo *fix,
352 struct atafb_par *par);
353 int (*decode_var)(struct fb_var_screeninfo *var,
354 struct atafb_par *par);
355 int (*encode_var)(struct fb_var_screeninfo *var,
356 struct atafb_par *par);
357 void (*get_par)(struct atafb_par *par);
358 void (*set_par)(struct atafb_par *par);
359 void (*set_screen_base)(void *s_base);
360 int (*blank)(int blank_mode);
361 int (*pan_display)(struct fb_var_screeninfo *var,
362 struct fb_info *info);
365 static char *autodetect_names[] = { "autodetect", NULL };
366 static char *stlow_names[] = { "stlow", NULL };
367 static char *stmid_names[] = { "stmid", "default5", NULL };
368 static char *sthigh_names[] = { "sthigh", "default4", NULL };
369 static char *ttlow_names[] = { "ttlow", NULL };
370 static char *ttmid_names[] = { "ttmid", "default1", NULL };
371 static char *tthigh_names[] = { "tthigh", "default2", NULL };
372 static char *vga2_names[] = { "vga2", NULL };
373 static char *vga4_names[] = { "vga4", NULL };
374 static char *vga16_names[] = { "vga16", "default3", NULL };
375 static char *vga256_names[] = { "vga256", NULL };
376 static char *falh2_names[] = { "falh2", NULL };
377 static char *falh16_names[] = { "falh16", NULL };
379 static char **fb_var_names[] = {
396 static struct fb_var_screeninfo atafb_predefined[] = {
398 * yres_virtual == 0 means use hw-scrolling if possible, else yres
401 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
402 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
403 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
405 320, 200, 320, 0, 0, 0, 4, 0,
406 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
407 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
409 640, 200, 640, 0, 0, 0, 2, 0,
410 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
411 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
413 640, 400, 640, 0, 0, 0, 1, 0,
414 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
415 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
417 320, 480, 320, 0, 0, 0, 8, 0,
418 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
419 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
421 640, 480, 640, 0, 0, 0, 4, 0,
422 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
423 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
425 1280, 960, 1280, 0, 0, 0, 1, 0,
426 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
427 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
429 640, 480, 640, 0, 0, 0, 1, 0,
430 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
431 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
433 640, 480, 640, 0, 0, 0, 2, 0,
434 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
435 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
437 640, 480, 640, 0, 0, 0, 4, 0,
438 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
439 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
441 640, 480, 640, 0, 0, 0, 8, 0,
442 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
443 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
445 896, 608, 896, 0, 0, 0, 1, 0,
446 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
447 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
449 896, 608, 896, 0, 0, 0, 4, 0,
450 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
451 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
454 static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
456 static struct fb_videomode atafb_modedb[] __initdata = {
460 * If you change these, make sure to update DEFMODE_* as well!
468 /* 320x200, 15 kHz, 60 Hz (ST low) */
469 "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
470 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
472 /* 640x200, 15 kHz, 60 Hz (ST medium) */
473 "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
474 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
476 /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
477 "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
478 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
480 /* 320x480, 15 kHz, 60 Hz (TT low) */
481 "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
482 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
484 /* 640x480, 29 kHz, 57 Hz (TT medium) */
485 "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
486 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
488 /* 1280x960, 72 kHz, 72 Hz (TT high) */
489 "tt-high", 57, 1280, 960, 7760, 260, 60, 36, 4, 192, 4,
490 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
498 /* 640x480, 31 kHz, 60 Hz (VGA) */
499 "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
500 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
502 /* 640x400, 31 kHz, 70 Hz (VGA) */
503 "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
504 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
508 * Falcon HiRes Video Modes
512 /* 896x608, 31 kHz, 60 Hz (Falcon High) */
513 "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
514 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
518 #define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb)
520 static char *mode_option __initdata = NULL;
524 #define DEFMODE_TT 5 /* "tt-high" for TT */
525 #define DEFMODE_F30 7 /* "vga70" for Falcon */
526 #define DEFMODE_STE 2 /* "st-high" for ST/E */
527 #define DEFMODE_EXT 6 /* "vga" for external */
530 static int get_video_mode(char *vname)
536 name_list = fb_var_names;
537 for (i = 0; i < num_atafb_predefined; i++) {
542 if (!strcmp(vname, *name))
552 /* ------------------- TT specific functions ---------------------- */
556 static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
560 strcpy(fix->id, "Atari Builtin");
561 fix->smem_start = phys_screen_base;
562 fix->smem_len = screen_len;
563 fix->type = FB_TYPE_INTERLEAVED_PLANES;
565 fix->visual = FB_VISUAL_PSEUDOCOLOR;
566 mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
567 if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
568 fix->type = FB_TYPE_PACKED_PIXELS;
570 if (mode == TT_SHIFTER_TTHIGH)
571 fix->visual = FB_VISUAL_MONO01;
576 fix->line_length = par->next_line;
577 fix->accel = FB_ACCEL_ATARIBLITT;
581 static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
583 int xres = var->xres;
584 int yres = var->yres;
585 int bpp = var->bits_per_pixel;
587 int yres_virtual = var->yres_virtual;
590 if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
592 par->hw.tt.mode = TT_SHIFTER_TTHIGH;
593 xres = sttt_xres * 2;
597 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
600 if (xres > sttt_xres / 2 || yres > tt_yres)
602 par->hw.tt.mode = TT_SHIFTER_TTLOW;
603 xres = sttt_xres / 2;
606 } else if (bpp > 2) {
607 if (xres > sttt_xres || yres > tt_yres)
609 if (xres > sttt_xres / 2 || yres > st_yres / 2) {
610 par->hw.tt.mode = TT_SHIFTER_TTMID;
615 par->hw.tt.mode = TT_SHIFTER_STLOW;
616 xres = sttt_xres / 2;
620 } else if (bpp > 1) {
621 if (xres > sttt_xres || yres > st_yres / 2)
623 par->hw.tt.mode = TT_SHIFTER_STMID;
627 } else if (var->xres > sttt_xres || var->yres > st_yres) {
630 par->hw.tt.mode = TT_SHIFTER_STHIGH;
636 if (yres_virtual <= 0)
638 else if (yres_virtual < yres)
640 if (var->sync & FB_SYNC_EXT)
644 linelen = xres * bpp / 8;
645 if (yres_virtual * linelen > screen_len && screen_len)
647 if (yres * linelen > screen_len && screen_len)
649 if (var->yoffset + yres > yres_virtual && yres_virtual)
651 par->yres_virtual = yres_virtual;
652 par->screen_base = screen_base + var->yoffset * linelen;
653 par->next_line = linelen;
657 static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
660 memset(var, 0, sizeof(struct fb_var_screeninfo));
663 var->red.msb_right = 0;
666 var->pixclock = 31041;
667 var->left_margin = 120; /* these may be incorrect */
668 var->right_margin = 100;
669 var->upper_margin = 8;
670 var->lower_margin = 16;
671 var->hsync_len = 140;
677 if (par->hw.tt.sync & 1)
680 var->sync = FB_SYNC_EXT;
682 switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
683 case TT_SHIFTER_STLOW:
684 var->xres = sttt_xres / 2;
685 var->xres_virtual = sttt_xres_virtual / 2;
686 var->yres = st_yres / 2;
687 var->bits_per_pixel = 4;
689 case TT_SHIFTER_STMID:
690 var->xres = sttt_xres;
691 var->xres_virtual = sttt_xres_virtual;
692 var->yres = st_yres / 2;
693 var->bits_per_pixel = 2;
695 case TT_SHIFTER_STHIGH:
696 var->xres = sttt_xres;
697 var->xres_virtual = sttt_xres_virtual;
699 var->bits_per_pixel = 1;
701 case TT_SHIFTER_TTLOW:
702 var->xres = sttt_xres / 2;
703 var->xres_virtual = sttt_xres_virtual / 2;
705 var->bits_per_pixel = 8;
707 case TT_SHIFTER_TTMID:
708 var->xres = sttt_xres;
709 var->xres_virtual = sttt_xres_virtual;
711 var->bits_per_pixel = 4;
713 case TT_SHIFTER_TTHIGH:
715 var->xres = sttt_xres * 2;
716 var->xres_virtual = sttt_xres_virtual * 2;
717 var->yres = tt_yres * 2;
718 var->bits_per_pixel = 1;
721 var->blue = var->green = var->red;
722 var->transp.offset = 0;
723 var->transp.length = 0;
724 var->transp.msb_right = 0;
725 linelen = var->xres_virtual * var->bits_per_pixel / 8;
727 var->yres_virtual = var->yres;
728 else if (screen_len) {
729 if (par->yres_virtual)
730 var->yres_virtual = par->yres_virtual;
732 /* yres_virtual == 0 means use maximum */
733 var->yres_virtual = screen_len / linelen;
736 var->yres_virtual = 2 * var->yres;
738 var->yres_virtual = var->yres + hwscroll * 16;
742 var->yoffset = (par->screen_base - screen_base) / linelen;
747 var->vmode = FB_VMODE_NONINTERLACED;
751 static void tt_get_par(struct atafb_par *par)
754 par->hw.tt.mode = shifter_tt.tt_shiftmode;
755 par->hw.tt.sync = shifter_st.syncmode;
756 addr = ((shifter_st.bas_hi & 0xff) << 16) |
757 ((shifter_st.bas_md & 0xff) << 8) |
758 ((shifter_st.bas_lo & 0xff));
759 par->screen_base = atari_stram_to_virt(addr);
762 static void tt_set_par(struct atafb_par *par)
764 shifter_tt.tt_shiftmode = par->hw.tt.mode;
765 shifter_st.syncmode = par->hw.tt.sync;
766 /* only set screen_base if really necessary */
767 if (current_par.screen_base != par->screen_base)
768 fbhw->set_screen_base(par->screen_base);
771 static int tt_setcolreg(unsigned int regno, unsigned int red,
772 unsigned int green, unsigned int blue,
773 unsigned int transp, struct fb_info *info)
775 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
779 tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
781 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
782 TT_SHIFTER_STHIGH && regno == 254)
787 static int tt_detect(void)
789 struct atafb_par par;
791 /* Determine the connected monitor: The DMA sound must be
792 * disabled before reading the MFP GPIP, because the Sound
793 * Done Signal and the Monochrome Detect are XORed together!
795 * Even on a TT, we should look if there is a DMA sound. It was
796 * announced that the Eagle is TT compatible, but only the PCM is
799 if (ATARIHW_PRESENT(PCM_8BIT)) {
800 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
801 udelay(20); /* wait a while for things to settle down */
803 mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
806 tt_encode_var(&atafb_predefined[0], &par);
811 #endif /* ATAFB_TT */
813 /* ------------------- Falcon specific functions ---------------------- */
817 static int mon_type; /* Falcon connected monitor */
818 static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
824 static struct pixel_clock {
825 unsigned long f; /* f/[Hz] */
826 unsigned long t; /* t/[ps] (=1/f) */
827 int right, hsync, left; /* standard timing in clock cycles, not pixel */
828 /* hsync initialized in falcon_detect() */
829 int sync_mask; /* or-mask for hw.falcon.sync to set this clock */
830 int control_mask; /* ditto, for hw.falcon.vid_control */
832 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
834 32000000, 31250, 18, 0, 42, 0x0, 0
836 0, 0, 18, 0, 42, 0x1, 0
839 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
840 static int vdl_prescale[4][3] = {
841 { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
844 /* Default hsync timing [mon_type] in picoseconds */
845 static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
847 static inline int hxx_prescale(struct falcon_hw *hw)
849 return hw->ste_mode ? 16
850 : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
853 static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
854 struct atafb_par *par)
856 strcpy(fix->id, "Atari Builtin");
857 fix->smem_start = phys_screen_base;
858 fix->smem_len = screen_len;
859 fix->type = FB_TYPE_INTERLEAVED_PLANES;
861 fix->visual = FB_VISUAL_PSEUDOCOLOR;
865 if (par->hw.falcon.mono) {
866 fix->type = FB_TYPE_PACKED_PIXELS;
868 /* no smooth scrolling with longword aligned video mem */
870 } else if (par->hw.falcon.f_shift & 0x100) {
871 fix->type = FB_TYPE_PACKED_PIXELS;
873 /* Is this ok or should it be DIRECTCOLOR? */
874 fix->visual = FB_VISUAL_TRUECOLOR;
877 fix->line_length = par->next_line;
878 fix->accel = FB_ACCEL_ATARIBLITT;
882 static int falcon_decode_var(struct fb_var_screeninfo *var,
883 struct atafb_par *par)
885 int bpp = var->bits_per_pixel;
886 int xres = var->xres;
887 int yres = var->yres;
888 int xres_virtual = var->xres_virtual;
889 int yres_virtual = var->yres_virtual;
890 int left_margin, right_margin, hsync_len;
891 int upper_margin, lower_margin, vsync_len;
893 int interlace = 0, doubleline = 0;
894 struct pixel_clock *pclock;
895 int plen; /* width of pixel in clock cycles */
900 int hdb_off, hde_off, base_off;
901 int gstart, gend1, gend2, align;
904 Get the video params out of 'var'. If a value doesn't fit, round
905 it up, if it's too big, return EINVAL.
906 Round up in the following order: bits_per_pixel, xres, yres,
907 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
908 horizontal timing, vertical timing.
910 There is a maximum of screen resolution determined by pixelclock
911 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
912 In interlace mode this is " * " *vfmin <= pixelclock.
913 Additional constraints: hfreq.
914 Frequency range for multisync monitors is given via command line.
915 For TV and SM124 both frequencies are fixed.
917 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
918 Y % 16 == 0 to fit 8x16 font
921 Currently interlace and doubleline mode in var are ignored.
922 On SM124 and TV only the standard resolutions can be used.
925 /* Reject uninitialized mode */
926 if (!xres || !yres || !bpp)
929 if (mon_type == F_MON_SM && bpp != 1)
934 par->hw.falcon.f_shift = 0x400;
935 par->hw.falcon.st_shift = 0x200;
936 } else if (bpp <= 2) {
938 par->hw.falcon.f_shift = 0x000;
939 par->hw.falcon.st_shift = 0x100;
940 } else if (bpp <= 4) {
942 par->hw.falcon.f_shift = 0x000;
943 par->hw.falcon.st_shift = 0x000;
944 } else if (bpp <= 8) {
946 par->hw.falcon.f_shift = 0x010;
947 } else if (bpp <= 16) {
948 bpp = 16; /* packed pixel mode */
949 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
952 par->hw.falcon.bpp = bpp;
954 if (mon_type == F_MON_SM || DontCalcRes) {
955 /* Skip all calculations. VGA/TV/SC1224 only supported. */
956 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
958 if (bpp > myvar->bits_per_pixel ||
959 var->xres > myvar->xres ||
960 var->yres > myvar->yres)
962 fbhw->get_par(par); /* Current par will be new par */
963 goto set_screen_base; /* Don't forget this */
966 /* Only some fixed resolutions < 640x400 */
969 else if (xres <= 640 && bpp != 16)
973 else if (yres <= 240)
975 else if (yres <= 400)
978 /* 2 planes must use STE compatibility mode */
979 par->hw.falcon.ste_mode = bpp == 2;
980 par->hw.falcon.mono = bpp == 1;
982 /* Total and visible scanline length must be a multiple of one longword,
983 * this and the console fontwidth yields the alignment for xres and
985 * TODO: this way "odd" fontheights are not supported
987 * Special case in STE mode: blank and graphic positions don't align,
988 * avoid trash at right margin
990 if (par->hw.falcon.ste_mode)
991 xres = (xres + 63) & ~63;
993 xres = (xres + 31) & ~31;
995 xres = (xres + 15) & ~15;
997 yres = (yres + 15) & ~15;
999 yres = (yres + 7) & ~7;
1001 if (xres_virtual < xres)
1002 xres_virtual = xres;
1004 xres_virtual = (xres_virtual + 31) & ~31;
1006 xres_virtual = (xres_virtual + 15) & ~15;
1008 if (yres_virtual <= 0)
1010 else if (yres_virtual < yres)
1011 yres_virtual = yres;
1013 /* backward bug-compatibility */
1014 if (var->pixclock > 1)
1017 par->hw.falcon.line_width = bpp * xres / 16;
1018 par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
1020 /* single or double pixel width */
1021 xstretch = (xres < 640) ? 2 : 1;
1023 #if 0 /* SM124 supports only 640x400, this is rejected above */
1024 if (mon_type == F_MON_SM) {
1025 if (xres != 640 && yres != 400)
1029 /* SM124-mode is special */
1030 par->hw.falcon.ste_mode = 1;
1031 par->hw.falcon.f_shift = 0x000;
1032 par->hw.falcon.st_shift = 0x200;
1033 left_margin = hsync_len = 128 / plen;
1035 /* TODO set all margins */
1038 if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
1039 plen = 2 * xstretch;
1040 if (var->pixclock > f32.t * plen)
1045 if (var->pixclock == 0) {
1046 /* set some minimal margins which center the screen */
1049 hsync_len = pclock->hsync / plen;
1052 vsync_len = interlace ? 3 : 4;
1054 left_margin = var->left_margin;
1055 right_margin = var->right_margin;
1056 hsync_len = var->hsync_len;
1057 upper_margin = var->upper_margin;
1058 lower_margin = var->lower_margin;
1059 vsync_len = var->vsync_len;
1060 if (var->vmode & FB_VMODE_INTERLACED) {
1061 upper_margin = (upper_margin + 1) / 2;
1062 lower_margin = (lower_margin + 1) / 2;
1063 vsync_len = (vsync_len + 1) / 2;
1064 } else if (var->vmode & FB_VMODE_DOUBLE) {
1070 } else { /* F_MON_VGA */
1072 xstretch = 2; /* Double pixel width only for hicolor */
1073 /* Default values are used for vert./hor. timing if no pixelclock given. */
1074 if (var->pixclock == 0) {
1077 /* Choose master pixelclock depending on hor. timing */
1078 plen = 1 * xstretch;
1079 if ((plen * xres + f25.right + f25.hsync + f25.left) *
1080 fb_info.monspecs.hfmin < f25.f)
1082 else if ((plen * xres + f32.right + f32.hsync +
1083 f32.left) * fb_info.monspecs.hfmin < f32.f)
1085 else if ((plen * xres + fext.right + fext.hsync +
1086 fext.left) * fb_info.monspecs.hfmin < fext.f &&
1092 left_margin = pclock->left / plen;
1093 right_margin = pclock->right / plen;
1094 hsync_len = pclock->hsync / plen;
1095 linesize = left_margin + xres + right_margin + hsync_len;
1100 /* Choose largest pixelclock <= wanted clock */
1102 unsigned long pcl = ULONG_MAX;
1104 for (i = 1; i <= 4; i *= 2) {
1105 if (f25.t * i >= var->pixclock &&
1110 if (f32.t * i >= var->pixclock &&
1115 if (fext.t && fext.t * i >= var->pixclock &&
1123 plen = pcl / pclock->t;
1125 left_margin = var->left_margin;
1126 right_margin = var->right_margin;
1127 hsync_len = var->hsync_len;
1128 upper_margin = var->upper_margin;
1129 lower_margin = var->lower_margin;
1130 vsync_len = var->vsync_len;
1131 /* Internal unit is [single lines per (half-)frame] */
1132 if (var->vmode & FB_VMODE_INTERLACED) {
1133 /* # lines in half frame */
1134 /* External unit is [lines per full frame] */
1135 upper_margin = (upper_margin + 1) / 2;
1136 lower_margin = (lower_margin + 1) / 2;
1137 vsync_len = (vsync_len + 1) / 2;
1138 } else if (var->vmode & FB_VMODE_DOUBLE) {
1139 /* External unit is [double lines per frame] */
1145 if (pclock == &fext)
1146 longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1148 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1149 /* this is definitely wrong if bus clock != 32MHz */
1150 if (pclock->f / plen / 8 * bpp > 32000000L)
1156 /* include sync lengths in right/lower margin for all calculations */
1157 right_margin += hsync_len;
1158 lower_margin += vsync_len;
1160 /* ! In all calculations of margins we use # of lines in half frame
1161 * (which is a full frame in non-interlace mode), so we can switch
1162 * between interlace and non-interlace without messing around
1166 /* Set base_offset 128 and video bus width */
1167 par->hw.falcon.vid_control = mon_type | f030_bus_width;
1169 par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */
1170 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1171 par->hw.falcon.vid_control |= VCO_HSYPOS;
1172 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1173 par->hw.falcon.vid_control |= VCO_VSYPOS;
1175 par->hw.falcon.vid_control |= pclock->control_mask;
1176 /* External or internal clock */
1177 par->hw.falcon.sync = pclock->sync_mask | 0x2;
1178 /* Pixellength and prescale */
1179 par->hw.falcon.vid_mode = (2 / plen) << 2;
1181 par->hw.falcon.vid_mode |= VMO_DOUBLE;
1183 par->hw.falcon.vid_mode |= VMO_INTER;
1185 /*********************
1186 * Horizontal timing: unit = [master clock cycles]
1187 * unit of hxx-registers: [master clock cycles * prescale]
1188 * Hxx-registers are 9 bit wide
1190 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1192 * graphic output = hdb & 0x200 ?
1193 * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1194 * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1195 * (this must be a multiple of plen*128/bpp, on VGA pixels
1196 * to the right may be cut off with a bigger right margin)
1198 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1199 * (hdb - hht - 2) * prescale + hdboff :
1200 * hdb * prescale + hdboff
1202 * end of graphics relative to start of 1st halfline =
1203 * (hde + hht + 2) * prescale + hdeoff
1204 *********************/
1205 /* Calculate VIDEL registers */
1207 prescale = hxx_prescale(&par->hw.falcon);
1208 base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1210 /* Offsets depend on video mode */
1211 /* Offsets are in clock cycles, divide by prescale to
1212 * calculate hd[be]-registers
1214 if (par->hw.falcon.f_shift & 0x100) {
1217 hdb_off = (base_off + 16 * plen) + prescale;
1220 hde_off = ((128 / bpp + 2) * plen);
1221 if (par->hw.falcon.ste_mode)
1222 hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1224 hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1227 gstart = (prescale / 2 + plen * left_margin) / prescale;
1228 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1229 gend1 = gstart + roundup(xres, align) * plen / prescale;
1230 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1231 gend2 = gstart + xres * plen / prescale;
1232 par->HHT = plen * (left_margin + xres + right_margin) /
1234 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1236 par->HDB = gstart - hdb_off / prescale;
1239 par->HDB += par->HHT + 2 + 0x200;
1240 par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
1241 par->HBB = gend2 - par->HHT - 2;
1243 /* One more Videl constraint: data fetch of two lines must not overlap */
1244 if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1245 /* if this happens increase margins, decrease hfreq. */
1248 if (hde_off % prescale)
1249 par->HBB++; /* compensate for non matching hde and hbb */
1250 par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1251 if (par->HSS < par->HBB)
1252 par->HSS = par->HBB;
1255 /* check hor. frequency */
1256 hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
1257 if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
1258 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1259 /* Too high -> enlarge margin */
1264 if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1268 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1269 * of the first displayed line!
1270 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1271 * non-interlace, odd in interlace mode for synchronisation.
1272 * Vxx-registers are 11 bit wide
1274 par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1275 par->VDB = par->VBE;
1280 par->VDE <<= 1; /* VDE now half lines per (half-)frame */
1281 par->VDE += par->VDB;
1282 par->VBB = par->VDE;
1283 par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1284 par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
1285 /* vbb,vss,vft must be even in interlace mode */
1292 /* V-frequency check, hope I didn't create any loop here. */
1293 /* Interlace and doubleline are mutually exclusive. */
1294 vfreq = (hfreq * 2) / (par->VFT + 1);
1295 if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1296 /* Too high -> try again with doubleline */
1299 } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1300 /* Too low -> try again with interlace */
1303 } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1304 /* Doubleline too low -> clear doubleline and enlarge margins */
1308 (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
1309 fb_info.monspecs.vfmax;
1312 upper_margin += lines;
1313 lower_margin += lines;
1315 } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1316 /* Doubleline too high -> enlarge margins */
1319 (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1320 fb_info.monspecs.vfmax;
1323 upper_margin += lines;
1324 lower_margin += lines;
1326 } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1327 /* Interlace, too high -> enlarge margins */
1330 (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1331 fb_info.monspecs.vfmax;
1334 upper_margin += lines;
1335 lower_margin += lines;
1337 } else if (vfreq < fb_info.monspecs.vfmin ||
1338 vfreq > fb_info.monspecs.vfmax)
1342 linelen = xres_virtual * bpp / 8;
1343 if (yres_virtual * linelen > screen_len && screen_len)
1345 if (yres * linelen > screen_len && screen_len)
1347 if (var->yoffset + yres > yres_virtual && yres_virtual)
1349 par->yres_virtual = yres_virtual;
1350 par->screen_base = screen_base + var->yoffset * linelen;
1351 par->hw.falcon.xoffset = 0;
1353 par->next_line = linelen;
1358 static int falcon_encode_var(struct fb_var_screeninfo *var,
1359 struct atafb_par *par)
1361 /* !!! only for VGA !!! */
1364 int hdb_off, hde_off, base_off;
1365 struct falcon_hw *hw = &par->hw.falcon;
1367 memset(var, 0, sizeof(struct fb_var_screeninfo));
1368 /* possible frequencies: 25.175 or 32MHz */
1369 var->pixclock = hw->sync & 0x1 ? fext.t :
1370 hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1376 if (hw->vid_control & VCO_HSYPOS)
1377 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1378 if (hw->vid_control & VCO_VSYPOS)
1379 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1381 var->vmode = FB_VMODE_NONINTERLACED;
1382 if (hw->vid_mode & VMO_INTER)
1383 var->vmode |= FB_VMODE_INTERLACED;
1384 if (hw->vid_mode & VMO_DOUBLE)
1385 var->vmode |= FB_VMODE_DOUBLE;
1387 /* visible y resolution:
1388 * Graphics display starts at line VDB and ends at line
1389 * VDE. If interlace mode off unit of VC-registers is
1390 * half lines, else lines.
1392 var->yres = hw->vde - hw->vdb;
1393 if (!(var->vmode & FB_VMODE_INTERLACED))
1395 if (var->vmode & FB_VMODE_DOUBLE)
1399 * to get bpp, we must examine f_shift and st_shift.
1400 * f_shift is valid if any of bits no. 10, 8 or 4
1401 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1402 * if bit 10 set then bit 8 and bit 4 don't care...
1403 * If all these bits are 0 get display depth from st_shift
1404 * (as for ST and STE)
1406 if (hw->f_shift & 0x400) /* 2 colors */
1407 var->bits_per_pixel = 1;
1408 else if (hw->f_shift & 0x100) /* hicolor */
1409 var->bits_per_pixel = 16;
1410 else if (hw->f_shift & 0x010) /* 8 bitplanes */
1411 var->bits_per_pixel = 8;
1412 else if (hw->st_shift == 0)
1413 var->bits_per_pixel = 4;
1414 else if (hw->st_shift == 0x100)
1415 var->bits_per_pixel = 2;
1416 else /* if (hw->st_shift == 0x200) */
1417 var->bits_per_pixel = 1;
1419 var->xres = hw->line_width * 16 / var->bits_per_pixel;
1420 var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1422 var->xres_virtual += 16;
1424 if (var->bits_per_pixel == 16) {
1425 var->red.offset = 11;
1426 var->red.length = 5;
1427 var->red.msb_right = 0;
1428 var->green.offset = 5;
1429 var->green.length = 6;
1430 var->green.msb_right = 0;
1431 var->blue.offset = 0;
1432 var->blue.length = 5;
1433 var->blue.msb_right = 0;
1435 var->red.offset = 0;
1436 var->red.length = hw->ste_mode ? 4 : 6;
1437 if (var->red.length > var->bits_per_pixel)
1438 var->red.length = var->bits_per_pixel;
1439 var->red.msb_right = 0;
1441 var->blue = var->green = var->red;
1443 var->transp.offset = 0;
1444 var->transp.length = 0;
1445 var->transp.msb_right = 0;
1447 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1449 if (par->yres_virtual)
1450 var->yres_virtual = par->yres_virtual;
1452 /* yres_virtual == 0 means use maximum */
1453 var->yres_virtual = screen_len / linelen;
1456 var->yres_virtual = 2 * var->yres;
1458 var->yres_virtual = var->yres + hwscroll * 16;
1460 var->xoffset = 0; /* TODO change this */
1463 prescale = hxx_prescale(hw);
1464 plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1465 base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1466 if (hw->f_shift & 0x100) {
1468 hdb_off = (base_off + 16 * plen) + prescale;
1470 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1472 hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1475 hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1479 /* Right margin includes hsync */
1480 var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1481 (hw->hdb & 0x200 ? 2 + hw->hht : 0));
1482 if (hw->ste_mode || mon_type != F_MON_VGA)
1483 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1485 /* can't use this in ste_mode, because hbb is +1 off */
1486 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1487 var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1489 /* Lower margin includes vsync */
1490 var->upper_margin = hw->vdb / 2; /* round down to full lines */
1491 var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2; /* round up */
1492 var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2; /* round up */
1493 if (var->vmode & FB_VMODE_INTERLACED) {
1494 var->upper_margin *= 2;
1495 var->lower_margin *= 2;
1496 var->vsync_len *= 2;
1497 } else if (var->vmode & FB_VMODE_DOUBLE) {
1498 var->upper_margin = (var->upper_margin + 1) / 2;
1499 var->lower_margin = (var->lower_margin + 1) / 2;
1500 var->vsync_len = (var->vsync_len + 1) / 2;
1503 var->pixclock *= plen;
1504 var->left_margin /= plen;
1505 var->right_margin /= plen;
1506 var->hsync_len /= plen;
1508 var->right_margin -= var->hsync_len;
1509 var->lower_margin -= var->vsync_len;
1512 var->yoffset = (par->screen_base - screen_base) / linelen;
1515 var->nonstd = 0; /* what is this for? */
1520 static int f_change_mode;
1521 static struct falcon_hw f_new_mode;
1522 static int f_pan_display;
1524 static void falcon_get_par(struct atafb_par *par)
1527 struct falcon_hw *hw = &par->hw.falcon;
1529 hw->line_width = shifter_f030.scn_width;
1530 hw->line_offset = shifter_f030.off_next;
1531 hw->st_shift = videl.st_shift & 0x300;
1532 hw->f_shift = videl.f_shift;
1533 hw->vid_control = videl.control;
1534 hw->vid_mode = videl.mode;
1535 hw->sync = shifter_st.syncmode & 0x1;
1536 hw->xoffset = videl.xoffset & 0xf;
1537 hw->hht = videl.hht;
1538 hw->hbb = videl.hbb;
1539 hw->hbe = videl.hbe;
1540 hw->hdb = videl.hdb;
1541 hw->hde = videl.hde;
1542 hw->hss = videl.hss;
1543 hw->vft = videl.vft;
1544 hw->vbb = videl.vbb;
1545 hw->vbe = videl.vbe;
1546 hw->vdb = videl.vdb;
1547 hw->vde = videl.vde;
1548 hw->vss = videl.vss;
1550 addr = (shifter_st.bas_hi & 0xff) << 16 |
1551 (shifter_st.bas_md & 0xff) << 8 |
1552 (shifter_st.bas_lo & 0xff);
1553 par->screen_base = atari_stram_to_virt(addr);
1555 /* derived parameters */
1556 hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
1557 hw->mono = (hw->f_shift & 0x400) ||
1558 ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
1561 static void falcon_set_par(struct atafb_par *par)
1565 /* only set screen_base if really necessary */
1566 if (current_par.screen_base != par->screen_base)
1567 fbhw->set_screen_base(par->screen_base);
1569 /* Don't touch any other registers if we keep the default resolution */
1573 /* Tell vbl-handler to change video mode.
1574 * We change modes only on next VBL, to avoid desynchronisation
1575 * (a shift to the right and wrap around by a random number of pixels
1576 * in all monochrome modes).
1577 * This seems to work on my Falcon.
1579 f_new_mode = par->hw.falcon;
1583 static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
1585 struct falcon_hw *hw = &f_new_mode;
1587 if (f_change_mode) {
1590 if (hw->sync & 0x1) {
1591 /* Enable external pixelclock. This code only for ScreenWonder */
1592 *(volatile unsigned short *)0xffff9202 = 0xffbf;
1594 /* Turn off external clocks. Read sets all output bits to 1. */
1595 *(volatile unsigned short *)0xffff9202;
1597 shifter_st.syncmode = hw->sync;
1599 videl.hht = hw->hht;
1600 videl.hbb = hw->hbb;
1601 videl.hbe = hw->hbe;
1602 videl.hdb = hw->hdb;
1603 videl.hde = hw->hde;
1604 videl.hss = hw->hss;
1605 videl.vft = hw->vft;
1606 videl.vbb = hw->vbb;
1607 videl.vbe = hw->vbe;
1608 videl.vdb = hw->vdb;
1609 videl.vde = hw->vde;
1610 videl.vss = hw->vss;
1612 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1614 videl.st_shift = hw->st_shift; /* write enables STE palette */
1617 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1618 * Writing 0 to f_shift enables 4 plane Falcon mode but
1619 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1620 * with Falcon palette.
1623 /* now back to Falcon palette mode */
1624 videl.f_shift = hw->f_shift;
1626 /* writing to st_shift changed scn_width and vid_mode */
1627 videl.xoffset = hw->xoffset;
1628 shifter_f030.scn_width = hw->line_width;
1629 shifter_f030.off_next = hw->line_offset;
1630 videl.control = hw->vid_control;
1631 videl.mode = hw->vid_mode;
1633 if (f_pan_display) {
1635 videl.xoffset = current_par.hw.falcon.xoffset;
1636 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1641 static int falcon_pan_display(struct fb_var_screeninfo *var,
1642 struct fb_info *info)
1644 struct atafb_par *par = (struct atafb_par *)info->par;
1647 int bpp = info->var.bits_per_pixel;
1650 var->xoffset = round_up(var->xoffset, 32);
1652 par->hw.falcon.xoffset = var->xoffset & 15;
1654 par->hw.falcon.xoffset = 0;
1655 var->xoffset = round_up(var->xoffset, 2);
1657 par->hw.falcon.line_offset = bpp *
1658 (info->var.xres_virtual - info->var.xres) / 16;
1659 if (par->hw.falcon.xoffset)
1660 par->hw.falcon.line_offset -= bpp;
1661 xoffset = var->xoffset - par->hw.falcon.xoffset;
1663 par->screen_base = screen_base +
1664 (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
1665 if (fbhw->set_screen_base)
1666 fbhw->set_screen_base(par->screen_base);
1668 return -EINVAL; /* shouldn't happen */
1673 static int falcon_setcolreg(unsigned int regno, unsigned int red,
1674 unsigned int green, unsigned int blue,
1675 unsigned int transp, struct fb_info *info)
1679 f030_col[regno] = (((red & 0xfc00) << 16) |
1680 ((green & 0xfc00) << 8) |
1681 ((blue & 0xfc00) >> 8));
1683 shifter_tt.color_reg[regno] =
1684 ((((red & 0xe000) >> 13) | ((red & 0x1000) >> 12)) << 8) |
1685 ((((green & 0xe000) >> 13) | ((green & 0x1000) >> 12)) << 4) |
1686 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1687 ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
1688 ((green & 0xfc00) >> 5) |
1689 ((blue & 0xf800) >> 11));
1694 static int falcon_blank(int blank_mode)
1696 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1697 * so VIDEL doesn't hog the bus while saving.
1698 * (this may affect usleep()).
1700 int vdb, vss, hbe, hss;
1702 if (mon_type == F_MON_SM) /* this doesn't work on SM124 */
1705 vdb = current_par.VDB;
1706 vss = current_par.VSS;
1707 hbe = current_par.HBE;
1708 hss = current_par.HSS;
1710 if (blank_mode >= 1) {
1711 /* disable graphics output (this speeds up the CPU) ... */
1712 vdb = current_par.VFT + 1;
1713 /* ... and blank all lines */
1714 hbe = current_par.HHT + 2;
1716 /* use VESA suspend modes on VGA monitors */
1717 if (mon_type == F_MON_VGA) {
1718 if (blank_mode == 2 || blank_mode == 4)
1719 vss = current_par.VFT + 1;
1720 if (blank_mode == 3 || blank_mode == 4)
1721 hss = current_par.HHT + 2;
1732 static int falcon_detect(void)
1734 struct atafb_par par;
1737 /* Determine connected monitor and set monitor parameters */
1738 fhw = *(unsigned char *)0xffff8006;
1739 mon_type = fhw >> 6 & 0x3;
1740 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1741 f030_bus_width = fhw << 6 & 0x80;
1744 fb_info.monspecs.vfmin = 70;
1745 fb_info.monspecs.vfmax = 72;
1746 fb_info.monspecs.hfmin = 35713;
1747 fb_info.monspecs.hfmax = 35715;
1752 fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
1753 fb_info.monspecs.vfmax = 60;
1754 fb_info.monspecs.hfmin = 15620;
1755 fb_info.monspecs.hfmax = 15755;
1758 /* initialize hsync-len */
1759 f25.hsync = h_syncs[mon_type] / f25.t;
1760 f32.hsync = h_syncs[mon_type] / f32.t;
1762 fext.hsync = h_syncs[mon_type] / fext.t;
1764 falcon_get_par(&par);
1765 falcon_encode_var(&atafb_predefined[0], &par);
1767 /* Detected mode is always the "autodetect" slot */
1771 #endif /* ATAFB_FALCON */
1773 /* ------------------- ST(E) specific functions ---------------------- */
1777 static int stste_encode_fix(struct fb_fix_screeninfo *fix,
1778 struct atafb_par *par)
1782 strcpy(fix->id, "Atari Builtin");
1783 fix->smem_start = phys_screen_base;
1784 fix->smem_len = screen_len;
1785 fix->type = FB_TYPE_INTERLEAVED_PLANES;
1787 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1788 mode = par->hw.st.mode & 3;
1789 if (mode == ST_HIGH) {
1790 fix->type = FB_TYPE_PACKED_PIXELS;
1792 fix->visual = FB_VISUAL_MONO10;
1794 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1802 fix->line_length = par->next_line;
1803 fix->accel = FB_ACCEL_ATARIBLITT;
1807 static int stste_decode_var(struct fb_var_screeninfo *var,
1808 struct atafb_par *par)
1810 int xres = var->xres;
1811 int yres = var->yres;
1812 int bpp = var->bits_per_pixel;
1814 int yres_virtual = var->yres_virtual;
1817 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1819 par->hw.st.mode = ST_HIGH;
1824 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1827 if (xres > sttt_xres / 2 || yres > st_yres / 2)
1829 par->hw.st.mode = ST_LOW;
1830 xres = sttt_xres / 2;
1833 } else if (bpp > 1) {
1834 if (xres > sttt_xres || yres > st_yres / 2)
1836 par->hw.st.mode = ST_MID;
1843 if (yres_virtual <= 0)
1845 else if (yres_virtual < yres)
1846 yres_virtual = yres;
1847 if (var->sync & FB_SYNC_EXT)
1848 par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
1850 par->hw.st.sync = (par->hw.st.sync & ~1);
1851 linelen = xres * bpp / 8;
1852 if (yres_virtual * linelen > screen_len && screen_len)
1854 if (yres * linelen > screen_len && screen_len)
1856 if (var->yoffset + yres > yres_virtual && yres_virtual)
1858 par->yres_virtual = yres_virtual;
1859 par->screen_base = screen_base + var->yoffset * linelen;
1860 par->next_line = linelen;
1864 static int stste_encode_var(struct fb_var_screeninfo *var,
1865 struct atafb_par *par)
1868 memset(var, 0, sizeof(struct fb_var_screeninfo));
1869 var->red.offset = 0;
1870 var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1871 var->red.msb_right = 0;
1874 var->pixclock = 31041;
1875 var->left_margin = 120; /* these are incorrect */
1876 var->right_margin = 100;
1877 var->upper_margin = 8;
1878 var->lower_margin = 16;
1879 var->hsync_len = 140;
1880 var->vsync_len = 30;
1885 if (!(par->hw.st.sync & 1))
1888 var->sync = FB_SYNC_EXT;
1890 switch (par->hw.st.mode & 3) {
1892 var->xres = sttt_xres / 2;
1893 var->yres = st_yres / 2;
1894 var->bits_per_pixel = 4;
1897 var->xres = sttt_xres;
1898 var->yres = st_yres / 2;
1899 var->bits_per_pixel = 2;
1902 var->xres = sttt_xres;
1903 var->yres = st_yres;
1904 var->bits_per_pixel = 1;
1907 var->blue = var->green = var->red;
1908 var->transp.offset = 0;
1909 var->transp.length = 0;
1910 var->transp.msb_right = 0;
1911 var->xres_virtual = sttt_xres_virtual;
1912 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1913 ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
1916 var->yres_virtual = var->yres;
1917 else if (screen_len) {
1918 if (par->yres_virtual)
1919 var->yres_virtual = par->yres_virtual;
1921 /* yres_virtual == 0 means use maximum */
1922 var->yres_virtual = screen_len / linelen;
1925 var->yres_virtual = 2 * var->yres;
1927 var->yres_virtual = var->yres + hwscroll * 16;
1931 var->yoffset = (par->screen_base - screen_base) / linelen;
1936 var->vmode = FB_VMODE_NONINTERLACED;
1940 static void stste_get_par(struct atafb_par *par)
1943 par->hw.st.mode = shifter_tt.st_shiftmode;
1944 par->hw.st.sync = shifter_st.syncmode;
1945 addr = ((shifter_st.bas_hi & 0xff) << 16) |
1946 ((shifter_st.bas_md & 0xff) << 8);
1947 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1948 addr |= (shifter_st.bas_lo & 0xff);
1949 par->screen_base = atari_stram_to_virt(addr);
1952 static void stste_set_par(struct atafb_par *par)
1954 shifter_tt.st_shiftmode = par->hw.st.mode;
1955 shifter_st.syncmode = par->hw.st.sync;
1956 /* only set screen_base if really necessary */
1957 if (current_par.screen_base != par->screen_base)
1958 fbhw->set_screen_base(par->screen_base);
1961 static int stste_setcolreg(unsigned int regno, unsigned int red,
1962 unsigned int green, unsigned int blue,
1963 unsigned int transp, struct fb_info *info)
1970 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1971 shifter_tt.color_reg[regno] =
1972 ((((red & 0xe) >> 1) | ((red & 1) << 3)) << 8) |
1973 ((((green & 0xe) >> 1) | ((green & 1) << 3)) << 4) |
1974 ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1976 shifter_tt.color_reg[regno] =
1977 ((red & 0xe) << 7) |
1978 ((green & 0xe) << 3) |
1979 ((blue & 0xe) >> 1);
1983 static int stste_detect(void)
1985 struct atafb_par par;
1987 /* Determine the connected monitor: The DMA sound must be
1988 * disabled before reading the MFP GPIP, because the Sound
1989 * Done Signal and the Monochrome Detect are XORed together!
1991 if (ATARIHW_PRESENT(PCM_8BIT)) {
1992 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1993 udelay(20); /* wait a while for things to settle down */
1995 mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
1997 stste_get_par(&par);
1998 stste_encode_var(&atafb_predefined[0], &par);
2000 if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2005 static void stste_set_screen_base(void *s_base)
2008 addr = atari_stram_to_phys(s_base);
2009 /* Setup Screen Memory */
2010 shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2011 shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2012 if (ATARIHW_PRESENT(EXTD_SHIFTER))
2013 shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
2016 #endif /* ATAFB_STE */
2018 /* Switching the screen size should be done during vsync, otherwise
2019 * the margins may get messed up. This is a well known problem of
2020 * the ST's video system.
2022 * Unfortunately there is hardly any way to find the vsync, as the
2023 * vertical blank interrupt is no longer in time on machines with
2024 * overscan type modifications.
2026 * We can, however, use Timer B to safely detect the black shoulder,
2027 * but then we've got to guess an appropriate delay to find the vsync.
2028 * This might not work on every machine.
2030 * martin_rogge @ ki.maus.de, 8th Aug 1995
2033 #define LINE_DELAY (mono_moni ? 30 : 70)
2034 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2036 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2037 static void st_ovsc_switch(void)
2039 unsigned long flags;
2040 register unsigned char old, new;
2042 if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2044 local_irq_save(flags);
2046 st_mfp.tim_ct_b = 0x10;
2047 st_mfp.active_edge |= 8;
2048 st_mfp.tim_ct_b = 0;
2049 st_mfp.tim_dt_b = 0xf0;
2050 st_mfp.tim_ct_b = 8;
2051 while (st_mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2053 new = st_mfp.tim_dt_b;
2057 new = st_mfp.tim_dt_b;
2058 } while (old != new);
2059 st_mfp.tim_ct_b = 0x10;
2062 if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2063 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2064 if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2065 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2066 if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2067 sound_ym.rd_data_reg_sel = 14;
2068 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2069 ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2070 ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2072 local_irq_restore(flags);
2075 /* ------------------- External Video ---------------------- */
2079 static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
2081 strcpy(fix->id, "Unknown Extern");
2082 fix->smem_start = external_addr;
2083 fix->smem_len = PAGE_ALIGN(external_len);
2084 if (external_depth == 1) {
2085 fix->type = FB_TYPE_PACKED_PIXELS;
2086 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2087 * for "normal" and "inverted", rsp., in the monochrome case */
2089 (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2090 external_pmode == FB_TYPE_PACKED_PIXELS) ?
2091 FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
2093 /* Use STATIC if we don't know how to access color registers */
2094 int visual = external_vgaiobase ?
2095 FB_VISUAL_PSEUDOCOLOR :
2096 FB_VISUAL_STATIC_PSEUDOCOLOR;
2097 switch (external_pmode) {
2098 case -1: /* truecolor */
2099 fix->type = FB_TYPE_PACKED_PIXELS;
2100 fix->visual = FB_VISUAL_TRUECOLOR;
2102 case FB_TYPE_PACKED_PIXELS:
2103 fix->type = FB_TYPE_PACKED_PIXELS;
2104 fix->visual = visual;
2106 case FB_TYPE_PLANES:
2107 fix->type = FB_TYPE_PLANES;
2108 fix->visual = visual;
2110 case FB_TYPE_INTERLEAVED_PLANES:
2111 fix->type = FB_TYPE_INTERLEAVED_PLANES;
2113 fix->visual = visual;
2120 fix->line_length = par->next_line;
2124 static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2126 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2128 if (var->bits_per_pixel > myvar->bits_per_pixel ||
2129 var->xres > myvar->xres ||
2130 var->xres_virtual > myvar->xres_virtual ||
2131 var->yres > myvar->yres ||
2136 par->next_line = external_xres_virtual * external_depth / 8;
2140 static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2142 memset(var, 0, sizeof(struct fb_var_screeninfo));
2143 var->red.offset = 0;
2144 var->red.length = (external_pmode == -1) ? external_depth / 3 :
2145 (external_vgaiobase ? external_bitspercol : 0);
2146 var->red.msb_right = 0;
2149 var->pixclock = 31041;
2150 var->left_margin = 120; /* these are surely incorrect */
2151 var->right_margin = 100;
2152 var->upper_margin = 8;
2153 var->lower_margin = 16;
2154 var->hsync_len = 140;
2155 var->vsync_len = 30;
2162 var->xres = external_xres;
2163 var->yres = external_yres;
2164 var->xres_virtual = external_xres_virtual;
2165 var->bits_per_pixel = external_depth;
2167 var->blue = var->green = var->red;
2168 var->transp.offset = 0;
2169 var->transp.length = 0;
2170 var->transp.msb_right = 0;
2171 var->yres_virtual = var->yres;
2176 var->vmode = FB_VMODE_NONINTERLACED;
2180 static void ext_get_par(struct atafb_par *par)
2182 par->screen_base = external_screen_base;
2185 static void ext_set_par(struct atafb_par *par)
2189 #define OUTB(port,val) \
2190 *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2192 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2195 unsigned char tmp = INB(0x3da); \
2199 static int ext_setcolreg(unsigned int regno, unsigned int red,
2200 unsigned int green, unsigned int blue,
2201 unsigned int transp, struct fb_info *info)
2203 unsigned char colmask = (1 << external_bitspercol) - 1;
2205 if (!external_vgaiobase)
2211 switch (external_card_type) {
2215 OUTB(0x3c9, red & colmask);
2217 OUTB(0x3c9, green & colmask);
2219 OUTB(0x3c9, blue & colmask);
2224 OUTB((MV300_reg[regno] << 2) + 1, red);
2225 OUTB((MV300_reg[regno] << 2) + 1, green);
2226 OUTB((MV300_reg[regno] << 2) + 1, blue);
2234 static int ext_detect(void)
2236 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2237 struct atafb_par dummy_par;
2239 myvar->xres = external_xres;
2240 myvar->xres_virtual = external_xres_virtual;
2241 myvar->yres = external_yres;
2242 myvar->bits_per_pixel = external_depth;
2243 ext_encode_var(myvar, &dummy_par);
2247 #endif /* ATAFB_EXT */
2249 /* ------ This is the same for most hardware types -------- */
2251 static void set_screen_base(void *s_base)
2255 addr = atari_stram_to_phys(s_base);
2256 /* Setup Screen Memory */
2257 shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2258 shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2259 shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
2262 static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2264 struct atafb_par *par = (struct atafb_par *)info->par;
2266 if (!fbhw->set_screen_base ||
2267 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2269 var->xoffset = round_up(var->xoffset, 16);
2270 par->screen_base = screen_base +
2271 (var->yoffset * info->var.xres_virtual + var->xoffset)
2272 * info->var.bits_per_pixel / 8;
2273 fbhw->set_screen_base(par->screen_base);
2277 /* ------------ Interfaces to hardware functions ------------ */
2280 static struct fb_hwswitch tt_switch = {
2281 .detect = tt_detect,
2282 .encode_fix = tt_encode_fix,
2283 .decode_var = tt_decode_var,
2284 .encode_var = tt_encode_var,
2285 .get_par = tt_get_par,
2286 .set_par = tt_set_par,
2287 .set_screen_base = set_screen_base,
2288 .pan_display = pan_display,
2293 static struct fb_hwswitch falcon_switch = {
2294 .detect = falcon_detect,
2295 .encode_fix = falcon_encode_fix,
2296 .decode_var = falcon_decode_var,
2297 .encode_var = falcon_encode_var,
2298 .get_par = falcon_get_par,
2299 .set_par = falcon_set_par,
2300 .set_screen_base = set_screen_base,
2301 .blank = falcon_blank,
2302 .pan_display = falcon_pan_display,
2307 static struct fb_hwswitch st_switch = {
2308 .detect = stste_detect,
2309 .encode_fix = stste_encode_fix,
2310 .decode_var = stste_decode_var,
2311 .encode_var = stste_encode_var,
2312 .get_par = stste_get_par,
2313 .set_par = stste_set_par,
2314 .set_screen_base = stste_set_screen_base,
2315 .pan_display = pan_display
2320 static struct fb_hwswitch ext_switch = {
2321 .detect = ext_detect,
2322 .encode_fix = ext_encode_fix,
2323 .decode_var = ext_decode_var,
2324 .encode_var = ext_encode_var,
2325 .get_par = ext_get_par,
2326 .set_par = ext_set_par,
2330 static void ata_get_par(struct atafb_par *par)
2332 if (current_par_valid)
2338 static void ata_set_par(struct atafb_par *par)
2342 current_par_valid = 1;
2346 /* =========================================================== */
2347 /* ============== Hardware Independent Functions ============= */
2348 /* =========================================================== */
2350 /* used for hardware scrolling */
2352 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2355 struct atafb_par par;
2357 err = fbhw->decode_var(var, &par);
2360 activate = var->activate;
2361 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2363 fbhw->encode_var(var, &par);
2364 var->activate = activate;
2368 /* fbhw->encode_fix() must be called with fb_info->mm_lock held
2369 * if it is called after the register_framebuffer() - not a case here
2371 static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2373 struct atafb_par par;
2375 // Get fix directly (case con == -1 before)??
2376 err = fbhw->decode_var(&info->var, &par);
2379 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2380 err = fbhw->encode_fix(fix, &par);
2384 static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
2386 struct atafb_par par;
2389 fbhw->encode_var(var, &par);
2394 // No longer called by fbcon!
2395 // Still called by set_var internally
2397 static void atafb_set_disp(struct fb_info *info)
2399 atafb_get_var(&info->var, info);
2400 atafb_get_fix(&info->fix, info);
2402 /* Note: smem_start derives from phys_screen_base, not screen_base! */
2403 info->screen_base = (external_addr ? external_screen_base :
2404 atari_stram_to_virt(info->fix.smem_start));
2408 atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2410 int xoffset = var->xoffset;
2411 int yoffset = var->yoffset;
2414 if (var->vmode & FB_VMODE_YWRAP) {
2415 if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
2418 if (xoffset + info->var.xres > info->var.xres_virtual ||
2419 yoffset + info->var.yres > info->var.yres_virtual)
2423 if (fbhw->pan_display) {
2424 err = fbhw->pan_display(var, info);
2430 info->var.xoffset = xoffset;
2431 info->var.yoffset = yoffset;
2433 if (var->vmode & FB_VMODE_YWRAP)
2434 info->var.vmode |= FB_VMODE_YWRAP;
2436 info->var.vmode &= ~FB_VMODE_YWRAP;
2442 * generic drawing routines; imageblit needs updating for image depth > 1
2445 #if BITS_PER_LONG == 32
2446 #define BYTES_PER_LONG 4
2447 #define SHIFT_PER_LONG 5
2448 #elif BITS_PER_LONG == 64
2449 #define BYTES_PER_LONG 8
2450 #define SHIFT_PER_LONG 6
2452 #define Please update me
2456 static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
2458 struct atafb_par *par = (struct atafb_par *)info->par;
2462 if (!rect->width || !rect->height)
2466 if (info->var.bits_per_pixel == 16) {
2467 cfb_fillrect(info, rect);
2473 * We could use hardware clipping but on many cards you get around
2474 * hardware clipping by writing to framebuffer directly.
2476 x2 = rect->dx + rect->width;
2477 y2 = rect->dy + rect->height;
2478 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2479 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2480 width = x2 - rect->dx;
2481 height = y2 - rect->dy;
2483 if (info->var.bits_per_pixel == 1)
2484 atafb_mfb_fillrect(info, par->next_line, rect->color,
2485 rect->dy, rect->dx, height, width);
2486 else if (info->var.bits_per_pixel == 2)
2487 atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
2488 rect->dy, rect->dx, height, width);
2489 else if (info->var.bits_per_pixel == 4)
2490 atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
2491 rect->dy, rect->dx, height, width);
2493 atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
2494 rect->dy, rect->dx, height, width);
2499 static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2501 struct atafb_par *par = (struct atafb_par *)info->par;
2503 u32 dx, dy, sx, sy, width, height;
2507 if (info->var.bits_per_pixel == 16) {
2508 cfb_copyarea(info, area);
2513 /* clip the destination */
2514 x2 = area->dx + area->width;
2515 y2 = area->dy + area->height;
2516 dx = area->dx > 0 ? area->dx : 0;
2517 dy = area->dy > 0 ? area->dy : 0;
2518 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2519 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2523 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2527 sx = area->sx + (dx - area->dx);
2528 sy = area->sy + (dy - area->dy);
2530 /* the source must be completely inside the virtual screen */
2531 if (sx + width > info->var.xres_virtual ||
2532 sy + height > info->var.yres_virtual)
2535 if (dy > sy || (dy == sy && dx > sx)) {
2541 if (info->var.bits_per_pixel == 1)
2542 atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2543 else if (info->var.bits_per_pixel == 2)
2544 atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2545 else if (info->var.bits_per_pixel == 4)
2546 atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2548 atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2553 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2555 struct atafb_par *par = (struct atafb_par *)info->par;
2560 u32 dx, dy, width, height, pitch;
2563 if (info->var.bits_per_pixel == 16) {
2564 cfb_imageblit(info, image);
2570 * We could use hardware clipping but on many cards you get around
2571 * hardware clipping by writing to framebuffer directly like we are
2574 x2 = image->dx + image->width;
2575 y2 = image->dy + image->height;
2578 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2579 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2583 if (image->depth == 1) {
2584 // used for font data
2585 dst = (unsigned long *)
2586 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2587 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2588 dst_idx += dy * par->next_line * 8 + dx;
2590 pitch = (image->width + 7) / 8;
2593 if (info->var.bits_per_pixel == 1)
2594 atafb_mfb_linefill(info, par->next_line,
2596 image->bg_color, image->fg_color);
2597 else if (info->var.bits_per_pixel == 2)
2598 atafb_iplan2p2_linefill(info, par->next_line,
2600 image->bg_color, image->fg_color);
2601 else if (info->var.bits_per_pixel == 4)
2602 atafb_iplan2p4_linefill(info, par->next_line,
2604 image->bg_color, image->fg_color);
2606 atafb_iplan2p8_linefill(info, par->next_line,
2608 image->bg_color, image->fg_color);
2613 c2p_iplan2(info->screen_base, image->data, dx, dy, width,
2614 height, par->next_line, image->width,
2615 info->var.bits_per_pixel);
2620 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2623 #ifdef FBCMD_GET_CURRENTPAR
2624 case FBCMD_GET_CURRENTPAR:
2625 if (copy_to_user((void *)arg, (void *)¤t_par,
2626 sizeof(struct atafb_par)))
2630 #ifdef FBCMD_SET_CURRENTPAR
2631 case FBCMD_SET_CURRENTPAR:
2632 if (copy_from_user((void *)¤t_par, (void *)arg,
2633 sizeof(struct atafb_par)))
2635 ata_set_par(¤t_par);
2642 /* (un)blank/poweroff
2649 static int atafb_blank(int blank, struct fb_info *info)
2651 unsigned short black[16];
2652 struct fb_cmap cmap;
2653 if (fbhw->blank && !fbhw->blank(blank))
2656 memset(black, 0, 16 * sizeof(unsigned short));
2663 fb_set_cmap(&cmap, info);
2667 do_install_cmap(info);
2673 * New fbcon interface ...
2676 /* check var by decoding var into hw par, rounding if necessary,
2677 * then encoding hw par back into new, validated var */
2678 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2681 struct atafb_par par;
2683 /* Validate wanted screen parameters */
2684 // if ((err = ata_decode_var(var, &par)))
2685 err = fbhw->decode_var(var, &par);
2689 /* Encode (possibly rounded) screen parameters */
2690 fbhw->encode_var(var, &par);
2694 /* actually set hw par by decoding var, then setting hardware from
2695 * hw par just decoded */
2696 static int atafb_set_par(struct fb_info *info)
2698 struct atafb_par *par = (struct atafb_par *)info->par;
2700 /* Decode wanted screen parameters */
2701 fbhw->decode_var(&info->var, par);
2702 mutex_lock(&info->mm_lock);
2703 fbhw->encode_fix(&info->fix, par);
2704 mutex_unlock(&info->mm_lock);
2706 /* Set new videomode */
2713 static struct fb_ops atafb_ops = {
2714 .owner = THIS_MODULE,
2715 .fb_check_var = atafb_check_var,
2716 .fb_set_par = atafb_set_par,
2717 .fb_blank = atafb_blank,
2718 .fb_pan_display = atafb_pan_display,
2719 .fb_fillrect = atafb_fillrect,
2720 .fb_copyarea = atafb_copyarea,
2721 .fb_imageblit = atafb_imageblit,
2722 .fb_ioctl = atafb_ioctl,
2725 static void check_default_par(int detected_mode)
2727 char default_name[10];
2729 struct fb_var_screeninfo var;
2730 unsigned long min_mem;
2732 /* First try the user supplied mode */
2734 var = atafb_predefined[default_par - 1];
2735 var.activate = FB_ACTIVATE_TEST;
2736 if (do_fb_set_var(&var, 1))
2737 default_par = 0; /* failed */
2739 /* Next is the autodetected one */
2741 var = atafb_predefined[detected_mode - 1]; /* autodetect */
2742 var.activate = FB_ACTIVATE_TEST;
2743 if (!do_fb_set_var(&var, 1))
2744 default_par = detected_mode;
2746 /* If that also failed, try some default modes... */
2748 /* try default1, default2... */
2749 for (i = 1; i < 10; i++) {
2750 sprintf(default_name,"default%d", i);
2751 default_par = get_video_mode(default_name);
2753 panic("can't set default video mode");
2754 var = atafb_predefined[default_par - 1];
2755 var.activate = FB_ACTIVATE_TEST;
2756 if (!do_fb_set_var(&var,1))
2760 min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
2761 if (default_mem_req < min_mem)
2762 default_mem_req = min_mem;
2766 static void __init atafb_setup_ext(char *spec)
2768 int xres, xres_virtual, yres, depth, planes;
2769 unsigned long addr, len;
2772 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2774 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2775 * [;<xres-virtual>]]]]]
2778 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2780 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2782 p = strsep(&spec, ";");
2785 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2789 p = strsep(&spec, ";");
2792 yres = simple_strtoul(p, NULL, 10);
2796 p = strsep(&spec, ";");
2799 depth = simple_strtoul(p, NULL, 10);
2800 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2801 depth != 16 && depth != 24)
2804 p = strsep(&spec, ";");
2808 planes = FB_TYPE_INTERLEAVED_PLANES;
2810 planes = FB_TYPE_PACKED_PIXELS;
2812 planes = FB_TYPE_PLANES;
2814 planes = -1; /* true color */
2818 p = strsep(&spec, ";");
2821 addr = simple_strtoul(p, NULL, 0);
2823 p = strsep(&spec, ";");
2825 len = xres * yres * depth / 8;
2827 len = simple_strtoul(p, NULL, 0);
2829 p = strsep(&spec, ";");
2831 external_vgaiobase = simple_strtoul(p, NULL, 0);
2833 p = strsep(&spec, ";");
2835 external_bitspercol = simple_strtoul(p, NULL, 0);
2836 if (external_bitspercol > 8)
2837 external_bitspercol = 8;
2838 else if (external_bitspercol < 1)
2839 external_bitspercol = 1;
2842 p = strsep(&spec, ";");
2844 if (!strcmp(p, "vga"))
2845 external_card_type = IS_VGA;
2846 if (!strcmp(p, "mv300"))
2847 external_card_type = IS_MV300;
2850 p = strsep(&spec, ";");
2852 xres_virtual = simple_strtoul(p, NULL, 10);
2853 if (xres_virtual < xres)
2854 xres_virtual = xres;
2855 if (xres_virtual * yres * depth / 8 > len)
2856 len = xres_virtual * yres * depth / 8;
2859 external_xres = xres;
2860 external_xres_virtual = xres_virtual;
2861 external_yres = yres;
2862 external_depth = depth;
2863 external_pmode = planes;
2864 external_addr = addr;
2867 if (external_card_type == IS_MV300) {
2868 switch (external_depth) {
2870 MV300_reg = MV300_reg_1bit;
2873 MV300_reg = MV300_reg_4bit;
2876 MV300_reg = MV300_reg_8bit;
2881 #endif /* ATAFB_EXT */
2883 static void __init atafb_setup_int(char *spec)
2885 /* Format to config extended internal video hardware like OverScan:
2886 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2888 * <xres>: x-resolution
2889 * <yres>: y-resolution
2890 * The following are only needed if you have an overscan which
2891 * needs a black border:
2892 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2893 * <yres_max>: max. number of lines your OverScan hardware would allow
2894 * <offset>: Offset from physical beginning to visible beginning
2895 * of screen in bytes
2900 if (!(p = strsep(&spec, ";")) || !*p)
2902 xres = simple_strtoul(p, NULL, 10);
2903 if (!(p = strsep(&spec, ";")) || !*p)
2906 tt_yres = st_yres = simple_strtoul(p, NULL, 10);
2907 if ((p = strsep(&spec, ";")) && *p)
2908 sttt_xres_virtual = simple_strtoul(p, NULL, 10);
2909 if ((p = strsep(&spec, ";")) && *p)
2910 sttt_yres_virtual = simple_strtoul(p, NULL, 0);
2911 if ((p = strsep(&spec, ";")) && *p)
2912 ovsc_offset = simple_strtoul(p, NULL, 0);
2914 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2919 static void __init atafb_setup_mcap(char *spec)
2922 int vmin, vmax, hmin, hmax;
2924 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2925 * <V*> vertical freq. in Hz
2926 * <H*> horizontal freq. in kHz
2928 if (!(p = strsep(&spec, ";")) || !*p)
2930 vmin = simple_strtoul(p, NULL, 10);
2933 if (!(p = strsep(&spec, ";")) || !*p)
2935 vmax = simple_strtoul(p, NULL, 10);
2936 if (vmax <= 0 || vmax <= vmin)
2938 if (!(p = strsep(&spec, ";")) || !*p)
2940 hmin = 1000 * simple_strtoul(p, NULL, 10);
2943 if (!(p = strsep(&spec, "")) || !*p)
2945 hmax = 1000 * simple_strtoul(p, NULL, 10);
2946 if (hmax <= 0 || hmax <= hmin)
2949 fb_info.monspecs.vfmin = vmin;
2950 fb_info.monspecs.vfmax = vmax;
2951 fb_info.monspecs.hfmin = hmin;
2952 fb_info.monspecs.hfmax = hmax;
2954 #endif /* ATAFB_FALCON */
2956 static void __init atafb_setup_user(char *spec)
2958 /* Format of user defined video mode is: <xres>;<yres>;<depth>
2961 int xres, yres, depth, temp;
2963 p = strsep(&spec, ";");
2966 xres = simple_strtoul(p, NULL, 10);
2967 p = strsep(&spec, ";");
2970 yres = simple_strtoul(p, NULL, 10);
2971 p = strsep(&spec, "");
2974 depth = simple_strtoul(p, NULL, 10);
2975 temp = get_video_mode("user0");
2978 atafb_predefined[default_par - 1].xres = xres;
2979 atafb_predefined[default_par - 1].yres = yres;
2980 atafb_predefined[default_par - 1].bits_per_pixel = depth;
2984 int __init atafb_setup(char *options)
2989 if (!options || !*options)
2992 while ((this_opt = strsep(&options, ",")) != NULL) {
2995 if ((temp = get_video_mode(this_opt))) {
2997 mode_option = this_opt;
2998 } else if (!strcmp(this_opt, "inverse"))
3000 else if (!strncmp(this_opt, "hwscroll_", 9)) {
3001 hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
3008 else if (!strcmp(this_opt, "mv300")) {
3009 external_bitspercol = 8;
3010 external_card_type = IS_MV300;
3011 } else if (!strncmp(this_opt, "external:", 9))
3012 atafb_setup_ext(this_opt + 9);
3014 else if (!strncmp(this_opt, "internal:", 9))
3015 atafb_setup_int(this_opt + 9);
3017 else if (!strncmp(this_opt, "eclock:", 7)) {
3018 fext.f = simple_strtoul(this_opt + 7, NULL, 10);
3019 /* external pixelclock in kHz --> ps */
3020 fext.t = 1000000000 / fext.f;
3022 } else if (!strncmp(this_opt, "monitorcap:", 11))
3023 atafb_setup_mcap(this_opt + 11);
3025 else if (!strcmp(this_opt, "keep"))
3027 else if (!strncmp(this_opt, "R", 1))
3028 atafb_setup_user(this_opt + 1);
3033 static int __init atafb_probe(struct platform_device *pdev)
3035 int pad, detected_mode, error;
3036 unsigned int defmode = 0;
3037 unsigned long mem_req;
3038 char *option = NULL;
3040 if (fb_get_options("atafb", &option))
3042 atafb_setup(option);
3043 dev_dbg(&pdev->dev, "%s: start\n", __func__);
3047 if (external_addr) {
3048 dev_dbg(&pdev->dev, "initializing external hw\n");
3050 atafb_ops.fb_setcolreg = &ext_setcolreg;
3051 defmode = DEFMODE_EXT;
3056 if (ATARIHW_PRESENT(TT_SHIFTER)) {
3057 dev_dbg(&pdev->dev, "initializing TT hw\n");
3059 atafb_ops.fb_setcolreg = &tt_setcolreg;
3060 defmode = DEFMODE_TT;
3065 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
3066 dev_dbg(&pdev->dev, "initializing Falcon hw\n");
3067 fbhw = &falcon_switch;
3068 atafb_ops.fb_setcolreg = &falcon_setcolreg;
3069 error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 0,
3070 "framebuffer:modeswitch",
3071 falcon_vbl_switcher);
3074 defmode = DEFMODE_F30;
3079 if (ATARIHW_PRESENT(STND_SHIFTER) ||
3080 ATARIHW_PRESENT(EXTD_SHIFTER)) {
3081 dev_dbg(&pdev->dev, "initializing ST/E hw\n");
3083 atafb_ops.fb_setcolreg = &stste_setcolreg;
3084 defmode = DEFMODE_STE;
3088 atafb_ops.fb_setcolreg = &stste_setcolreg;
3089 dev_warn(&pdev->dev,
3090 "Cannot determine video hardware; defaulting to ST(e)\n");
3091 #else /* ATAFB_STE */
3092 /* no default driver included */
3093 /* Nobody will ever see this message :-) */
3094 panic("Cannot initialize video hardware");
3098 /* Multisync monitor capabilities */
3099 /* Atari-TOS defaults if no boot option present */
3100 if (fb_info.monspecs.hfmin == 0) {
3101 fb_info.monspecs.hfmin = 31000;
3102 fb_info.monspecs.hfmax = 32000;
3103 fb_info.monspecs.vfmin = 58;
3104 fb_info.monspecs.vfmax = 62;
3107 detected_mode = fbhw->detect();
3108 check_default_par(detected_mode);
3110 if (!external_addr) {
3111 #endif /* ATAFB_EXT */
3112 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
3113 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
3114 screen_base = atari_stram_alloc(mem_req, "atafb");
3116 panic("Cannot allocate screen memory");
3117 memset(screen_base, 0, mem_req);
3118 pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
3120 phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
3121 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
3123 if (CPU_IS_040_OR_060) {
3124 /* On a '040+, the cache mode of video RAM must be set to
3125 * write-through also for internal video hardware! */
3126 cache_push(atari_stram_to_phys(screen_base), screen_len);
3127 kernel_set_cachemode(screen_base, screen_len,
3128 IOMAP_WRITETHROUGH);
3130 dev_info(&pdev->dev, "phys_screen_base %lx screen_len %d\n",
3131 phys_screen_base, screen_len);
3134 /* Map the video memory (physical address given) to somewhere
3135 * in the kernel address space.
3137 external_screen_base = ioremap_wt(external_addr, external_len);
3138 if (external_vgaiobase)
3139 external_vgaiobase =
3140 (unsigned long)ioremap(external_vgaiobase, 0x10000);
3141 screen_base = external_screen_base;
3142 phys_screen_base = external_addr;
3143 screen_len = external_len & PAGE_MASK;
3144 memset (screen_base, 0, external_len);
3146 #endif /* ATAFB_EXT */
3148 // strcpy(fb_info.mode->name, "Atari Builtin ");
3149 fb_info.fbops = &atafb_ops;
3150 // try to set default (detected; requested) var
3151 do_fb_set_var(&atafb_predefined[default_par - 1], 1);
3152 // reads hw state into current par, which may not be sane yet
3153 ata_get_par(¤t_par);
3154 fb_info.par = ¤t_par;
3155 // tries to read from HW which may not be initialized yet
3156 // so set sane var first, then call atafb_set_par
3157 atafb_get_var(&fb_info.var, &fb_info);
3160 fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
3162 fb_info.flags = FBINFO_FLAG_DEFAULT;
3164 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
3165 NUM_TOTAL_MODES, &atafb_modedb[defmode],
3166 fb_info.var.bits_per_pixel)) {
3170 fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
3173 atafb_set_disp(&fb_info);
3175 fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
3178 dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
3179 fb_info.var.yres, fb_info.var.bits_per_pixel);
3180 if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
3181 (fb_info.var.yres != fb_info.var.yres_virtual))
3182 dev_info(&pdev->dev, " virtual %dx%d\n",
3183 fb_info.var.xres_virtual, fb_info.var.yres_virtual);
3185 if (register_framebuffer(&fb_info) < 0) {
3187 if (external_addr) {
3188 iounmap(external_screen_base);
3191 if (external_vgaiobase) {
3192 iounmap((void*)external_vgaiobase);
3193 external_vgaiobase = 0;
3199 fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
3202 /* TODO: This driver cannot be unloaded yet */
3206 static void atafb_shutdown(struct platform_device *pdev)
3208 /* Unblank before kexec */
3213 static struct platform_driver atafb_driver = {
3214 .shutdown = atafb_shutdown,
3220 static int __init atafb_init(void)
3222 struct platform_device *pdev;
3227 pdev = platform_device_register_simple("atafb", -1, NULL, 0);
3229 return PTR_ERR(pdev);
3231 return platform_driver_probe(&atafb_driver, atafb_probe);
3234 device_initcall(atafb_init);