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 */
241 * * open/release and usage marking
242 * struct module *owner;
243 * int (*fb_open)(struct fb_info *info, int user);
244 * int (*fb_release)(struct fb_info *info, int user);
246 * * For framebuffers with strange non linear layouts or that do not
247 * * work with normal memory mapped access
248 * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
249 * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
251 * * checks var and eventually tweaks it to something supported,
252 * * DOES NOT MODIFY PAR *
253 * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
255 * * set the video mode according to info->var *
256 * int (*fb_set_par)(struct fb_info *info);
258 * * set color register *
259 * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
260 * unsigned int blue, unsigned int transp, struct fb_info *info);
262 * * set color registers in batch *
263 * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
266 * int (*fb_blank)(int blank, struct fb_info *info);
269 * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
271 * *** The meat of the drawing engine ***
272 * * Draws a rectangle *
273 * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
274 * * Copy data from area to another *
275 * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
276 * * Draws a image to the display *
277 * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
280 * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
282 * * wait for blit idle, optional *
283 * int (*fb_sync)(struct fb_info *info);
285 * * perform fb specific ioctl (optional) *
286 * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
287 * unsigned long arg);
289 * * Handle 32bit compat ioctl (optional) *
290 * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
291 * unsigned long arg);
293 * * perform fb specific mmap *
294 * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
299 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
302 * int (*detect)(void)
303 * This function should detect the current video mode settings and
304 * store them in atafb_predefined[0] for later reference by the
305 * user. Return the index+1 of an equivalent predefined mode or 0
306 * if there is no such.
308 * int (*encode_fix)(struct fb_fix_screeninfo *fix,
309 * struct atafb_par *par)
310 * This function should fill in the 'fix' structure based on the
311 * values in the 'par' structure.
312 * !!! Obsolete, perhaps !!!
314 * int (*decode_var)(struct fb_var_screeninfo *var,
315 * struct atafb_par *par)
316 * Get the video params out of 'var'. If a value doesn't fit, round
317 * it up, if it's too big, return EINVAL.
318 * Round up in the following order: bits_per_pixel, xres, yres,
319 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
320 * horizontal timing, vertical timing.
322 * int (*encode_var)(struct fb_var_screeninfo *var,
323 * struct atafb_par *par);
324 * Fill the 'var' structure based on the values in 'par' and maybe
325 * other values read out of the hardware.
327 * void (*get_par)(struct atafb_par *par)
328 * Fill the hardware's 'par' structure.
329 * !!! Used only by detect() !!!
331 * void (*set_par)(struct atafb_par *par)
332 * Set the hardware according to 'par'.
334 * void (*set_screen_base)(void *s_base)
335 * Set the base address of the displayed frame buffer. Only called
336 * if yres_virtual > yres or xres_virtual > xres.
338 * int (*blank)(int blank_mode)
339 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
340 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
341 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
342 * doesn't support it. Implements VESA suspend and powerdown modes on
343 * hardware that supports disabling hsync/vsync:
344 * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
347 static struct fb_hwswitch {
349 int (*encode_fix)(struct fb_fix_screeninfo *fix,
350 struct atafb_par *par);
351 int (*decode_var)(struct fb_var_screeninfo *var,
352 struct atafb_par *par);
353 int (*encode_var)(struct fb_var_screeninfo *var,
354 struct atafb_par *par);
355 void (*get_par)(struct atafb_par *par);
356 void (*set_par)(struct atafb_par *par);
357 void (*set_screen_base)(void *s_base);
358 int (*blank)(int blank_mode);
359 int (*pan_display)(struct fb_var_screeninfo *var,
360 struct fb_info *info);
363 static char *autodetect_names[] = { "autodetect", NULL };
364 static char *stlow_names[] = { "stlow", NULL };
365 static char *stmid_names[] = { "stmid", "default5", NULL };
366 static char *sthigh_names[] = { "sthigh", "default4", NULL };
367 static char *ttlow_names[] = { "ttlow", NULL };
368 static char *ttmid_names[] = { "ttmid", "default1", NULL };
369 static char *tthigh_names[] = { "tthigh", "default2", NULL };
370 static char *vga2_names[] = { "vga2", NULL };
371 static char *vga4_names[] = { "vga4", NULL };
372 static char *vga16_names[] = { "vga16", "default3", NULL };
373 static char *vga256_names[] = { "vga256", NULL };
374 static char *falh2_names[] = { "falh2", NULL };
375 static char *falh16_names[] = { "falh16", NULL };
377 static char **fb_var_names[] = {
394 static struct fb_var_screeninfo atafb_predefined[] = {
396 * yres_virtual == 0 means use hw-scrolling if possible, else yres
399 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
400 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
401 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
403 320, 200, 320, 0, 0, 0, 4, 0,
404 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
405 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
407 640, 200, 640, 0, 0, 0, 2, 0,
408 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
409 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
411 640, 400, 640, 0, 0, 0, 1, 0,
412 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
413 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
415 320, 480, 320, 0, 0, 0, 8, 0,
416 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
417 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
419 640, 480, 640, 0, 0, 0, 4, 0,
420 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
421 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
423 1280, 960, 1280, 0, 0, 0, 1, 0,
424 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
425 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
427 640, 480, 640, 0, 0, 0, 1, 0,
428 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
429 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
431 640, 480, 640, 0, 0, 0, 2, 0,
432 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
433 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
435 640, 480, 640, 0, 0, 0, 4, 0,
436 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
437 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
439 640, 480, 640, 0, 0, 0, 8, 0,
440 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
441 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
443 896, 608, 896, 0, 0, 0, 1, 0,
444 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
445 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
447 896, 608, 896, 0, 0, 0, 4, 0,
448 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
449 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
452 static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
454 static struct fb_videomode atafb_modedb[] __initdata = {
458 * If you change these, make sure to update DEFMODE_* as well!
466 /* 320x200, 15 kHz, 60 Hz (ST low) */
467 "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
468 0, FB_VMODE_NONINTERLACED
470 /* 640x200, 15 kHz, 60 Hz (ST medium) */
471 "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
472 0, FB_VMODE_NONINTERLACED
474 /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
475 "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
476 0, FB_VMODE_NONINTERLACED
478 /* 320x480, 15 kHz, 60 Hz (TT low) */
479 "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
480 0, FB_VMODE_NONINTERLACED
482 /* 640x480, 29 kHz, 57 Hz (TT medium) */
483 "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
484 0, FB_VMODE_NONINTERLACED
486 /* 1280x960, 72 kHz, 72 Hz (TT high) */
487 "tt-high", 57, 1280, 960, 7760, 260, 60, 36, 4, 192, 4,
488 0, FB_VMODE_NONINTERLACED
496 /* 640x480, 31 kHz, 60 Hz (VGA) */
497 "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
498 0, FB_VMODE_NONINTERLACED
500 /* 640x400, 31 kHz, 70 Hz (VGA) */
501 "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
502 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED
506 * Falcon HiRes Video Modes
510 /* 896x608, 31 kHz, 60 Hz (Falcon High) */
511 "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
512 0, FB_VMODE_NONINTERLACED
516 #define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb)
518 static char *mode_option __initdata = NULL;
522 #define DEFMODE_TT 5 /* "tt-high" for TT */
523 #define DEFMODE_F30 7 /* "vga70" for Falcon */
524 #define DEFMODE_STE 2 /* "st-high" for ST/E */
525 #define DEFMODE_EXT 6 /* "vga" for external */
528 static int get_video_mode(char *vname)
534 name_list = fb_var_names;
535 for (i = 0; i < num_atafb_predefined; i++) {
540 if (!strcmp(vname, *name))
550 /* ------------------- TT specific functions ---------------------- */
554 static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
558 strcpy(fix->id, "Atari Builtin");
559 fix->smem_start = phys_screen_base;
560 fix->smem_len = screen_len;
561 fix->type = FB_TYPE_INTERLEAVED_PLANES;
563 fix->visual = FB_VISUAL_PSEUDOCOLOR;
564 mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
565 if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
566 fix->type = FB_TYPE_PACKED_PIXELS;
568 if (mode == TT_SHIFTER_TTHIGH)
569 fix->visual = FB_VISUAL_MONO01;
574 fix->line_length = par->next_line;
575 fix->accel = FB_ACCEL_ATARIBLITT;
579 static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
581 int xres = var->xres;
582 int yres = var->yres;
583 int bpp = var->bits_per_pixel;
585 int yres_virtual = var->yres_virtual;
588 if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
590 par->hw.tt.mode = TT_SHIFTER_TTHIGH;
591 xres = sttt_xres * 2;
595 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
598 if (xres > sttt_xres / 2 || yres > tt_yres)
600 par->hw.tt.mode = TT_SHIFTER_TTLOW;
601 xres = sttt_xres / 2;
604 } else if (bpp > 2) {
605 if (xres > sttt_xres || yres > tt_yres)
607 if (xres > sttt_xres / 2 || yres > st_yres / 2) {
608 par->hw.tt.mode = TT_SHIFTER_TTMID;
613 par->hw.tt.mode = TT_SHIFTER_STLOW;
614 xres = sttt_xres / 2;
618 } else if (bpp > 1) {
619 if (xres > sttt_xres || yres > st_yres / 2)
621 par->hw.tt.mode = TT_SHIFTER_STMID;
625 } else if (var->xres > sttt_xres || var->yres > st_yres) {
628 par->hw.tt.mode = TT_SHIFTER_STHIGH;
634 if (yres_virtual <= 0)
636 else if (yres_virtual < yres)
638 if (var->sync & FB_SYNC_EXT)
642 linelen = xres * bpp / 8;
643 if (yres_virtual * linelen > screen_len && screen_len)
645 if (yres * linelen > screen_len && screen_len)
647 if (var->yoffset + yres > yres_virtual && yres_virtual)
649 par->yres_virtual = yres_virtual;
650 par->screen_base = screen_base + var->yoffset * linelen;
651 par->next_line = linelen;
655 static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
658 memset(var, 0, sizeof(struct fb_var_screeninfo));
661 var->red.msb_right = 0;
664 var->pixclock = 31041;
665 var->left_margin = 120; /* these may be incorrect */
666 var->right_margin = 100;
667 var->upper_margin = 8;
668 var->lower_margin = 16;
669 var->hsync_len = 140;
675 if (par->hw.tt.sync & 1)
678 var->sync = FB_SYNC_EXT;
680 switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
681 case TT_SHIFTER_STLOW:
682 var->xres = sttt_xres / 2;
683 var->xres_virtual = sttt_xres_virtual / 2;
684 var->yres = st_yres / 2;
685 var->bits_per_pixel = 4;
687 case TT_SHIFTER_STMID:
688 var->xres = sttt_xres;
689 var->xres_virtual = sttt_xres_virtual;
690 var->yres = st_yres / 2;
691 var->bits_per_pixel = 2;
693 case TT_SHIFTER_STHIGH:
694 var->xres = sttt_xres;
695 var->xres_virtual = sttt_xres_virtual;
697 var->bits_per_pixel = 1;
699 case TT_SHIFTER_TTLOW:
700 var->xres = sttt_xres / 2;
701 var->xres_virtual = sttt_xres_virtual / 2;
703 var->bits_per_pixel = 8;
705 case TT_SHIFTER_TTMID:
706 var->xres = sttt_xres;
707 var->xres_virtual = sttt_xres_virtual;
709 var->bits_per_pixel = 4;
711 case TT_SHIFTER_TTHIGH:
713 var->xres = sttt_xres * 2;
714 var->xres_virtual = sttt_xres_virtual * 2;
715 var->yres = tt_yres * 2;
716 var->bits_per_pixel = 1;
719 var->blue = var->green = var->red;
720 var->transp.offset = 0;
721 var->transp.length = 0;
722 var->transp.msb_right = 0;
723 linelen = var->xres_virtual * var->bits_per_pixel / 8;
725 var->yres_virtual = var->yres;
726 else if (screen_len) {
727 if (par->yres_virtual)
728 var->yres_virtual = par->yres_virtual;
730 /* yres_virtual == 0 means use maximum */
731 var->yres_virtual = screen_len / linelen;
734 var->yres_virtual = 2 * var->yres;
736 var->yres_virtual = var->yres + hwscroll * 16;
740 var->yoffset = (par->screen_base - screen_base) / linelen;
745 var->vmode = FB_VMODE_NONINTERLACED;
749 static void tt_get_par(struct atafb_par *par)
752 par->hw.tt.mode = shifter_tt.tt_shiftmode;
753 par->hw.tt.sync = shifter_st.syncmode;
754 addr = ((shifter_st.bas_hi & 0xff) << 16) |
755 ((shifter_st.bas_md & 0xff) << 8) |
756 ((shifter_st.bas_lo & 0xff));
757 par->screen_base = atari_stram_to_virt(addr);
760 static void tt_set_par(struct atafb_par *par)
762 shifter_tt.tt_shiftmode = par->hw.tt.mode;
763 shifter_st.syncmode = par->hw.tt.sync;
764 /* only set screen_base if really necessary */
765 if (current_par.screen_base != par->screen_base)
766 fbhw->set_screen_base(par->screen_base);
769 static int tt_setcolreg(unsigned int regno, unsigned int red,
770 unsigned int green, unsigned int blue,
771 unsigned int transp, struct fb_info *info)
773 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
777 tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
779 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
780 TT_SHIFTER_STHIGH && regno == 254)
785 static int tt_detect(void)
787 struct atafb_par par;
789 /* Determine the connected monitor: The DMA sound must be
790 * disabled before reading the MFP GPIP, because the Sound
791 * Done Signal and the Monochrome Detect are XORed together!
793 * Even on a TT, we should look if there is a DMA sound. It was
794 * announced that the Eagle is TT compatible, but only the PCM is
797 if (ATARIHW_PRESENT(PCM_8BIT)) {
798 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
799 udelay(20); /* wait a while for things to settle down */
801 mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
804 tt_encode_var(&atafb_predefined[0], &par);
809 #endif /* ATAFB_TT */
811 /* ------------------- Falcon specific functions ---------------------- */
815 static int mon_type; /* Falcon connected monitor */
816 static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
822 static struct pixel_clock {
823 unsigned long f; /* f/[Hz] */
824 unsigned long t; /* t/[ps] (=1/f) */
825 int right, hsync, left; /* standard timing in clock cycles, not pixel */
826 /* hsync initialized in falcon_detect() */
827 int sync_mask; /* or-mask for hw.falcon.sync to set this clock */
828 int control_mask; /* ditto, for hw.falcon.vid_control */
830 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
832 32000000, 31250, 18, 0, 42, 0x0, 0
834 0, 0, 18, 0, 42, 0x1, 0
837 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
838 static int vdl_prescale[4][3] = {
839 { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
842 /* Default hsync timing [mon_type] in picoseconds */
843 static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
845 static inline int hxx_prescale(struct falcon_hw *hw)
847 return hw->ste_mode ? 16
848 : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
851 static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
852 struct atafb_par *par)
854 strcpy(fix->id, "Atari Builtin");
855 fix->smem_start = phys_screen_base;
856 fix->smem_len = screen_len;
857 fix->type = FB_TYPE_INTERLEAVED_PLANES;
859 fix->visual = FB_VISUAL_PSEUDOCOLOR;
863 if (par->hw.falcon.mono) {
864 fix->type = FB_TYPE_PACKED_PIXELS;
866 /* no smooth scrolling with longword aligned video mem */
868 } else if (par->hw.falcon.f_shift & 0x100) {
869 fix->type = FB_TYPE_PACKED_PIXELS;
871 /* Is this ok or should it be DIRECTCOLOR? */
872 fix->visual = FB_VISUAL_TRUECOLOR;
875 fix->line_length = par->next_line;
876 fix->accel = FB_ACCEL_ATARIBLITT;
880 static int falcon_decode_var(struct fb_var_screeninfo *var,
881 struct atafb_par *par)
883 int bpp = var->bits_per_pixel;
884 int xres = var->xres;
885 int yres = var->yres;
886 int xres_virtual = var->xres_virtual;
887 int yres_virtual = var->yres_virtual;
888 int left_margin, right_margin, hsync_len;
889 int upper_margin, lower_margin, vsync_len;
891 int interlace = 0, doubleline = 0;
892 struct pixel_clock *pclock;
893 int plen; /* width of pixel in clock cycles */
898 int hdb_off, hde_off, base_off;
899 int gstart, gend1, gend2, align;
902 Get the video params out of 'var'. If a value doesn't fit, round
903 it up, if it's too big, return EINVAL.
904 Round up in the following order: bits_per_pixel, xres, yres,
905 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
906 horizontal timing, vertical timing.
908 There is a maximum of screen resolution determined by pixelclock
909 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
910 In interlace mode this is " * " *vfmin <= pixelclock.
911 Additional constraints: hfreq.
912 Frequency range for multisync monitors is given via command line.
913 For TV and SM124 both frequencies are fixed.
915 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
916 Y % 16 == 0 to fit 8x16 font
919 Currently interlace and doubleline mode in var are ignored.
920 On SM124 and TV only the standard resolutions can be used.
923 /* Reject uninitialized mode */
924 if (!xres || !yres || !bpp)
927 if (mon_type == F_MON_SM && bpp != 1)
932 par->hw.falcon.f_shift = 0x400;
933 par->hw.falcon.st_shift = 0x200;
934 } else if (bpp <= 2) {
936 par->hw.falcon.f_shift = 0x000;
937 par->hw.falcon.st_shift = 0x100;
938 } else if (bpp <= 4) {
940 par->hw.falcon.f_shift = 0x000;
941 par->hw.falcon.st_shift = 0x000;
942 } else if (bpp <= 8) {
944 par->hw.falcon.f_shift = 0x010;
945 } else if (bpp <= 16) {
946 bpp = 16; /* packed pixel mode */
947 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
950 par->hw.falcon.bpp = bpp;
952 if (mon_type == F_MON_SM || DontCalcRes) {
953 /* Skip all calculations. VGA/TV/SC1224 only supported. */
954 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
956 if (bpp > myvar->bits_per_pixel ||
957 var->xres > myvar->xres ||
958 var->yres > myvar->yres)
960 fbhw->get_par(par); /* Current par will be new par */
961 goto set_screen_base; /* Don't forget this */
964 /* Only some fixed resolutions < 640x400 */
967 else if (xres <= 640 && bpp != 16)
971 else if (yres <= 240)
973 else if (yres <= 400)
976 /* 2 planes must use STE compatibility mode */
977 par->hw.falcon.ste_mode = bpp == 2;
978 par->hw.falcon.mono = bpp == 1;
980 /* Total and visible scanline length must be a multiple of one longword,
981 * this and the console fontwidth yields the alignment for xres and
983 * TODO: this way "odd" fontheights are not supported
985 * Special case in STE mode: blank and graphic positions don't align,
986 * avoid trash at right margin
988 if (par->hw.falcon.ste_mode)
989 xres = (xres + 63) & ~63;
991 xres = (xres + 31) & ~31;
993 xres = (xres + 15) & ~15;
995 yres = (yres + 15) & ~15;
997 yres = (yres + 7) & ~7;
999 if (xres_virtual < xres)
1000 xres_virtual = xres;
1002 xres_virtual = (xres_virtual + 31) & ~31;
1004 xres_virtual = (xres_virtual + 15) & ~15;
1006 if (yres_virtual <= 0)
1008 else if (yres_virtual < yres)
1009 yres_virtual = yres;
1011 /* backward bug-compatibility */
1012 if (var->pixclock > 1)
1015 par->hw.falcon.line_width = bpp * xres / 16;
1016 par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
1018 /* single or double pixel width */
1019 xstretch = (xres < 640) ? 2 : 1;
1021 #if 0 /* SM124 supports only 640x400, this is rejected above */
1022 if (mon_type == F_MON_SM) {
1023 if (xres != 640 && yres != 400)
1027 /* SM124-mode is special */
1028 par->hw.falcon.ste_mode = 1;
1029 par->hw.falcon.f_shift = 0x000;
1030 par->hw.falcon.st_shift = 0x200;
1031 left_margin = hsync_len = 128 / plen;
1033 /* TODO set all margins */
1036 if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
1037 plen = 2 * xstretch;
1038 if (var->pixclock > f32.t * plen)
1043 if (var->pixclock == 0) {
1044 /* set some minimal margins which center the screen */
1047 hsync_len = pclock->hsync / plen;
1050 vsync_len = interlace ? 3 : 4;
1052 left_margin = var->left_margin;
1053 right_margin = var->right_margin;
1054 hsync_len = var->hsync_len;
1055 upper_margin = var->upper_margin;
1056 lower_margin = var->lower_margin;
1057 vsync_len = var->vsync_len;
1058 if (var->vmode & FB_VMODE_INTERLACED) {
1059 upper_margin = (upper_margin + 1) / 2;
1060 lower_margin = (lower_margin + 1) / 2;
1061 vsync_len = (vsync_len + 1) / 2;
1062 } else if (var->vmode & FB_VMODE_DOUBLE) {
1068 } else { /* F_MON_VGA */
1070 xstretch = 2; /* Double pixel width only for hicolor */
1071 /* Default values are used for vert./hor. timing if no pixelclock given. */
1072 if (var->pixclock == 0) {
1075 /* Choose master pixelclock depending on hor. timing */
1076 plen = 1 * xstretch;
1077 if ((plen * xres + f25.right + f25.hsync + f25.left) *
1078 fb_info.monspecs.hfmin < f25.f)
1080 else if ((plen * xres + f32.right + f32.hsync +
1081 f32.left) * fb_info.monspecs.hfmin < f32.f)
1083 else if ((plen * xres + fext.right + fext.hsync +
1084 fext.left) * fb_info.monspecs.hfmin < fext.f &&
1090 left_margin = pclock->left / plen;
1091 right_margin = pclock->right / plen;
1092 hsync_len = pclock->hsync / plen;
1093 linesize = left_margin + xres + right_margin + hsync_len;
1098 /* Choose largest pixelclock <= wanted clock */
1100 unsigned long pcl = ULONG_MAX;
1102 for (i = 1; i <= 4; i *= 2) {
1103 if (f25.t * i >= var->pixclock &&
1108 if (f32.t * i >= var->pixclock &&
1113 if (fext.t && fext.t * i >= var->pixclock &&
1121 plen = pcl / pclock->t;
1123 left_margin = var->left_margin;
1124 right_margin = var->right_margin;
1125 hsync_len = var->hsync_len;
1126 upper_margin = var->upper_margin;
1127 lower_margin = var->lower_margin;
1128 vsync_len = var->vsync_len;
1129 /* Internal unit is [single lines per (half-)frame] */
1130 if (var->vmode & FB_VMODE_INTERLACED) {
1131 /* # lines in half frame */
1132 /* External unit is [lines per full frame] */
1133 upper_margin = (upper_margin + 1) / 2;
1134 lower_margin = (lower_margin + 1) / 2;
1135 vsync_len = (vsync_len + 1) / 2;
1136 } else if (var->vmode & FB_VMODE_DOUBLE) {
1137 /* External unit is [double lines per frame] */
1143 if (pclock == &fext)
1144 longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1146 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1147 /* this is definitely wrong if bus clock != 32MHz */
1148 if (pclock->f / plen / 8 * bpp > 32000000L)
1154 /* include sync lengths in right/lower margin for all calculations */
1155 right_margin += hsync_len;
1156 lower_margin += vsync_len;
1158 /* ! In all calculations of margins we use # of lines in half frame
1159 * (which is a full frame in non-interlace mode), so we can switch
1160 * between interlace and non-interlace without messing around
1164 /* Set base_offset 128 and video bus width */
1165 par->hw.falcon.vid_control = mon_type | f030_bus_width;
1167 par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */
1168 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1169 par->hw.falcon.vid_control |= VCO_HSYPOS;
1170 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1171 par->hw.falcon.vid_control |= VCO_VSYPOS;
1173 par->hw.falcon.vid_control |= pclock->control_mask;
1174 /* External or internal clock */
1175 par->hw.falcon.sync = pclock->sync_mask | 0x2;
1176 /* Pixellength and prescale */
1177 par->hw.falcon.vid_mode = (2 / plen) << 2;
1179 par->hw.falcon.vid_mode |= VMO_DOUBLE;
1181 par->hw.falcon.vid_mode |= VMO_INTER;
1183 /*********************
1184 * Horizontal timing: unit = [master clock cycles]
1185 * unit of hxx-registers: [master clock cycles * prescale]
1186 * Hxx-registers are 9 bit wide
1188 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1190 * graphic output = hdb & 0x200 ?
1191 * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1192 * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1193 * (this must be a multiple of plen*128/bpp, on VGA pixels
1194 * to the right may be cut off with a bigger right margin)
1196 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1197 * (hdb - hht - 2) * prescale + hdboff :
1198 * hdb * prescale + hdboff
1200 * end of graphics relative to start of 1st halfline =
1201 * (hde + hht + 2) * prescale + hdeoff
1202 *********************/
1203 /* Calculate VIDEL registers */
1205 prescale = hxx_prescale(&par->hw.falcon);
1206 base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1208 /* Offsets depend on video mode */
1209 /* Offsets are in clock cycles, divide by prescale to
1210 * calculate hd[be]-registers
1212 if (par->hw.falcon.f_shift & 0x100) {
1215 hdb_off = (base_off + 16 * plen) + prescale;
1218 hde_off = ((128 / bpp + 2) * plen);
1219 if (par->hw.falcon.ste_mode)
1220 hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1222 hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1225 gstart = (prescale / 2 + plen * left_margin) / prescale;
1226 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1227 gend1 = gstart + roundup(xres, align) * plen / prescale;
1228 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1229 gend2 = gstart + xres * plen / prescale;
1230 par->HHT = plen * (left_margin + xres + right_margin) /
1232 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1234 par->HDB = gstart - hdb_off / prescale;
1237 par->HDB += par->HHT + 2 + 0x200;
1238 par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
1239 par->HBB = gend2 - par->HHT - 2;
1241 /* One more Videl constraint: data fetch of two lines must not overlap */
1242 if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1243 /* if this happens increase margins, decrease hfreq. */
1246 if (hde_off % prescale)
1247 par->HBB++; /* compensate for non matching hde and hbb */
1248 par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1249 if (par->HSS < par->HBB)
1250 par->HSS = par->HBB;
1253 /* check hor. frequency */
1254 hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
1255 if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
1256 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1257 /* Too high -> enlarge margin */
1262 if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1266 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1267 * of the first displayed line!
1268 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1269 * non-interlace, odd in interlace mode for synchronisation.
1270 * Vxx-registers are 11 bit wide
1272 par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1273 par->VDB = par->VBE;
1278 par->VDE <<= 1; /* VDE now half lines per (half-)frame */
1279 par->VDE += par->VDB;
1280 par->VBB = par->VDE;
1281 par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1282 par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
1283 /* vbb,vss,vft must be even in interlace mode */
1290 /* V-frequency check, hope I didn't create any loop here. */
1291 /* Interlace and doubleline are mutually exclusive. */
1292 vfreq = (hfreq * 2) / (par->VFT + 1);
1293 if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1294 /* Too high -> try again with doubleline */
1297 } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1298 /* Too low -> try again with interlace */
1301 } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1302 /* Doubleline too low -> clear doubleline and enlarge margins */
1306 (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
1307 fb_info.monspecs.vfmax;
1310 upper_margin += lines;
1311 lower_margin += lines;
1313 } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1314 /* Doubleline too high -> enlarge margins */
1317 (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1318 fb_info.monspecs.vfmax;
1321 upper_margin += lines;
1322 lower_margin += lines;
1324 } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1325 /* Interlace, too high -> enlarge margins */
1328 (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1329 fb_info.monspecs.vfmax;
1332 upper_margin += lines;
1333 lower_margin += lines;
1335 } else if (vfreq < fb_info.monspecs.vfmin ||
1336 vfreq > fb_info.monspecs.vfmax)
1340 linelen = xres_virtual * bpp / 8;
1341 if (yres_virtual * linelen > screen_len && screen_len)
1343 if (yres * linelen > screen_len && screen_len)
1345 if (var->yoffset + yres > yres_virtual && yres_virtual)
1347 par->yres_virtual = yres_virtual;
1348 par->screen_base = screen_base + var->yoffset * linelen;
1349 par->hw.falcon.xoffset = 0;
1351 par->next_line = linelen;
1356 static int falcon_encode_var(struct fb_var_screeninfo *var,
1357 struct atafb_par *par)
1359 /* !!! only for VGA !!! */
1362 int hdb_off, hde_off, base_off;
1363 struct falcon_hw *hw = &par->hw.falcon;
1365 memset(var, 0, sizeof(struct fb_var_screeninfo));
1366 /* possible frequencies: 25.175 or 32MHz */
1367 var->pixclock = hw->sync & 0x1 ? fext.t :
1368 hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1374 if (hw->vid_control & VCO_HSYPOS)
1375 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1376 if (hw->vid_control & VCO_VSYPOS)
1377 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1379 var->vmode = FB_VMODE_NONINTERLACED;
1380 if (hw->vid_mode & VMO_INTER)
1381 var->vmode |= FB_VMODE_INTERLACED;
1382 if (hw->vid_mode & VMO_DOUBLE)
1383 var->vmode |= FB_VMODE_DOUBLE;
1385 /* visible y resolution:
1386 * Graphics display starts at line VDB and ends at line
1387 * VDE. If interlace mode off unit of VC-registers is
1388 * half lines, else lines.
1390 var->yres = hw->vde - hw->vdb;
1391 if (!(var->vmode & FB_VMODE_INTERLACED))
1393 if (var->vmode & FB_VMODE_DOUBLE)
1397 * to get bpp, we must examine f_shift and st_shift.
1398 * f_shift is valid if any of bits no. 10, 8 or 4
1399 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1400 * if bit 10 set then bit 8 and bit 4 don't care...
1401 * If all these bits are 0 get display depth from st_shift
1402 * (as for ST and STE)
1404 if (hw->f_shift & 0x400) /* 2 colors */
1405 var->bits_per_pixel = 1;
1406 else if (hw->f_shift & 0x100) /* hicolor */
1407 var->bits_per_pixel = 16;
1408 else if (hw->f_shift & 0x010) /* 8 bitplanes */
1409 var->bits_per_pixel = 8;
1410 else if (hw->st_shift == 0)
1411 var->bits_per_pixel = 4;
1412 else if (hw->st_shift == 0x100)
1413 var->bits_per_pixel = 2;
1414 else /* if (hw->st_shift == 0x200) */
1415 var->bits_per_pixel = 1;
1417 var->xres = hw->line_width * 16 / var->bits_per_pixel;
1418 var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1420 var->xres_virtual += 16;
1422 if (var->bits_per_pixel == 16) {
1423 var->red.offset = 11;
1424 var->red.length = 5;
1425 var->red.msb_right = 0;
1426 var->green.offset = 5;
1427 var->green.length = 6;
1428 var->green.msb_right = 0;
1429 var->blue.offset = 0;
1430 var->blue.length = 5;
1431 var->blue.msb_right = 0;
1433 var->red.offset = 0;
1434 var->red.length = hw->ste_mode ? 4 : 6;
1435 if (var->red.length > var->bits_per_pixel)
1436 var->red.length = var->bits_per_pixel;
1437 var->red.msb_right = 0;
1439 var->blue = var->green = var->red;
1441 var->transp.offset = 0;
1442 var->transp.length = 0;
1443 var->transp.msb_right = 0;
1445 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1447 if (par->yres_virtual)
1448 var->yres_virtual = par->yres_virtual;
1450 /* yres_virtual == 0 means use maximum */
1451 var->yres_virtual = screen_len / linelen;
1454 var->yres_virtual = 2 * var->yres;
1456 var->yres_virtual = var->yres + hwscroll * 16;
1458 var->xoffset = 0; /* TODO change this */
1461 prescale = hxx_prescale(hw);
1462 plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1463 base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1464 if (hw->f_shift & 0x100) {
1466 hdb_off = (base_off + 16 * plen) + prescale;
1468 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1470 hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1473 hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1477 /* Right margin includes hsync */
1478 var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1479 (hw->hdb & 0x200 ? 2 + hw->hht : 0));
1480 if (hw->ste_mode || mon_type != F_MON_VGA)
1481 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1483 /* can't use this in ste_mode, because hbb is +1 off */
1484 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1485 var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1487 /* Lower margin includes vsync */
1488 var->upper_margin = hw->vdb / 2; /* round down to full lines */
1489 var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2; /* round up */
1490 var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2; /* round up */
1491 if (var->vmode & FB_VMODE_INTERLACED) {
1492 var->upper_margin *= 2;
1493 var->lower_margin *= 2;
1494 var->vsync_len *= 2;
1495 } else if (var->vmode & FB_VMODE_DOUBLE) {
1496 var->upper_margin = (var->upper_margin + 1) / 2;
1497 var->lower_margin = (var->lower_margin + 1) / 2;
1498 var->vsync_len = (var->vsync_len + 1) / 2;
1501 var->pixclock *= plen;
1502 var->left_margin /= plen;
1503 var->right_margin /= plen;
1504 var->hsync_len /= plen;
1506 var->right_margin -= var->hsync_len;
1507 var->lower_margin -= var->vsync_len;
1510 var->yoffset = (par->screen_base - screen_base) / linelen;
1513 var->nonstd = 0; /* what is this for? */
1518 static int f_change_mode;
1519 static struct falcon_hw f_new_mode;
1520 static int f_pan_display;
1522 static void falcon_get_par(struct atafb_par *par)
1525 struct falcon_hw *hw = &par->hw.falcon;
1527 hw->line_width = shifter_f030.scn_width;
1528 hw->line_offset = shifter_f030.off_next;
1529 hw->st_shift = videl.st_shift & 0x300;
1530 hw->f_shift = videl.f_shift;
1531 hw->vid_control = videl.control;
1532 hw->vid_mode = videl.mode;
1533 hw->sync = shifter_st.syncmode & 0x1;
1534 hw->xoffset = videl.xoffset & 0xf;
1535 hw->hht = videl.hht;
1536 hw->hbb = videl.hbb;
1537 hw->hbe = videl.hbe;
1538 hw->hdb = videl.hdb;
1539 hw->hde = videl.hde;
1540 hw->hss = videl.hss;
1541 hw->vft = videl.vft;
1542 hw->vbb = videl.vbb;
1543 hw->vbe = videl.vbe;
1544 hw->vdb = videl.vdb;
1545 hw->vde = videl.vde;
1546 hw->vss = videl.vss;
1548 addr = (shifter_st.bas_hi & 0xff) << 16 |
1549 (shifter_st.bas_md & 0xff) << 8 |
1550 (shifter_st.bas_lo & 0xff);
1551 par->screen_base = atari_stram_to_virt(addr);
1553 /* derived parameters */
1554 hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
1555 hw->mono = (hw->f_shift & 0x400) ||
1556 ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
1559 static void falcon_set_par(struct atafb_par *par)
1563 /* only set screen_base if really necessary */
1564 if (current_par.screen_base != par->screen_base)
1565 fbhw->set_screen_base(par->screen_base);
1567 /* Don't touch any other registers if we keep the default resolution */
1571 /* Tell vbl-handler to change video mode.
1572 * We change modes only on next VBL, to avoid desynchronisation
1573 * (a shift to the right and wrap around by a random number of pixels
1574 * in all monochrome modes).
1575 * This seems to work on my Falcon.
1577 f_new_mode = par->hw.falcon;
1581 static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
1583 struct falcon_hw *hw = &f_new_mode;
1585 if (f_change_mode) {
1588 if (hw->sync & 0x1) {
1589 /* Enable external pixelclock. This code only for ScreenWonder */
1590 *(volatile unsigned short *)0xffff9202 = 0xffbf;
1592 /* Turn off external clocks. Read sets all output bits to 1. */
1593 *(volatile unsigned short *)0xffff9202;
1595 shifter_st.syncmode = hw->sync;
1597 videl.hht = hw->hht;
1598 videl.hbb = hw->hbb;
1599 videl.hbe = hw->hbe;
1600 videl.hdb = hw->hdb;
1601 videl.hde = hw->hde;
1602 videl.hss = hw->hss;
1603 videl.vft = hw->vft;
1604 videl.vbb = hw->vbb;
1605 videl.vbe = hw->vbe;
1606 videl.vdb = hw->vdb;
1607 videl.vde = hw->vde;
1608 videl.vss = hw->vss;
1610 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1612 videl.st_shift = hw->st_shift; /* write enables STE palette */
1615 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1616 * Writing 0 to f_shift enables 4 plane Falcon mode but
1617 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1618 * with Falcon palette.
1621 /* now back to Falcon palette mode */
1622 videl.f_shift = hw->f_shift;
1624 /* writing to st_shift changed scn_width and vid_mode */
1625 videl.xoffset = hw->xoffset;
1626 shifter_f030.scn_width = hw->line_width;
1627 shifter_f030.off_next = hw->line_offset;
1628 videl.control = hw->vid_control;
1629 videl.mode = hw->vid_mode;
1631 if (f_pan_display) {
1633 videl.xoffset = current_par.hw.falcon.xoffset;
1634 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1639 static int falcon_pan_display(struct fb_var_screeninfo *var,
1640 struct fb_info *info)
1642 struct atafb_par *par = (struct atafb_par *)info->par;
1645 int bpp = info->var.bits_per_pixel;
1648 var->xoffset = round_up(var->xoffset, 32);
1650 par->hw.falcon.xoffset = var->xoffset & 15;
1652 par->hw.falcon.xoffset = 0;
1653 var->xoffset = round_up(var->xoffset, 2);
1655 par->hw.falcon.line_offset = bpp *
1656 (info->var.xres_virtual - info->var.xres) / 16;
1657 if (par->hw.falcon.xoffset)
1658 par->hw.falcon.line_offset -= bpp;
1659 xoffset = var->xoffset - par->hw.falcon.xoffset;
1661 par->screen_base = screen_base +
1662 (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
1663 if (fbhw->set_screen_base)
1664 fbhw->set_screen_base(par->screen_base);
1666 return -EINVAL; /* shouldn't happen */
1671 static int falcon_setcolreg(unsigned int regno, unsigned int red,
1672 unsigned int green, unsigned int blue,
1673 unsigned int transp, struct fb_info *info)
1677 f030_col[regno] = (((red & 0xfc00) << 16) |
1678 ((green & 0xfc00) << 8) |
1679 ((blue & 0xfc00) >> 8));
1681 shifter_tt.color_reg[regno] =
1682 ((((red & 0xe000) >> 13) | ((red & 0x1000) >> 12)) << 8) |
1683 ((((green & 0xe000) >> 13) | ((green & 0x1000) >> 12)) << 4) |
1684 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1685 ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
1686 ((green & 0xfc00) >> 5) |
1687 ((blue & 0xf800) >> 11));
1692 static int falcon_blank(int blank_mode)
1694 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1695 * so VIDEL doesn't hog the bus while saving.
1696 * (this may affect usleep()).
1698 int vdb, vss, hbe, hss;
1700 if (mon_type == F_MON_SM) /* this doesn't work on SM124 */
1703 vdb = current_par.VDB;
1704 vss = current_par.VSS;
1705 hbe = current_par.HBE;
1706 hss = current_par.HSS;
1708 if (blank_mode >= 1) {
1709 /* disable graphics output (this speeds up the CPU) ... */
1710 vdb = current_par.VFT + 1;
1711 /* ... and blank all lines */
1712 hbe = current_par.HHT + 2;
1714 /* use VESA suspend modes on VGA monitors */
1715 if (mon_type == F_MON_VGA) {
1716 if (blank_mode == 2 || blank_mode == 4)
1717 vss = current_par.VFT + 1;
1718 if (blank_mode == 3 || blank_mode == 4)
1719 hss = current_par.HHT + 2;
1730 static int falcon_detect(void)
1732 struct atafb_par par;
1735 /* Determine connected monitor and set monitor parameters */
1736 fhw = *(unsigned char *)0xffff8006;
1737 mon_type = fhw >> 6 & 0x3;
1738 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1739 f030_bus_width = fhw << 6 & 0x80;
1742 fb_info.monspecs.vfmin = 70;
1743 fb_info.monspecs.vfmax = 72;
1744 fb_info.monspecs.hfmin = 35713;
1745 fb_info.monspecs.hfmax = 35715;
1750 fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
1751 fb_info.monspecs.vfmax = 60;
1752 fb_info.monspecs.hfmin = 15620;
1753 fb_info.monspecs.hfmax = 15755;
1756 /* initialize hsync-len */
1757 f25.hsync = h_syncs[mon_type] / f25.t;
1758 f32.hsync = h_syncs[mon_type] / f32.t;
1760 fext.hsync = h_syncs[mon_type] / fext.t;
1762 falcon_get_par(&par);
1763 falcon_encode_var(&atafb_predefined[0], &par);
1765 /* Detected mode is always the "autodetect" slot */
1769 #endif /* ATAFB_FALCON */
1771 /* ------------------- ST(E) specific functions ---------------------- */
1775 static int stste_encode_fix(struct fb_fix_screeninfo *fix,
1776 struct atafb_par *par)
1780 strcpy(fix->id, "Atari Builtin");
1781 fix->smem_start = phys_screen_base;
1782 fix->smem_len = screen_len;
1783 fix->type = FB_TYPE_INTERLEAVED_PLANES;
1785 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1786 mode = par->hw.st.mode & 3;
1787 if (mode == ST_HIGH) {
1788 fix->type = FB_TYPE_PACKED_PIXELS;
1790 fix->visual = FB_VISUAL_MONO10;
1792 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1800 fix->line_length = par->next_line;
1801 fix->accel = FB_ACCEL_ATARIBLITT;
1805 static int stste_decode_var(struct fb_var_screeninfo *var,
1806 struct atafb_par *par)
1808 int xres = var->xres;
1809 int yres = var->yres;
1810 int bpp = var->bits_per_pixel;
1812 int yres_virtual = var->yres_virtual;
1815 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1817 par->hw.st.mode = ST_HIGH;
1822 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1825 if (xres > sttt_xres / 2 || yres > st_yres / 2)
1827 par->hw.st.mode = ST_LOW;
1828 xres = sttt_xres / 2;
1831 } else if (bpp > 1) {
1832 if (xres > sttt_xres || yres > st_yres / 2)
1834 par->hw.st.mode = ST_MID;
1841 if (yres_virtual <= 0)
1843 else if (yres_virtual < yres)
1844 yres_virtual = yres;
1845 if (var->sync & FB_SYNC_EXT)
1846 par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
1848 par->hw.st.sync = (par->hw.st.sync & ~1);
1849 linelen = xres * bpp / 8;
1850 if (yres_virtual * linelen > screen_len && screen_len)
1852 if (yres * linelen > screen_len && screen_len)
1854 if (var->yoffset + yres > yres_virtual && yres_virtual)
1856 par->yres_virtual = yres_virtual;
1857 par->screen_base = screen_base + var->yoffset * linelen;
1858 par->next_line = linelen;
1862 static int stste_encode_var(struct fb_var_screeninfo *var,
1863 struct atafb_par *par)
1866 memset(var, 0, sizeof(struct fb_var_screeninfo));
1867 var->red.offset = 0;
1868 var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1869 var->red.msb_right = 0;
1872 var->pixclock = 31041;
1873 var->left_margin = 120; /* these are incorrect */
1874 var->right_margin = 100;
1875 var->upper_margin = 8;
1876 var->lower_margin = 16;
1877 var->hsync_len = 140;
1878 var->vsync_len = 30;
1883 if (!(par->hw.st.sync & 1))
1886 var->sync = FB_SYNC_EXT;
1888 switch (par->hw.st.mode & 3) {
1890 var->xres = sttt_xres / 2;
1891 var->yres = st_yres / 2;
1892 var->bits_per_pixel = 4;
1895 var->xres = sttt_xres;
1896 var->yres = st_yres / 2;
1897 var->bits_per_pixel = 2;
1900 var->xres = sttt_xres;
1901 var->yres = st_yres;
1902 var->bits_per_pixel = 1;
1905 var->blue = var->green = var->red;
1906 var->transp.offset = 0;
1907 var->transp.length = 0;
1908 var->transp.msb_right = 0;
1909 var->xres_virtual = sttt_xres_virtual;
1910 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1911 ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
1914 var->yres_virtual = var->yres;
1915 else if (screen_len) {
1916 if (par->yres_virtual)
1917 var->yres_virtual = par->yres_virtual;
1919 /* yres_virtual == 0 means use maximum */
1920 var->yres_virtual = screen_len / linelen;
1923 var->yres_virtual = 2 * var->yres;
1925 var->yres_virtual = var->yres + hwscroll * 16;
1929 var->yoffset = (par->screen_base - screen_base) / linelen;
1934 var->vmode = FB_VMODE_NONINTERLACED;
1938 static void stste_get_par(struct atafb_par *par)
1941 par->hw.st.mode = shifter_tt.st_shiftmode;
1942 par->hw.st.sync = shifter_st.syncmode;
1943 addr = ((shifter_st.bas_hi & 0xff) << 16) |
1944 ((shifter_st.bas_md & 0xff) << 8);
1945 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1946 addr |= (shifter_st.bas_lo & 0xff);
1947 par->screen_base = atari_stram_to_virt(addr);
1950 static void stste_set_par(struct atafb_par *par)
1952 shifter_tt.st_shiftmode = par->hw.st.mode;
1953 shifter_st.syncmode = par->hw.st.sync;
1954 /* only set screen_base if really necessary */
1955 if (current_par.screen_base != par->screen_base)
1956 fbhw->set_screen_base(par->screen_base);
1959 static int stste_setcolreg(unsigned int regno, unsigned int red,
1960 unsigned int green, unsigned int blue,
1961 unsigned int transp, struct fb_info *info)
1968 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1969 shifter_tt.color_reg[regno] =
1970 ((((red & 0xe) >> 1) | ((red & 1) << 3)) << 8) |
1971 ((((green & 0xe) >> 1) | ((green & 1) << 3)) << 4) |
1972 ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1974 shifter_tt.color_reg[regno] =
1975 ((red & 0xe) << 7) |
1976 ((green & 0xe) << 3) |
1977 ((blue & 0xe) >> 1);
1981 static int stste_detect(void)
1983 struct atafb_par par;
1985 /* Determine the connected monitor: The DMA sound must be
1986 * disabled before reading the MFP GPIP, because the Sound
1987 * Done Signal and the Monochrome Detect are XORed together!
1989 if (ATARIHW_PRESENT(PCM_8BIT)) {
1990 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1991 udelay(20); /* wait a while for things to settle down */
1993 mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
1995 stste_get_par(&par);
1996 stste_encode_var(&atafb_predefined[0], &par);
1998 if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2003 static void stste_set_screen_base(void *s_base)
2006 addr = atari_stram_to_phys(s_base);
2007 /* Setup Screen Memory */
2008 shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2009 shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2010 if (ATARIHW_PRESENT(EXTD_SHIFTER))
2011 shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
2014 #endif /* ATAFB_STE */
2016 /* Switching the screen size should be done during vsync, otherwise
2017 * the margins may get messed up. This is a well known problem of
2018 * the ST's video system.
2020 * Unfortunately there is hardly any way to find the vsync, as the
2021 * vertical blank interrupt is no longer in time on machines with
2022 * overscan type modifications.
2024 * We can, however, use Timer B to safely detect the black shoulder,
2025 * but then we've got to guess an appropriate delay to find the vsync.
2026 * This might not work on every machine.
2028 * martin_rogge @ ki.maus.de, 8th Aug 1995
2031 #define LINE_DELAY (mono_moni ? 30 : 70)
2032 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2034 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2035 static void st_ovsc_switch(void)
2037 unsigned long flags;
2038 register unsigned char old, new;
2040 if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2042 local_irq_save(flags);
2044 st_mfp.tim_ct_b = 0x10;
2045 st_mfp.active_edge |= 8;
2046 st_mfp.tim_ct_b = 0;
2047 st_mfp.tim_dt_b = 0xf0;
2048 st_mfp.tim_ct_b = 8;
2049 while (st_mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2051 new = st_mfp.tim_dt_b;
2055 new = st_mfp.tim_dt_b;
2056 } while (old != new);
2057 st_mfp.tim_ct_b = 0x10;
2060 if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2061 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2062 if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2063 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2064 if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2065 sound_ym.rd_data_reg_sel = 14;
2066 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2067 ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2068 ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2070 local_irq_restore(flags);
2073 /* ------------------- External Video ---------------------- */
2077 static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
2079 strcpy(fix->id, "Unknown Extern");
2080 fix->smem_start = external_addr;
2081 fix->smem_len = PAGE_ALIGN(external_len);
2082 if (external_depth == 1) {
2083 fix->type = FB_TYPE_PACKED_PIXELS;
2084 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2085 * for "normal" and "inverted", rsp., in the monochrome case */
2087 (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2088 external_pmode == FB_TYPE_PACKED_PIXELS) ?
2089 FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
2091 /* Use STATIC if we don't know how to access color registers */
2092 int visual = external_vgaiobase ?
2093 FB_VISUAL_PSEUDOCOLOR :
2094 FB_VISUAL_STATIC_PSEUDOCOLOR;
2095 switch (external_pmode) {
2096 case -1: /* truecolor */
2097 fix->type = FB_TYPE_PACKED_PIXELS;
2098 fix->visual = FB_VISUAL_TRUECOLOR;
2100 case FB_TYPE_PACKED_PIXELS:
2101 fix->type = FB_TYPE_PACKED_PIXELS;
2102 fix->visual = visual;
2104 case FB_TYPE_PLANES:
2105 fix->type = FB_TYPE_PLANES;
2106 fix->visual = visual;
2108 case FB_TYPE_INTERLEAVED_PLANES:
2109 fix->type = FB_TYPE_INTERLEAVED_PLANES;
2111 fix->visual = visual;
2118 fix->line_length = par->next_line;
2122 static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2124 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2126 if (var->bits_per_pixel > myvar->bits_per_pixel ||
2127 var->xres > myvar->xres ||
2128 var->xres_virtual > myvar->xres_virtual ||
2129 var->yres > myvar->yres ||
2134 par->next_line = external_xres_virtual * external_depth / 8;
2138 static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2140 memset(var, 0, sizeof(struct fb_var_screeninfo));
2141 var->red.offset = 0;
2142 var->red.length = (external_pmode == -1) ? external_depth / 3 :
2143 (external_vgaiobase ? external_bitspercol : 0);
2144 var->red.msb_right = 0;
2147 var->pixclock = 31041;
2148 var->left_margin = 120; /* these are surely incorrect */
2149 var->right_margin = 100;
2150 var->upper_margin = 8;
2151 var->lower_margin = 16;
2152 var->hsync_len = 140;
2153 var->vsync_len = 30;
2160 var->xres = external_xres;
2161 var->yres = external_yres;
2162 var->xres_virtual = external_xres_virtual;
2163 var->bits_per_pixel = external_depth;
2165 var->blue = var->green = var->red;
2166 var->transp.offset = 0;
2167 var->transp.length = 0;
2168 var->transp.msb_right = 0;
2169 var->yres_virtual = var->yres;
2174 var->vmode = FB_VMODE_NONINTERLACED;
2178 static void ext_get_par(struct atafb_par *par)
2180 par->screen_base = external_screen_base;
2183 static void ext_set_par(struct atafb_par *par)
2187 #define OUTB(port,val) \
2188 *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2190 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2193 unsigned char tmp = INB(0x3da); \
2197 static int ext_setcolreg(unsigned int regno, unsigned int red,
2198 unsigned int green, unsigned int blue,
2199 unsigned int transp, struct fb_info *info)
2201 unsigned char colmask = (1 << external_bitspercol) - 1;
2203 if (!external_vgaiobase)
2209 switch (external_card_type) {
2213 OUTB(0x3c9, red & colmask);
2215 OUTB(0x3c9, green & colmask);
2217 OUTB(0x3c9, blue & colmask);
2222 OUTB((MV300_reg[regno] << 2) + 1, red);
2223 OUTB((MV300_reg[regno] << 2) + 1, green);
2224 OUTB((MV300_reg[regno] << 2) + 1, blue);
2232 static int ext_detect(void)
2234 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2235 struct atafb_par dummy_par;
2237 myvar->xres = external_xres;
2238 myvar->xres_virtual = external_xres_virtual;
2239 myvar->yres = external_yres;
2240 myvar->bits_per_pixel = external_depth;
2241 ext_encode_var(myvar, &dummy_par);
2245 #endif /* ATAFB_EXT */
2247 /* ------ This is the same for most hardware types -------- */
2249 static void set_screen_base(void *s_base)
2253 addr = atari_stram_to_phys(s_base);
2254 /* Setup Screen Memory */
2255 shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2256 shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2257 shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
2260 static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2262 struct atafb_par *par = (struct atafb_par *)info->par;
2264 if (!fbhw->set_screen_base ||
2265 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2267 var->xoffset = round_up(var->xoffset, 16);
2268 par->screen_base = screen_base +
2269 (var->yoffset * info->var.xres_virtual + var->xoffset)
2270 * info->var.bits_per_pixel / 8;
2271 fbhw->set_screen_base(par->screen_base);
2275 /* ------------ Interfaces to hardware functions ------------ */
2278 static struct fb_hwswitch tt_switch = {
2279 .detect = tt_detect,
2280 .encode_fix = tt_encode_fix,
2281 .decode_var = tt_decode_var,
2282 .encode_var = tt_encode_var,
2283 .get_par = tt_get_par,
2284 .set_par = tt_set_par,
2285 .set_screen_base = set_screen_base,
2286 .pan_display = pan_display,
2291 static struct fb_hwswitch falcon_switch = {
2292 .detect = falcon_detect,
2293 .encode_fix = falcon_encode_fix,
2294 .decode_var = falcon_decode_var,
2295 .encode_var = falcon_encode_var,
2296 .get_par = falcon_get_par,
2297 .set_par = falcon_set_par,
2298 .set_screen_base = set_screen_base,
2299 .blank = falcon_blank,
2300 .pan_display = falcon_pan_display,
2305 static struct fb_hwswitch st_switch = {
2306 .detect = stste_detect,
2307 .encode_fix = stste_encode_fix,
2308 .decode_var = stste_decode_var,
2309 .encode_var = stste_encode_var,
2310 .get_par = stste_get_par,
2311 .set_par = stste_set_par,
2312 .set_screen_base = stste_set_screen_base,
2313 .pan_display = pan_display
2318 static struct fb_hwswitch ext_switch = {
2319 .detect = ext_detect,
2320 .encode_fix = ext_encode_fix,
2321 .decode_var = ext_decode_var,
2322 .encode_var = ext_encode_var,
2323 .get_par = ext_get_par,
2324 .set_par = ext_set_par,
2328 static void ata_get_par(struct atafb_par *par)
2330 if (current_par_valid)
2336 static void ata_set_par(struct atafb_par *par)
2340 current_par_valid = 1;
2344 /* =========================================================== */
2345 /* ============== Hardware Independent Functions ============= */
2346 /* =========================================================== */
2348 /* used for hardware scrolling */
2350 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2353 struct atafb_par par;
2355 err = fbhw->decode_var(var, &par);
2358 activate = var->activate;
2359 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2361 fbhw->encode_var(var, &par);
2362 var->activate = activate;
2366 /* fbhw->encode_fix() must be called with fb_info->mm_lock held
2367 * if it is called after the register_framebuffer() - not a case here
2369 static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2371 struct atafb_par par;
2373 // Get fix directly (case con == -1 before)??
2374 err = fbhw->decode_var(&info->var, &par);
2377 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2378 err = fbhw->encode_fix(fix, &par);
2382 static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
2384 struct atafb_par par;
2387 fbhw->encode_var(var, &par);
2392 // No longer called by fbcon!
2393 // Still called by set_var internally
2395 static void atafb_set_disp(struct fb_info *info)
2397 atafb_get_var(&info->var, info);
2398 atafb_get_fix(&info->fix, info);
2400 /* Note: smem_start derives from phys_screen_base, not screen_base! */
2401 info->screen_base = (external_addr ? external_screen_base :
2402 atari_stram_to_virt(info->fix.smem_start));
2406 atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2408 if (!fbhw->pan_display)
2411 return fbhw->pan_display(var, info);
2415 * generic drawing routines; imageblit needs updating for image depth > 1
2418 #if BITS_PER_LONG == 32
2419 #define BYTES_PER_LONG 4
2420 #define SHIFT_PER_LONG 5
2421 #elif BITS_PER_LONG == 64
2422 #define BYTES_PER_LONG 8
2423 #define SHIFT_PER_LONG 6
2425 #define Please update me
2429 static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
2431 struct atafb_par *par = (struct atafb_par *)info->par;
2435 if (!rect->width || !rect->height)
2439 if (info->var.bits_per_pixel == 16) {
2440 cfb_fillrect(info, rect);
2446 * We could use hardware clipping but on many cards you get around
2447 * hardware clipping by writing to framebuffer directly.
2449 x2 = rect->dx + rect->width;
2450 y2 = rect->dy + rect->height;
2451 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2452 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2453 width = x2 - rect->dx;
2454 height = y2 - rect->dy;
2456 if (info->var.bits_per_pixel == 1)
2457 atafb_mfb_fillrect(info, par->next_line, rect->color,
2458 rect->dy, rect->dx, height, width);
2459 else if (info->var.bits_per_pixel == 2)
2460 atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
2461 rect->dy, rect->dx, height, width);
2462 else if (info->var.bits_per_pixel == 4)
2463 atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
2464 rect->dy, rect->dx, height, width);
2466 atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
2467 rect->dy, rect->dx, height, width);
2472 static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2474 struct atafb_par *par = (struct atafb_par *)info->par;
2476 u32 dx, dy, sx, sy, width, height;
2480 if (info->var.bits_per_pixel == 16) {
2481 cfb_copyarea(info, area);
2486 /* clip the destination */
2487 x2 = area->dx + area->width;
2488 y2 = area->dy + area->height;
2489 dx = area->dx > 0 ? area->dx : 0;
2490 dy = area->dy > 0 ? area->dy : 0;
2491 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2492 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2496 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2500 sx = area->sx + (dx - area->dx);
2501 sy = area->sy + (dy - area->dy);
2503 /* the source must be completely inside the virtual screen */
2504 if (sx + width > info->var.xres_virtual ||
2505 sy + height > info->var.yres_virtual)
2508 if (dy > sy || (dy == sy && dx > sx)) {
2514 if (info->var.bits_per_pixel == 1)
2515 atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2516 else if (info->var.bits_per_pixel == 2)
2517 atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2518 else if (info->var.bits_per_pixel == 4)
2519 atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2521 atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2526 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2528 struct atafb_par *par = (struct atafb_par *)info->par;
2533 u32 dx, dy, width, height, pitch;
2536 if (info->var.bits_per_pixel == 16) {
2537 cfb_imageblit(info, image);
2543 * We could use hardware clipping but on many cards you get around
2544 * hardware clipping by writing to framebuffer directly like we are
2547 x2 = image->dx + image->width;
2548 y2 = image->dy + image->height;
2551 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2552 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2556 if (image->depth == 1) {
2557 // used for font data
2558 dst = (unsigned long *)
2559 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2560 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2561 dst_idx += dy * par->next_line * 8 + dx;
2563 pitch = (image->width + 7) / 8;
2566 if (info->var.bits_per_pixel == 1)
2567 atafb_mfb_linefill(info, par->next_line,
2569 image->bg_color, image->fg_color);
2570 else if (info->var.bits_per_pixel == 2)
2571 atafb_iplan2p2_linefill(info, par->next_line,
2573 image->bg_color, image->fg_color);
2574 else if (info->var.bits_per_pixel == 4)
2575 atafb_iplan2p4_linefill(info, par->next_line,
2577 image->bg_color, image->fg_color);
2579 atafb_iplan2p8_linefill(info, par->next_line,
2581 image->bg_color, image->fg_color);
2586 c2p_iplan2(info->screen_base, image->data, dx, dy, width,
2587 height, par->next_line, image->width,
2588 info->var.bits_per_pixel);
2593 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2596 #ifdef FBCMD_GET_CURRENTPAR
2597 case FBCMD_GET_CURRENTPAR:
2598 if (copy_to_user((void *)arg, (void *)¤t_par,
2599 sizeof(struct atafb_par)))
2603 #ifdef FBCMD_SET_CURRENTPAR
2604 case FBCMD_SET_CURRENTPAR:
2605 if (copy_from_user((void *)¤t_par, (void *)arg,
2606 sizeof(struct atafb_par)))
2608 ata_set_par(¤t_par);
2615 /* (un)blank/poweroff
2622 static int atafb_blank(int blank, struct fb_info *info)
2624 unsigned short black[16];
2625 struct fb_cmap cmap;
2626 if (fbhw->blank && !fbhw->blank(blank))
2629 memset(black, 0, 16 * sizeof(unsigned short));
2636 fb_set_cmap(&cmap, info);
2640 do_install_cmap(info);
2646 * New fbcon interface ...
2649 /* check var by decoding var into hw par, rounding if necessary,
2650 * then encoding hw par back into new, validated var */
2651 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2654 struct atafb_par par;
2656 /* Validate wanted screen parameters */
2657 // if ((err = ata_decode_var(var, &par)))
2658 err = fbhw->decode_var(var, &par);
2662 /* Encode (possibly rounded) screen parameters */
2663 fbhw->encode_var(var, &par);
2667 /* actually set hw par by decoding var, then setting hardware from
2668 * hw par just decoded */
2669 static int atafb_set_par(struct fb_info *info)
2671 struct atafb_par *par = (struct atafb_par *)info->par;
2673 /* Decode wanted screen parameters */
2674 fbhw->decode_var(&info->var, par);
2675 mutex_lock(&info->mm_lock);
2676 fbhw->encode_fix(&info->fix, par);
2677 mutex_unlock(&info->mm_lock);
2679 /* Set new videomode */
2686 static struct fb_ops atafb_ops = {
2687 .owner = THIS_MODULE,
2688 .fb_check_var = atafb_check_var,
2689 .fb_set_par = atafb_set_par,
2690 .fb_blank = atafb_blank,
2691 .fb_pan_display = atafb_pan_display,
2692 .fb_fillrect = atafb_fillrect,
2693 .fb_copyarea = atafb_copyarea,
2694 .fb_imageblit = atafb_imageblit,
2695 .fb_ioctl = atafb_ioctl,
2698 static void check_default_par(int detected_mode)
2700 char default_name[10];
2702 struct fb_var_screeninfo var;
2703 unsigned long min_mem;
2705 /* First try the user supplied mode */
2707 var = atafb_predefined[default_par - 1];
2708 var.activate = FB_ACTIVATE_TEST;
2709 if (do_fb_set_var(&var, 1))
2710 default_par = 0; /* failed */
2712 /* Next is the autodetected one */
2714 var = atafb_predefined[detected_mode - 1]; /* autodetect */
2715 var.activate = FB_ACTIVATE_TEST;
2716 if (!do_fb_set_var(&var, 1))
2717 default_par = detected_mode;
2719 /* If that also failed, try some default modes... */
2721 /* try default1, default2... */
2722 for (i = 1; i < 10; i++) {
2723 sprintf(default_name,"default%d", i);
2724 default_par = get_video_mode(default_name);
2726 panic("can't set default video mode");
2727 var = atafb_predefined[default_par - 1];
2728 var.activate = FB_ACTIVATE_TEST;
2729 if (!do_fb_set_var(&var,1))
2733 min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
2734 if (default_mem_req < min_mem)
2735 default_mem_req = min_mem;
2739 static void __init atafb_setup_ext(char *spec)
2741 int xres, xres_virtual, yres, depth, planes;
2742 unsigned long addr, len;
2745 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2747 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2748 * [;<xres-virtual>]]]]]
2751 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2753 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2755 p = strsep(&spec, ";");
2758 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2762 p = strsep(&spec, ";");
2765 yres = simple_strtoul(p, NULL, 10);
2769 p = strsep(&spec, ";");
2772 depth = simple_strtoul(p, NULL, 10);
2773 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2774 depth != 16 && depth != 24)
2777 p = strsep(&spec, ";");
2781 planes = FB_TYPE_INTERLEAVED_PLANES;
2783 planes = FB_TYPE_PACKED_PIXELS;
2785 planes = FB_TYPE_PLANES;
2787 planes = -1; /* true color */
2791 p = strsep(&spec, ";");
2794 addr = simple_strtoul(p, NULL, 0);
2796 p = strsep(&spec, ";");
2798 len = xres * yres * depth / 8;
2800 len = simple_strtoul(p, NULL, 0);
2802 p = strsep(&spec, ";");
2804 external_vgaiobase = simple_strtoul(p, NULL, 0);
2806 p = strsep(&spec, ";");
2808 external_bitspercol = simple_strtoul(p, NULL, 0);
2809 if (external_bitspercol > 8)
2810 external_bitspercol = 8;
2811 else if (external_bitspercol < 1)
2812 external_bitspercol = 1;
2815 p = strsep(&spec, ";");
2817 if (!strcmp(p, "vga"))
2818 external_card_type = IS_VGA;
2819 if (!strcmp(p, "mv300"))
2820 external_card_type = IS_MV300;
2823 p = strsep(&spec, ";");
2825 xres_virtual = simple_strtoul(p, NULL, 10);
2826 if (xres_virtual < xres)
2827 xres_virtual = xres;
2828 if (xres_virtual * yres * depth / 8 > len)
2829 len = xres_virtual * yres * depth / 8;
2832 external_xres = xres;
2833 external_xres_virtual = xres_virtual;
2834 external_yres = yres;
2835 external_depth = depth;
2836 external_pmode = planes;
2837 external_addr = addr;
2840 if (external_card_type == IS_MV300) {
2841 switch (external_depth) {
2843 MV300_reg = MV300_reg_1bit;
2846 MV300_reg = MV300_reg_4bit;
2849 MV300_reg = MV300_reg_8bit;
2854 #endif /* ATAFB_EXT */
2856 static void __init atafb_setup_int(char *spec)
2858 /* Format to config extended internal video hardware like OverScan:
2859 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2861 * <xres>: x-resolution
2862 * <yres>: y-resolution
2863 * The following are only needed if you have an overscan which
2864 * needs a black border:
2865 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2866 * <yres_max>: max. number of lines your OverScan hardware would allow
2867 * <offset>: Offset from physical beginning to visible beginning
2868 * of screen in bytes
2873 if (!(p = strsep(&spec, ";")) || !*p)
2875 xres = simple_strtoul(p, NULL, 10);
2876 if (!(p = strsep(&spec, ";")) || !*p)
2879 tt_yres = st_yres = simple_strtoul(p, NULL, 10);
2880 if ((p = strsep(&spec, ";")) && *p)
2881 sttt_xres_virtual = simple_strtoul(p, NULL, 10);
2882 if ((p = strsep(&spec, ";")) && *p)
2883 sttt_yres_virtual = simple_strtoul(p, NULL, 0);
2884 if ((p = strsep(&spec, ";")) && *p)
2885 ovsc_offset = simple_strtoul(p, NULL, 0);
2887 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2892 static void __init atafb_setup_mcap(char *spec)
2895 int vmin, vmax, hmin, hmax;
2897 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2898 * <V*> vertical freq. in Hz
2899 * <H*> horizontal freq. in kHz
2901 if (!(p = strsep(&spec, ";")) || !*p)
2903 vmin = simple_strtoul(p, NULL, 10);
2906 if (!(p = strsep(&spec, ";")) || !*p)
2908 vmax = simple_strtoul(p, NULL, 10);
2909 if (vmax <= 0 || vmax <= vmin)
2911 if (!(p = strsep(&spec, ";")) || !*p)
2913 hmin = 1000 * simple_strtoul(p, NULL, 10);
2916 if (!(p = strsep(&spec, "")) || !*p)
2918 hmax = 1000 * simple_strtoul(p, NULL, 10);
2919 if (hmax <= 0 || hmax <= hmin)
2922 fb_info.monspecs.vfmin = vmin;
2923 fb_info.monspecs.vfmax = vmax;
2924 fb_info.monspecs.hfmin = hmin;
2925 fb_info.monspecs.hfmax = hmax;
2927 #endif /* ATAFB_FALCON */
2929 static void __init atafb_setup_user(char *spec)
2931 /* Format of user defined video mode is: <xres>;<yres>;<depth>
2934 int xres, yres, depth, temp;
2936 p = strsep(&spec, ";");
2939 xres = simple_strtoul(p, NULL, 10);
2940 p = strsep(&spec, ";");
2943 yres = simple_strtoul(p, NULL, 10);
2944 p = strsep(&spec, "");
2947 depth = simple_strtoul(p, NULL, 10);
2948 temp = get_video_mode("user0");
2951 atafb_predefined[default_par - 1].xres = xres;
2952 atafb_predefined[default_par - 1].yres = yres;
2953 atafb_predefined[default_par - 1].bits_per_pixel = depth;
2957 static int __init atafb_setup(char *options)
2962 if (!options || !*options)
2965 while ((this_opt = strsep(&options, ",")) != NULL) {
2968 if ((temp = get_video_mode(this_opt))) {
2970 mode_option = this_opt;
2971 } else if (!strcmp(this_opt, "inverse"))
2973 else if (!strncmp(this_opt, "hwscroll_", 9)) {
2974 hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
2981 else if (!strcmp(this_opt, "mv300")) {
2982 external_bitspercol = 8;
2983 external_card_type = IS_MV300;
2984 } else if (!strncmp(this_opt, "external:", 9))
2985 atafb_setup_ext(this_opt + 9);
2987 else if (!strncmp(this_opt, "internal:", 9))
2988 atafb_setup_int(this_opt + 9);
2990 else if (!strncmp(this_opt, "eclock:", 7)) {
2991 fext.f = simple_strtoul(this_opt + 7, NULL, 10);
2992 /* external pixelclock in kHz --> ps */
2993 fext.t = 1000000000 / fext.f;
2995 } else if (!strncmp(this_opt, "monitorcap:", 11))
2996 atafb_setup_mcap(this_opt + 11);
2998 else if (!strcmp(this_opt, "keep"))
3000 else if (!strncmp(this_opt, "R", 1))
3001 atafb_setup_user(this_opt + 1);
3006 static int __init atafb_probe(struct platform_device *pdev)
3008 int pad, detected_mode, error;
3009 unsigned int defmode = 0;
3010 unsigned long mem_req;
3011 char *option = NULL;
3013 if (fb_get_options("atafb", &option))
3015 atafb_setup(option);
3016 dev_dbg(&pdev->dev, "%s: start\n", __func__);
3020 if (external_addr) {
3021 dev_dbg(&pdev->dev, "initializing external hw\n");
3023 atafb_ops.fb_setcolreg = &ext_setcolreg;
3024 defmode = DEFMODE_EXT;
3029 if (ATARIHW_PRESENT(TT_SHIFTER)) {
3030 dev_dbg(&pdev->dev, "initializing TT hw\n");
3032 atafb_ops.fb_setcolreg = &tt_setcolreg;
3033 defmode = DEFMODE_TT;
3038 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
3039 dev_dbg(&pdev->dev, "initializing Falcon hw\n");
3040 fbhw = &falcon_switch;
3041 atafb_ops.fb_setcolreg = &falcon_setcolreg;
3042 error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 0,
3043 "framebuffer:modeswitch",
3044 falcon_vbl_switcher);
3047 defmode = DEFMODE_F30;
3052 if (ATARIHW_PRESENT(STND_SHIFTER) ||
3053 ATARIHW_PRESENT(EXTD_SHIFTER)) {
3054 dev_dbg(&pdev->dev, "initializing ST/E hw\n");
3056 atafb_ops.fb_setcolreg = &stste_setcolreg;
3057 defmode = DEFMODE_STE;
3061 atafb_ops.fb_setcolreg = &stste_setcolreg;
3062 dev_warn(&pdev->dev,
3063 "Cannot determine video hardware; defaulting to ST(e)\n");
3064 #else /* ATAFB_STE */
3065 /* no default driver included */
3066 /* Nobody will ever see this message :-) */
3067 panic("Cannot initialize video hardware");
3071 /* Multisync monitor capabilities */
3072 /* Atari-TOS defaults if no boot option present */
3073 if (fb_info.monspecs.hfmin == 0) {
3074 fb_info.monspecs.hfmin = 31000;
3075 fb_info.monspecs.hfmax = 32000;
3076 fb_info.monspecs.vfmin = 58;
3077 fb_info.monspecs.vfmax = 62;
3080 detected_mode = fbhw->detect();
3081 check_default_par(detected_mode);
3083 if (!external_addr) {
3084 #endif /* ATAFB_EXT */
3085 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
3086 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
3087 screen_base = atari_stram_alloc(mem_req, "atafb");
3089 panic("Cannot allocate screen memory");
3090 memset(screen_base, 0, mem_req);
3091 pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
3093 phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
3094 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
3096 if (CPU_IS_040_OR_060) {
3097 /* On a '040+, the cache mode of video RAM must be set to
3098 * write-through also for internal video hardware! */
3099 cache_push(atari_stram_to_phys(screen_base), screen_len);
3100 kernel_set_cachemode(screen_base, screen_len,
3101 IOMAP_WRITETHROUGH);
3103 dev_info(&pdev->dev, "phys_screen_base %lx screen_len %d\n",
3104 phys_screen_base, screen_len);
3107 /* Map the video memory (physical address given) to somewhere
3108 * in the kernel address space.
3110 external_screen_base = ioremap_wt(external_addr, external_len);
3111 if (external_vgaiobase)
3112 external_vgaiobase =
3113 (unsigned long)ioremap(external_vgaiobase, 0x10000);
3114 screen_base = external_screen_base;
3115 phys_screen_base = external_addr;
3116 screen_len = external_len & PAGE_MASK;
3117 memset (screen_base, 0, external_len);
3119 #endif /* ATAFB_EXT */
3121 // strcpy(fb_info.mode->name, "Atari Builtin ");
3122 fb_info.fbops = &atafb_ops;
3123 // try to set default (detected; requested) var
3124 do_fb_set_var(&atafb_predefined[default_par - 1], 1);
3125 // reads hw state into current par, which may not be sane yet
3126 ata_get_par(¤t_par);
3127 fb_info.par = ¤t_par;
3128 // tries to read from HW which may not be initialized yet
3129 // so set sane var first, then call atafb_set_par
3130 atafb_get_var(&fb_info.var, &fb_info);
3133 fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
3135 fb_info.flags = FBINFO_FLAG_DEFAULT;
3137 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
3138 NUM_TOTAL_MODES, &atafb_modedb[defmode],
3139 fb_info.var.bits_per_pixel)) {
3143 fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
3146 atafb_set_disp(&fb_info);
3148 fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
3151 dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
3152 fb_info.var.yres, fb_info.var.bits_per_pixel);
3153 if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
3154 (fb_info.var.yres != fb_info.var.yres_virtual))
3155 dev_info(&pdev->dev, " virtual %dx%d\n",
3156 fb_info.var.xres_virtual, fb_info.var.yres_virtual);
3158 if (register_framebuffer(&fb_info) < 0) {
3160 if (external_addr) {
3161 iounmap(external_screen_base);
3164 if (external_vgaiobase) {
3165 iounmap((void*)external_vgaiobase);
3166 external_vgaiobase = 0;
3172 fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
3175 /* TODO: This driver cannot be unloaded yet */
3179 static void atafb_shutdown(struct platform_device *pdev)
3181 /* Unblank before kexec */
3186 static struct platform_driver atafb_driver = {
3187 .shutdown = atafb_shutdown,
3193 static int __init atafb_init(void)
3195 struct platform_device *pdev;
3200 pdev = platform_device_register_simple("atafb", -1, NULL, 0);
3202 return PTR_ERR(pdev);
3204 return platform_driver_probe(&atafb_driver, atafb_probe);
3207 device_initcall(atafb_init);