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
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
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
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
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
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
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
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
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
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 if (!fbhw->pan_display)
2413 return fbhw->pan_display(var, info);
2417 * generic drawing routines; imageblit needs updating for image depth > 1
2420 #if BITS_PER_LONG == 32
2421 #define BYTES_PER_LONG 4
2422 #define SHIFT_PER_LONG 5
2423 #elif BITS_PER_LONG == 64
2424 #define BYTES_PER_LONG 8
2425 #define SHIFT_PER_LONG 6
2427 #define Please update me
2431 static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
2433 struct atafb_par *par = (struct atafb_par *)info->par;
2437 if (!rect->width || !rect->height)
2441 if (info->var.bits_per_pixel == 16) {
2442 cfb_fillrect(info, rect);
2448 * We could use hardware clipping but on many cards you get around
2449 * hardware clipping by writing to framebuffer directly.
2451 x2 = rect->dx + rect->width;
2452 y2 = rect->dy + rect->height;
2453 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2454 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2455 width = x2 - rect->dx;
2456 height = y2 - rect->dy;
2458 if (info->var.bits_per_pixel == 1)
2459 atafb_mfb_fillrect(info, par->next_line, rect->color,
2460 rect->dy, rect->dx, height, width);
2461 else if (info->var.bits_per_pixel == 2)
2462 atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
2463 rect->dy, rect->dx, height, width);
2464 else if (info->var.bits_per_pixel == 4)
2465 atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
2466 rect->dy, rect->dx, height, width);
2468 atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
2469 rect->dy, rect->dx, height, width);
2474 static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2476 struct atafb_par *par = (struct atafb_par *)info->par;
2478 u32 dx, dy, sx, sy, width, height;
2482 if (info->var.bits_per_pixel == 16) {
2483 cfb_copyarea(info, area);
2488 /* clip the destination */
2489 x2 = area->dx + area->width;
2490 y2 = area->dy + area->height;
2491 dx = area->dx > 0 ? area->dx : 0;
2492 dy = area->dy > 0 ? area->dy : 0;
2493 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2494 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2498 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2502 sx = area->sx + (dx - area->dx);
2503 sy = area->sy + (dy - area->dy);
2505 /* the source must be completely inside the virtual screen */
2506 if (sx + width > info->var.xres_virtual ||
2507 sy + height > info->var.yres_virtual)
2510 if (dy > sy || (dy == sy && dx > sx)) {
2516 if (info->var.bits_per_pixel == 1)
2517 atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2518 else if (info->var.bits_per_pixel == 2)
2519 atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2520 else if (info->var.bits_per_pixel == 4)
2521 atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2523 atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2528 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2530 struct atafb_par *par = (struct atafb_par *)info->par;
2535 u32 dx, dy, width, height, pitch;
2538 if (info->var.bits_per_pixel == 16) {
2539 cfb_imageblit(info, image);
2545 * We could use hardware clipping but on many cards you get around
2546 * hardware clipping by writing to framebuffer directly like we are
2549 x2 = image->dx + image->width;
2550 y2 = image->dy + image->height;
2553 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2554 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2558 if (image->depth == 1) {
2559 // used for font data
2560 dst = (unsigned long *)
2561 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2562 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2563 dst_idx += dy * par->next_line * 8 + dx;
2565 pitch = (image->width + 7) / 8;
2568 if (info->var.bits_per_pixel == 1)
2569 atafb_mfb_linefill(info, par->next_line,
2571 image->bg_color, image->fg_color);
2572 else if (info->var.bits_per_pixel == 2)
2573 atafb_iplan2p2_linefill(info, par->next_line,
2575 image->bg_color, image->fg_color);
2576 else if (info->var.bits_per_pixel == 4)
2577 atafb_iplan2p4_linefill(info, par->next_line,
2579 image->bg_color, image->fg_color);
2581 atafb_iplan2p8_linefill(info, par->next_line,
2583 image->bg_color, image->fg_color);
2588 c2p_iplan2(info->screen_base, image->data, dx, dy, width,
2589 height, par->next_line, image->width,
2590 info->var.bits_per_pixel);
2595 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2598 #ifdef FBCMD_GET_CURRENTPAR
2599 case FBCMD_GET_CURRENTPAR:
2600 if (copy_to_user((void *)arg, (void *)¤t_par,
2601 sizeof(struct atafb_par)))
2605 #ifdef FBCMD_SET_CURRENTPAR
2606 case FBCMD_SET_CURRENTPAR:
2607 if (copy_from_user((void *)¤t_par, (void *)arg,
2608 sizeof(struct atafb_par)))
2610 ata_set_par(¤t_par);
2617 /* (un)blank/poweroff
2624 static int atafb_blank(int blank, struct fb_info *info)
2626 unsigned short black[16];
2627 struct fb_cmap cmap;
2628 if (fbhw->blank && !fbhw->blank(blank))
2631 memset(black, 0, 16 * sizeof(unsigned short));
2638 fb_set_cmap(&cmap, info);
2642 do_install_cmap(info);
2648 * New fbcon interface ...
2651 /* check var by decoding var into hw par, rounding if necessary,
2652 * then encoding hw par back into new, validated var */
2653 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2656 struct atafb_par par;
2658 /* Validate wanted screen parameters */
2659 // if ((err = ata_decode_var(var, &par)))
2660 err = fbhw->decode_var(var, &par);
2664 /* Encode (possibly rounded) screen parameters */
2665 fbhw->encode_var(var, &par);
2669 /* actually set hw par by decoding var, then setting hardware from
2670 * hw par just decoded */
2671 static int atafb_set_par(struct fb_info *info)
2673 struct atafb_par *par = (struct atafb_par *)info->par;
2675 /* Decode wanted screen parameters */
2676 fbhw->decode_var(&info->var, par);
2677 mutex_lock(&info->mm_lock);
2678 fbhw->encode_fix(&info->fix, par);
2679 mutex_unlock(&info->mm_lock);
2681 /* Set new videomode */
2688 static struct fb_ops atafb_ops = {
2689 .owner = THIS_MODULE,
2690 .fb_check_var = atafb_check_var,
2691 .fb_set_par = atafb_set_par,
2692 .fb_blank = atafb_blank,
2693 .fb_pan_display = atafb_pan_display,
2694 .fb_fillrect = atafb_fillrect,
2695 .fb_copyarea = atafb_copyarea,
2696 .fb_imageblit = atafb_imageblit,
2697 .fb_ioctl = atafb_ioctl,
2700 static void check_default_par(int detected_mode)
2702 char default_name[10];
2704 struct fb_var_screeninfo var;
2705 unsigned long min_mem;
2707 /* First try the user supplied mode */
2709 var = atafb_predefined[default_par - 1];
2710 var.activate = FB_ACTIVATE_TEST;
2711 if (do_fb_set_var(&var, 1))
2712 default_par = 0; /* failed */
2714 /* Next is the autodetected one */
2716 var = atafb_predefined[detected_mode - 1]; /* autodetect */
2717 var.activate = FB_ACTIVATE_TEST;
2718 if (!do_fb_set_var(&var, 1))
2719 default_par = detected_mode;
2721 /* If that also failed, try some default modes... */
2723 /* try default1, default2... */
2724 for (i = 1; i < 10; i++) {
2725 sprintf(default_name,"default%d", i);
2726 default_par = get_video_mode(default_name);
2728 panic("can't set default video mode");
2729 var = atafb_predefined[default_par - 1];
2730 var.activate = FB_ACTIVATE_TEST;
2731 if (!do_fb_set_var(&var,1))
2735 min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
2736 if (default_mem_req < min_mem)
2737 default_mem_req = min_mem;
2741 static void __init atafb_setup_ext(char *spec)
2743 int xres, xres_virtual, yres, depth, planes;
2744 unsigned long addr, len;
2747 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2749 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2750 * [;<xres-virtual>]]]]]
2753 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2755 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2757 p = strsep(&spec, ";");
2760 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2764 p = strsep(&spec, ";");
2767 yres = simple_strtoul(p, NULL, 10);
2771 p = strsep(&spec, ";");
2774 depth = simple_strtoul(p, NULL, 10);
2775 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2776 depth != 16 && depth != 24)
2779 p = strsep(&spec, ";");
2783 planes = FB_TYPE_INTERLEAVED_PLANES;
2785 planes = FB_TYPE_PACKED_PIXELS;
2787 planes = FB_TYPE_PLANES;
2789 planes = -1; /* true color */
2793 p = strsep(&spec, ";");
2796 addr = simple_strtoul(p, NULL, 0);
2798 p = strsep(&spec, ";");
2800 len = xres * yres * depth / 8;
2802 len = simple_strtoul(p, NULL, 0);
2804 p = strsep(&spec, ";");
2806 external_vgaiobase = simple_strtoul(p, NULL, 0);
2808 p = strsep(&spec, ";");
2810 external_bitspercol = simple_strtoul(p, NULL, 0);
2811 if (external_bitspercol > 8)
2812 external_bitspercol = 8;
2813 else if (external_bitspercol < 1)
2814 external_bitspercol = 1;
2817 p = strsep(&spec, ";");
2819 if (!strcmp(p, "vga"))
2820 external_card_type = IS_VGA;
2821 if (!strcmp(p, "mv300"))
2822 external_card_type = IS_MV300;
2825 p = strsep(&spec, ";");
2827 xres_virtual = simple_strtoul(p, NULL, 10);
2828 if (xres_virtual < xres)
2829 xres_virtual = xres;
2830 if (xres_virtual * yres * depth / 8 > len)
2831 len = xres_virtual * yres * depth / 8;
2834 external_xres = xres;
2835 external_xres_virtual = xres_virtual;
2836 external_yres = yres;
2837 external_depth = depth;
2838 external_pmode = planes;
2839 external_addr = addr;
2842 if (external_card_type == IS_MV300) {
2843 switch (external_depth) {
2845 MV300_reg = MV300_reg_1bit;
2848 MV300_reg = MV300_reg_4bit;
2851 MV300_reg = MV300_reg_8bit;
2856 #endif /* ATAFB_EXT */
2858 static void __init atafb_setup_int(char *spec)
2860 /* Format to config extended internal video hardware like OverScan:
2861 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2863 * <xres>: x-resolution
2864 * <yres>: y-resolution
2865 * The following are only needed if you have an overscan which
2866 * needs a black border:
2867 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2868 * <yres_max>: max. number of lines your OverScan hardware would allow
2869 * <offset>: Offset from physical beginning to visible beginning
2870 * of screen in bytes
2875 if (!(p = strsep(&spec, ";")) || !*p)
2877 xres = simple_strtoul(p, NULL, 10);
2878 if (!(p = strsep(&spec, ";")) || !*p)
2881 tt_yres = st_yres = simple_strtoul(p, NULL, 10);
2882 if ((p = strsep(&spec, ";")) && *p)
2883 sttt_xres_virtual = simple_strtoul(p, NULL, 10);
2884 if ((p = strsep(&spec, ";")) && *p)
2885 sttt_yres_virtual = simple_strtoul(p, NULL, 0);
2886 if ((p = strsep(&spec, ";")) && *p)
2887 ovsc_offset = simple_strtoul(p, NULL, 0);
2889 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2894 static void __init atafb_setup_mcap(char *spec)
2897 int vmin, vmax, hmin, hmax;
2899 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2900 * <V*> vertical freq. in Hz
2901 * <H*> horizontal freq. in kHz
2903 if (!(p = strsep(&spec, ";")) || !*p)
2905 vmin = simple_strtoul(p, NULL, 10);
2908 if (!(p = strsep(&spec, ";")) || !*p)
2910 vmax = simple_strtoul(p, NULL, 10);
2911 if (vmax <= 0 || vmax <= vmin)
2913 if (!(p = strsep(&spec, ";")) || !*p)
2915 hmin = 1000 * simple_strtoul(p, NULL, 10);
2918 if (!(p = strsep(&spec, "")) || !*p)
2920 hmax = 1000 * simple_strtoul(p, NULL, 10);
2921 if (hmax <= 0 || hmax <= hmin)
2924 fb_info.monspecs.vfmin = vmin;
2925 fb_info.monspecs.vfmax = vmax;
2926 fb_info.monspecs.hfmin = hmin;
2927 fb_info.monspecs.hfmax = hmax;
2929 #endif /* ATAFB_FALCON */
2931 static void __init atafb_setup_user(char *spec)
2933 /* Format of user defined video mode is: <xres>;<yres>;<depth>
2936 int xres, yres, depth, temp;
2938 p = strsep(&spec, ";");
2941 xres = simple_strtoul(p, NULL, 10);
2942 p = strsep(&spec, ";");
2945 yres = simple_strtoul(p, NULL, 10);
2946 p = strsep(&spec, "");
2949 depth = simple_strtoul(p, NULL, 10);
2950 temp = get_video_mode("user0");
2953 atafb_predefined[default_par - 1].xres = xres;
2954 atafb_predefined[default_par - 1].yres = yres;
2955 atafb_predefined[default_par - 1].bits_per_pixel = depth;
2959 static int __init atafb_setup(char *options)
2964 if (!options || !*options)
2967 while ((this_opt = strsep(&options, ",")) != NULL) {
2970 if ((temp = get_video_mode(this_opt))) {
2972 mode_option = this_opt;
2973 } else if (!strcmp(this_opt, "inverse"))
2975 else if (!strncmp(this_opt, "hwscroll_", 9)) {
2976 hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
2983 else if (!strcmp(this_opt, "mv300")) {
2984 external_bitspercol = 8;
2985 external_card_type = IS_MV300;
2986 } else if (!strncmp(this_opt, "external:", 9))
2987 atafb_setup_ext(this_opt + 9);
2989 else if (!strncmp(this_opt, "internal:", 9))
2990 atafb_setup_int(this_opt + 9);
2992 else if (!strncmp(this_opt, "eclock:", 7)) {
2993 fext.f = simple_strtoul(this_opt + 7, NULL, 10);
2994 /* external pixelclock in kHz --> ps */
2995 fext.t = 1000000000 / fext.f;
2997 } else if (!strncmp(this_opt, "monitorcap:", 11))
2998 atafb_setup_mcap(this_opt + 11);
3000 else if (!strcmp(this_opt, "keep"))
3002 else if (!strncmp(this_opt, "R", 1))
3003 atafb_setup_user(this_opt + 1);
3008 static int __init atafb_probe(struct platform_device *pdev)
3010 int pad, detected_mode, error;
3011 unsigned int defmode = 0;
3012 unsigned long mem_req;
3013 char *option = NULL;
3015 if (fb_get_options("atafb", &option))
3017 atafb_setup(option);
3018 dev_dbg(&pdev->dev, "%s: start\n", __func__);
3022 if (external_addr) {
3023 dev_dbg(&pdev->dev, "initializing external hw\n");
3025 atafb_ops.fb_setcolreg = &ext_setcolreg;
3026 defmode = DEFMODE_EXT;
3031 if (ATARIHW_PRESENT(TT_SHIFTER)) {
3032 dev_dbg(&pdev->dev, "initializing TT hw\n");
3034 atafb_ops.fb_setcolreg = &tt_setcolreg;
3035 defmode = DEFMODE_TT;
3040 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
3041 dev_dbg(&pdev->dev, "initializing Falcon hw\n");
3042 fbhw = &falcon_switch;
3043 atafb_ops.fb_setcolreg = &falcon_setcolreg;
3044 error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 0,
3045 "framebuffer:modeswitch",
3046 falcon_vbl_switcher);
3049 defmode = DEFMODE_F30;
3054 if (ATARIHW_PRESENT(STND_SHIFTER) ||
3055 ATARIHW_PRESENT(EXTD_SHIFTER)) {
3056 dev_dbg(&pdev->dev, "initializing ST/E hw\n");
3058 atafb_ops.fb_setcolreg = &stste_setcolreg;
3059 defmode = DEFMODE_STE;
3063 atafb_ops.fb_setcolreg = &stste_setcolreg;
3064 dev_warn(&pdev->dev,
3065 "Cannot determine video hardware; defaulting to ST(e)\n");
3066 #else /* ATAFB_STE */
3067 /* no default driver included */
3068 /* Nobody will ever see this message :-) */
3069 panic("Cannot initialize video hardware");
3073 /* Multisync monitor capabilities */
3074 /* Atari-TOS defaults if no boot option present */
3075 if (fb_info.monspecs.hfmin == 0) {
3076 fb_info.monspecs.hfmin = 31000;
3077 fb_info.monspecs.hfmax = 32000;
3078 fb_info.monspecs.vfmin = 58;
3079 fb_info.monspecs.vfmax = 62;
3082 detected_mode = fbhw->detect();
3083 check_default_par(detected_mode);
3085 if (!external_addr) {
3086 #endif /* ATAFB_EXT */
3087 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
3088 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
3089 screen_base = atari_stram_alloc(mem_req, "atafb");
3091 panic("Cannot allocate screen memory");
3092 memset(screen_base, 0, mem_req);
3093 pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
3095 phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
3096 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
3098 if (CPU_IS_040_OR_060) {
3099 /* On a '040+, the cache mode of video RAM must be set to
3100 * write-through also for internal video hardware! */
3101 cache_push(atari_stram_to_phys(screen_base), screen_len);
3102 kernel_set_cachemode(screen_base, screen_len,
3103 IOMAP_WRITETHROUGH);
3105 dev_info(&pdev->dev, "phys_screen_base %lx screen_len %d\n",
3106 phys_screen_base, screen_len);
3109 /* Map the video memory (physical address given) to somewhere
3110 * in the kernel address space.
3112 external_screen_base = ioremap_wt(external_addr, external_len);
3113 if (external_vgaiobase)
3114 external_vgaiobase =
3115 (unsigned long)ioremap(external_vgaiobase, 0x10000);
3116 screen_base = external_screen_base;
3117 phys_screen_base = external_addr;
3118 screen_len = external_len & PAGE_MASK;
3119 memset (screen_base, 0, external_len);
3121 #endif /* ATAFB_EXT */
3123 // strcpy(fb_info.mode->name, "Atari Builtin ");
3124 fb_info.fbops = &atafb_ops;
3125 // try to set default (detected; requested) var
3126 do_fb_set_var(&atafb_predefined[default_par - 1], 1);
3127 // reads hw state into current par, which may not be sane yet
3128 ata_get_par(¤t_par);
3129 fb_info.par = ¤t_par;
3130 // tries to read from HW which may not be initialized yet
3131 // so set sane var first, then call atafb_set_par
3132 atafb_get_var(&fb_info.var, &fb_info);
3135 fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
3137 fb_info.flags = FBINFO_FLAG_DEFAULT;
3139 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
3140 NUM_TOTAL_MODES, &atafb_modedb[defmode],
3141 fb_info.var.bits_per_pixel)) {
3145 fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
3148 atafb_set_disp(&fb_info);
3150 fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
3153 dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
3154 fb_info.var.yres, fb_info.var.bits_per_pixel);
3155 if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
3156 (fb_info.var.yres != fb_info.var.yres_virtual))
3157 dev_info(&pdev->dev, " virtual %dx%d\n",
3158 fb_info.var.xres_virtual, fb_info.var.yres_virtual);
3160 if (register_framebuffer(&fb_info) < 0) {
3162 if (external_addr) {
3163 iounmap(external_screen_base);
3166 if (external_vgaiobase) {
3167 iounmap((void*)external_vgaiobase);
3168 external_vgaiobase = 0;
3174 fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
3177 /* TODO: This driver cannot be unloaded yet */
3181 static void atafb_shutdown(struct platform_device *pdev)
3183 /* Unblank before kexec */
3188 static struct platform_driver atafb_driver = {
3189 .shutdown = atafb_shutdown,
3195 static int __init atafb_init(void)
3197 struct platform_device *pdev;
3202 pdev = platform_device_register_simple("atafb", -1, NULL, 0);
3204 return PTR_ERR(pdev);
3206 return platform_driver_probe(&atafb_driver, atafb_probe);
3209 device_initcall(atafb_init);