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", 72, 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 = 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)
2213 switch (external_card_type) {
2217 OUTB(0x3c9, red & colmask);
2219 OUTB(0x3c9, green & colmask);
2221 OUTB(0x3c9, blue & colmask);
2226 OUTB((MV300_reg[regno] << 2) + 1, red);
2227 OUTB((MV300_reg[regno] << 2) + 1, green);
2228 OUTB((MV300_reg[regno] << 2) + 1, blue);
2236 static int ext_detect(void)
2238 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2239 struct atafb_par dummy_par;
2241 myvar->xres = external_xres;
2242 myvar->xres_virtual = external_xres_virtual;
2243 myvar->yres = external_yres;
2244 myvar->bits_per_pixel = external_depth;
2245 ext_encode_var(myvar, &dummy_par);
2249 #endif /* ATAFB_EXT */
2251 /* ------ This is the same for most hardware types -------- */
2253 static void set_screen_base(void *s_base)
2257 addr = atari_stram_to_phys(s_base);
2258 /* Setup Screen Memory */
2259 shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2260 shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2261 shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
2264 static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2266 struct atafb_par *par = info->par;
2268 if (!fbhw->set_screen_base ||
2269 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2271 var->xoffset = round_up(var->xoffset, 16);
2272 par->screen_base = screen_base +
2273 (var->yoffset * info->var.xres_virtual + var->xoffset)
2274 * info->var.bits_per_pixel / 8;
2275 fbhw->set_screen_base(par->screen_base);
2279 /* ------------ Interfaces to hardware functions ------------ */
2282 static struct fb_hwswitch tt_switch = {
2283 .detect = tt_detect,
2284 .encode_fix = tt_encode_fix,
2285 .decode_var = tt_decode_var,
2286 .encode_var = tt_encode_var,
2287 .get_par = tt_get_par,
2288 .set_par = tt_set_par,
2289 .set_screen_base = set_screen_base,
2290 .pan_display = pan_display,
2295 static struct fb_hwswitch falcon_switch = {
2296 .detect = falcon_detect,
2297 .encode_fix = falcon_encode_fix,
2298 .decode_var = falcon_decode_var,
2299 .encode_var = falcon_encode_var,
2300 .get_par = falcon_get_par,
2301 .set_par = falcon_set_par,
2302 .set_screen_base = set_screen_base,
2303 .blank = falcon_blank,
2304 .pan_display = falcon_pan_display,
2309 static struct fb_hwswitch st_switch = {
2310 .detect = stste_detect,
2311 .encode_fix = stste_encode_fix,
2312 .decode_var = stste_decode_var,
2313 .encode_var = stste_encode_var,
2314 .get_par = stste_get_par,
2315 .set_par = stste_set_par,
2316 .set_screen_base = stste_set_screen_base,
2317 .pan_display = pan_display
2322 static struct fb_hwswitch ext_switch = {
2323 .detect = ext_detect,
2324 .encode_fix = ext_encode_fix,
2325 .decode_var = ext_decode_var,
2326 .encode_var = ext_encode_var,
2327 .get_par = ext_get_par,
2328 .set_par = ext_set_par,
2332 static void ata_get_par(struct atafb_par *par)
2334 if (current_par_valid)
2340 static void ata_set_par(struct atafb_par *par)
2344 current_par_valid = 1;
2348 /* =========================================================== */
2349 /* ============== Hardware Independent Functions ============= */
2350 /* =========================================================== */
2352 /* used for hardware scrolling */
2354 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2357 struct atafb_par par;
2359 err = fbhw->decode_var(var, &par);
2362 activate = var->activate;
2363 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2365 fbhw->encode_var(var, &par);
2366 var->activate = activate;
2370 /* fbhw->encode_fix() must be called with fb_info->mm_lock held
2371 * if it is called after the register_framebuffer() - not a case here
2373 static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2375 struct atafb_par par;
2377 // Get fix directly (case con == -1 before)??
2378 err = fbhw->decode_var(&info->var, &par);
2381 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2382 err = fbhw->encode_fix(fix, &par);
2386 static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
2388 struct atafb_par par;
2391 fbhw->encode_var(var, &par);
2396 // No longer called by fbcon!
2397 // Still called by set_var internally
2399 static void atafb_set_disp(struct fb_info *info)
2401 atafb_get_var(&info->var, info);
2402 atafb_get_fix(&info->fix, info);
2404 /* Note: smem_start derives from phys_screen_base, not screen_base! */
2405 info->screen_base = (external_addr ? external_screen_base :
2406 atari_stram_to_virt(info->fix.smem_start));
2410 atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2412 if (!fbhw->pan_display)
2415 return fbhw->pan_display(var, info);
2419 * generic drawing routines; imageblit needs updating for image depth > 1
2422 #if BITS_PER_LONG == 32
2423 #define BYTES_PER_LONG 4
2424 #define SHIFT_PER_LONG 5
2425 #elif BITS_PER_LONG == 64
2426 #define BYTES_PER_LONG 8
2427 #define SHIFT_PER_LONG 6
2429 #define Please update me
2433 static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
2435 struct atafb_par *par = info->par;
2439 if (!rect->width || !rect->height)
2443 if (info->var.bits_per_pixel == 16) {
2444 cfb_fillrect(info, rect);
2450 * We could use hardware clipping but on many cards you get around
2451 * hardware clipping by writing to framebuffer directly.
2453 x2 = rect->dx + rect->width;
2454 y2 = rect->dy + rect->height;
2455 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2456 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2457 width = x2 - rect->dx;
2458 height = y2 - rect->dy;
2460 if (info->var.bits_per_pixel == 1)
2461 atafb_mfb_fillrect(info, par->next_line, rect->color,
2462 rect->dy, rect->dx, height, width);
2463 else if (info->var.bits_per_pixel == 2)
2464 atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
2465 rect->dy, rect->dx, height, width);
2466 else if (info->var.bits_per_pixel == 4)
2467 atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
2468 rect->dy, rect->dx, height, width);
2470 atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
2471 rect->dy, rect->dx, height, width);
2476 static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2478 struct atafb_par *par = info->par;
2480 u32 dx, dy, sx, sy, width, height;
2484 if (info->var.bits_per_pixel == 16) {
2485 cfb_copyarea(info, area);
2490 /* clip the destination */
2491 x2 = area->dx + area->width;
2492 y2 = area->dy + area->height;
2493 dx = area->dx > 0 ? area->dx : 0;
2494 dy = area->dy > 0 ? area->dy : 0;
2495 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2496 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2500 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2504 sx = area->sx + (dx - area->dx);
2505 sy = area->sy + (dy - area->dy);
2507 /* the source must be completely inside the virtual screen */
2508 if (sx + width > info->var.xres_virtual ||
2509 sy + height > info->var.yres_virtual)
2512 if (dy > sy || (dy == sy && dx > sx)) {
2518 if (info->var.bits_per_pixel == 1)
2519 atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2520 else if (info->var.bits_per_pixel == 2)
2521 atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2522 else if (info->var.bits_per_pixel == 4)
2523 atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2525 atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2530 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2532 struct atafb_par *par = info->par;
2537 u32 dx, dy, width, height, pitch;
2540 if (info->var.bits_per_pixel == 16) {
2541 cfb_imageblit(info, image);
2547 * We could use hardware clipping but on many cards you get around
2548 * hardware clipping by writing to framebuffer directly like we are
2551 x2 = image->dx + image->width;
2552 y2 = image->dy + image->height;
2555 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2556 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2560 if (image->depth == 1) {
2561 // used for font data
2562 dst = (unsigned long *)
2563 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2564 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2565 dst_idx += dy * par->next_line * 8 + dx;
2567 pitch = (image->width + 7) / 8;
2570 if (info->var.bits_per_pixel == 1)
2571 atafb_mfb_linefill(info, par->next_line,
2573 image->bg_color, image->fg_color);
2574 else if (info->var.bits_per_pixel == 2)
2575 atafb_iplan2p2_linefill(info, par->next_line,
2577 image->bg_color, image->fg_color);
2578 else if (info->var.bits_per_pixel == 4)
2579 atafb_iplan2p4_linefill(info, par->next_line,
2581 image->bg_color, image->fg_color);
2583 atafb_iplan2p8_linefill(info, par->next_line,
2585 image->bg_color, image->fg_color);
2590 c2p_iplan2(info->screen_base, image->data, dx, dy, width,
2591 height, par->next_line, image->width,
2592 info->var.bits_per_pixel);
2597 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2600 #ifdef FBCMD_GET_CURRENTPAR
2601 case FBCMD_GET_CURRENTPAR:
2602 if (copy_to_user((void *)arg, ¤t_par,
2603 sizeof(struct atafb_par)))
2607 #ifdef FBCMD_SET_CURRENTPAR
2608 case FBCMD_SET_CURRENTPAR:
2609 if (copy_from_user(¤t_par, (void *)arg,
2610 sizeof(struct atafb_par)))
2612 ata_set_par(¤t_par);
2619 /* (un)blank/poweroff
2626 static int atafb_blank(int blank, struct fb_info *info)
2628 unsigned short black[16];
2629 struct fb_cmap cmap;
2630 if (fbhw->blank && !fbhw->blank(blank))
2633 memset(black, 0, 16 * sizeof(unsigned short));
2640 fb_set_cmap(&cmap, info);
2644 do_install_cmap(info);
2650 * New fbcon interface ...
2653 /* check var by decoding var into hw par, rounding if necessary,
2654 * then encoding hw par back into new, validated var */
2655 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2658 struct atafb_par par;
2660 /* Validate wanted screen parameters */
2661 // if ((err = ata_decode_var(var, &par)))
2662 err = fbhw->decode_var(var, &par);
2666 /* Encode (possibly rounded) screen parameters */
2667 fbhw->encode_var(var, &par);
2671 /* actually set hw par by decoding var, then setting hardware from
2672 * hw par just decoded */
2673 static int atafb_set_par(struct fb_info *info)
2675 struct atafb_par *par = info->par;
2677 /* Decode wanted screen parameters */
2678 fbhw->decode_var(&info->var, par);
2679 mutex_lock(&info->mm_lock);
2680 fbhw->encode_fix(&info->fix, par);
2681 mutex_unlock(&info->mm_lock);
2683 /* Set new videomode */
2690 static struct fb_ops atafb_ops = {
2691 .owner = THIS_MODULE,
2692 .fb_check_var = atafb_check_var,
2693 .fb_set_par = atafb_set_par,
2694 .fb_blank = atafb_blank,
2695 .fb_pan_display = atafb_pan_display,
2696 .fb_fillrect = atafb_fillrect,
2697 .fb_copyarea = atafb_copyarea,
2698 .fb_imageblit = atafb_imageblit,
2699 .fb_ioctl = atafb_ioctl,
2702 static void check_default_par(int detected_mode)
2704 char default_name[10];
2706 struct fb_var_screeninfo var;
2707 unsigned long min_mem;
2709 /* First try the user supplied mode */
2711 var = atafb_predefined[default_par - 1];
2712 var.activate = FB_ACTIVATE_TEST;
2713 if (do_fb_set_var(&var, 1))
2714 default_par = 0; /* failed */
2716 /* Next is the autodetected one */
2718 var = atafb_predefined[detected_mode - 1]; /* autodetect */
2719 var.activate = FB_ACTIVATE_TEST;
2720 if (!do_fb_set_var(&var, 1))
2721 default_par = detected_mode;
2723 /* If that also failed, try some default modes... */
2725 /* try default1, default2... */
2726 for (i = 1; i < 10; i++) {
2727 sprintf(default_name,"default%d", i);
2728 default_par = get_video_mode(default_name);
2730 panic("can't set default video mode");
2731 var = atafb_predefined[default_par - 1];
2732 var.activate = FB_ACTIVATE_TEST;
2733 if (!do_fb_set_var(&var,1))
2737 min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
2738 if (default_mem_req < min_mem)
2739 default_mem_req = min_mem;
2743 static void __init atafb_setup_ext(char *spec)
2745 int xres, xres_virtual, yres, depth, planes;
2746 unsigned long addr, len;
2749 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2751 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2752 * [;<xres-virtual>]]]]]
2755 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2757 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2759 p = strsep(&spec, ";");
2762 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2766 p = strsep(&spec, ";");
2769 yres = simple_strtoul(p, NULL, 10);
2773 p = strsep(&spec, ";");
2776 depth = simple_strtoul(p, NULL, 10);
2777 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2778 depth != 16 && depth != 24)
2781 p = strsep(&spec, ";");
2785 planes = FB_TYPE_INTERLEAVED_PLANES;
2787 planes = FB_TYPE_PACKED_PIXELS;
2789 planes = FB_TYPE_PLANES;
2791 planes = -1; /* true color */
2795 p = strsep(&spec, ";");
2798 addr = simple_strtoul(p, NULL, 0);
2800 p = strsep(&spec, ";");
2802 len = xres * yres * depth / 8;
2804 len = simple_strtoul(p, NULL, 0);
2806 p = strsep(&spec, ";");
2808 external_vgaiobase = simple_strtoul(p, NULL, 0);
2810 p = strsep(&spec, ";");
2812 external_bitspercol = simple_strtoul(p, NULL, 0);
2813 if (external_bitspercol > 8)
2814 external_bitspercol = 8;
2815 else if (external_bitspercol < 1)
2816 external_bitspercol = 1;
2819 p = strsep(&spec, ";");
2821 if (!strcmp(p, "vga"))
2822 external_card_type = IS_VGA;
2823 if (!strcmp(p, "mv300"))
2824 external_card_type = IS_MV300;
2827 p = strsep(&spec, ";");
2829 xres_virtual = simple_strtoul(p, NULL, 10);
2830 if (xres_virtual < xres)
2831 xres_virtual = xres;
2832 if (xres_virtual * yres * depth / 8 > len)
2833 len = xres_virtual * yres * depth / 8;
2836 external_xres = xres;
2837 external_xres_virtual = xres_virtual;
2838 external_yres = yres;
2839 external_depth = depth;
2840 external_pmode = planes;
2841 external_addr = addr;
2844 if (external_card_type == IS_MV300) {
2845 switch (external_depth) {
2847 MV300_reg = MV300_reg_1bit;
2850 MV300_reg = MV300_reg_4bit;
2853 MV300_reg = MV300_reg_8bit;
2858 #endif /* ATAFB_EXT */
2860 static void __init atafb_setup_int(char *spec)
2862 /* Format to config extended internal video hardware like OverScan:
2863 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2865 * <xres>: x-resolution
2866 * <yres>: y-resolution
2867 * The following are only needed if you have an overscan which
2868 * needs a black border:
2869 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2870 * <yres_max>: max. number of lines your OverScan hardware would allow
2871 * <offset>: Offset from physical beginning to visible beginning
2872 * of screen in bytes
2877 if (!(p = strsep(&spec, ";")) || !*p)
2879 xres = simple_strtoul(p, NULL, 10);
2880 if (!(p = strsep(&spec, ";")) || !*p)
2883 tt_yres = st_yres = simple_strtoul(p, NULL, 10);
2884 if ((p = strsep(&spec, ";")) && *p)
2885 sttt_xres_virtual = simple_strtoul(p, NULL, 10);
2886 if ((p = strsep(&spec, ";")) && *p)
2887 sttt_yres_virtual = simple_strtoul(p, NULL, 0);
2888 if ((p = strsep(&spec, ";")) && *p)
2889 ovsc_offset = simple_strtoul(p, NULL, 0);
2891 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2896 static void __init atafb_setup_mcap(char *spec)
2899 int vmin, vmax, hmin, hmax;
2901 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2902 * <V*> vertical freq. in Hz
2903 * <H*> horizontal freq. in kHz
2905 if (!(p = strsep(&spec, ";")) || !*p)
2907 vmin = simple_strtoul(p, NULL, 10);
2910 if (!(p = strsep(&spec, ";")) || !*p)
2912 vmax = simple_strtoul(p, NULL, 10);
2913 if (vmax <= 0 || vmax <= vmin)
2915 if (!(p = strsep(&spec, ";")) || !*p)
2917 hmin = 1000 * simple_strtoul(p, NULL, 10);
2920 if (!(p = strsep(&spec, "")) || !*p)
2922 hmax = 1000 * simple_strtoul(p, NULL, 10);
2923 if (hmax <= 0 || hmax <= hmin)
2926 fb_info.monspecs.vfmin = vmin;
2927 fb_info.monspecs.vfmax = vmax;
2928 fb_info.monspecs.hfmin = hmin;
2929 fb_info.monspecs.hfmax = hmax;
2931 #endif /* ATAFB_FALCON */
2933 static void __init atafb_setup_user(char *spec)
2935 /* Format of user defined video mode is: <xres>;<yres>;<depth>
2938 int xres, yres, depth, temp;
2940 p = strsep(&spec, ";");
2943 xres = simple_strtoul(p, NULL, 10);
2944 p = strsep(&spec, ";");
2947 yres = simple_strtoul(p, NULL, 10);
2948 p = strsep(&spec, "");
2951 depth = simple_strtoul(p, NULL, 10);
2952 temp = get_video_mode("user0");
2955 atafb_predefined[default_par - 1].xres = xres;
2956 atafb_predefined[default_par - 1].yres = yres;
2957 atafb_predefined[default_par - 1].bits_per_pixel = depth;
2961 static int __init atafb_setup(char *options)
2966 if (!options || !*options)
2969 while ((this_opt = strsep(&options, ",")) != NULL) {
2972 if ((temp = get_video_mode(this_opt))) {
2974 mode_option = this_opt;
2975 } else if (!strcmp(this_opt, "inverse"))
2977 else if (!strncmp(this_opt, "hwscroll_", 9)) {
2978 hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
2985 else if (!strcmp(this_opt, "mv300")) {
2986 external_bitspercol = 8;
2987 external_card_type = IS_MV300;
2988 } else if (!strncmp(this_opt, "external:", 9))
2989 atafb_setup_ext(this_opt + 9);
2991 else if (!strncmp(this_opt, "internal:", 9))
2992 atafb_setup_int(this_opt + 9);
2994 else if (!strncmp(this_opt, "eclock:", 7)) {
2995 fext.f = simple_strtoul(this_opt + 7, NULL, 10);
2996 /* external pixelclock in kHz --> ps */
2997 fext.t = 1000000000 / fext.f;
2999 } else if (!strncmp(this_opt, "monitorcap:", 11))
3000 atafb_setup_mcap(this_opt + 11);
3002 else if (!strcmp(this_opt, "keep"))
3004 else if (!strncmp(this_opt, "R", 1))
3005 atafb_setup_user(this_opt + 1);
3010 static int __init atafb_probe(struct platform_device *pdev)
3012 int pad, detected_mode, error;
3013 unsigned int defmode = 0;
3014 unsigned long mem_req;
3015 char *option = NULL;
3017 if (fb_get_options("atafb", &option))
3019 atafb_setup(option);
3020 dev_dbg(&pdev->dev, "%s: start\n", __func__);
3024 if (external_addr) {
3025 dev_dbg(&pdev->dev, "initializing external hw\n");
3027 atafb_ops.fb_setcolreg = &ext_setcolreg;
3028 defmode = DEFMODE_EXT;
3033 if (ATARIHW_PRESENT(TT_SHIFTER)) {
3034 dev_dbg(&pdev->dev, "initializing TT hw\n");
3036 atafb_ops.fb_setcolreg = &tt_setcolreg;
3037 defmode = DEFMODE_TT;
3042 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
3043 dev_dbg(&pdev->dev, "initializing Falcon hw\n");
3044 fbhw = &falcon_switch;
3045 atafb_ops.fb_setcolreg = &falcon_setcolreg;
3046 error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 0,
3047 "framebuffer:modeswitch",
3048 falcon_vbl_switcher);
3051 defmode = DEFMODE_F30;
3056 if (ATARIHW_PRESENT(STND_SHIFTER) ||
3057 ATARIHW_PRESENT(EXTD_SHIFTER)) {
3058 dev_dbg(&pdev->dev, "initializing ST/E hw\n");
3060 atafb_ops.fb_setcolreg = &stste_setcolreg;
3061 defmode = DEFMODE_STE;
3065 atafb_ops.fb_setcolreg = &stste_setcolreg;
3066 dev_warn(&pdev->dev,
3067 "Cannot determine video hardware; defaulting to ST(e)\n");
3068 #else /* ATAFB_STE */
3069 /* no default driver included */
3070 /* Nobody will ever see this message :-) */
3071 panic("Cannot initialize video hardware");
3075 /* Multisync monitor capabilities */
3076 /* Atari-TOS defaults if no boot option present */
3077 if (fb_info.monspecs.hfmin == 0) {
3078 fb_info.monspecs.hfmin = 31000;
3079 fb_info.monspecs.hfmax = 32000;
3080 fb_info.monspecs.vfmin = 58;
3081 fb_info.monspecs.vfmax = 62;
3084 detected_mode = fbhw->detect();
3085 check_default_par(detected_mode);
3087 if (!external_addr) {
3088 #endif /* ATAFB_EXT */
3089 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
3090 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
3091 screen_base = atari_stram_alloc(mem_req, "atafb");
3093 panic("Cannot allocate screen memory");
3094 memset(screen_base, 0, mem_req);
3095 pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
3097 phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
3098 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
3100 if (CPU_IS_040_OR_060) {
3101 /* On a '040+, the cache mode of video RAM must be set to
3102 * write-through also for internal video hardware! */
3103 cache_push(atari_stram_to_phys(screen_base), screen_len);
3104 kernel_set_cachemode(screen_base, screen_len,
3105 IOMAP_WRITETHROUGH);
3107 dev_info(&pdev->dev, "phys_screen_base %lx screen_len %d\n",
3108 phys_screen_base, screen_len);
3111 /* Map the video memory (physical address given) to somewhere
3112 * in the kernel address space.
3114 external_screen_base = ioremap_wt(external_addr, external_len);
3115 if (external_vgaiobase)
3116 external_vgaiobase =
3117 (unsigned long)ioremap(external_vgaiobase, 0x10000);
3118 screen_base = external_screen_base;
3119 phys_screen_base = external_addr;
3120 screen_len = external_len & PAGE_MASK;
3121 memset (screen_base, 0, external_len);
3123 #endif /* ATAFB_EXT */
3125 // strcpy(fb_info.mode->name, "Atari Builtin ");
3126 fb_info.fbops = &atafb_ops;
3127 // try to set default (detected; requested) var
3128 do_fb_set_var(&atafb_predefined[default_par - 1], 1);
3129 // reads hw state into current par, which may not be sane yet
3130 ata_get_par(¤t_par);
3131 fb_info.par = ¤t_par;
3132 // tries to read from HW which may not be initialized yet
3133 // so set sane var first, then call atafb_set_par
3134 atafb_get_var(&fb_info.var, &fb_info);
3137 fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
3139 fb_info.flags = FBINFO_FLAG_DEFAULT;
3141 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
3142 NUM_TOTAL_MODES, &atafb_modedb[defmode],
3143 fb_info.var.bits_per_pixel)) {
3147 fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
3150 atafb_set_disp(&fb_info);
3152 fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
3155 dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
3156 fb_info.var.yres, fb_info.var.bits_per_pixel);
3157 if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
3158 (fb_info.var.yres != fb_info.var.yres_virtual))
3159 dev_info(&pdev->dev, " virtual %dx%d\n",
3160 fb_info.var.xres_virtual, fb_info.var.yres_virtual);
3162 if (register_framebuffer(&fb_info) < 0) {
3164 if (external_addr) {
3165 iounmap(external_screen_base);
3168 if (external_vgaiobase) {
3169 iounmap((void*)external_vgaiobase);
3170 external_vgaiobase = 0;
3176 fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
3179 /* TODO: This driver cannot be unloaded yet */
3183 static void atafb_shutdown(struct platform_device *pdev)
3185 /* Unblank before kexec */
3190 static struct platform_driver atafb_driver = {
3191 .shutdown = atafb_shutdown,
3197 static int __init atafb_init(void)
3199 struct platform_device *pdev;
3204 pdev = platform_device_register_simple("atafb", -1, NULL, 0);
3206 return PTR_ERR(pdev);
3208 return platform_driver_probe(&atafb_driver, atafb_probe);
3211 device_initcall(atafb_init);