2 * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
4 * Copyright (C) 1994 Martin Schaller & Roman Hodek
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
11 * - 03 Jan 95: Original version by Martin Schaller: The TT driver and
12 * all the device independent stuff
13 * - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
14 * and wrote the Falcon, ST(E), and External drivers
15 * based on the original TT driver.
16 * - 07 May 95: Martin: Added colormap operations for the external driver
17 * - 21 May 95: Martin: Added support for overscan
18 * Andreas: some bug fixes for this
19 * - Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
20 * Programmable Falcon video modes
21 * (thanks to Christian Cartus for documentation
22 * of VIDEL registers).
23 * - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
24 * on minor 24...31. "user0" may be set on commandline by
25 * "R<x>;<y>;<depth>". (Makes sense only on Falcon)
26 * Video mode switch on Falcon now done at next VBL interrupt
27 * to avoid the annoying right shift of the screen.
28 * - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
29 * The external-part is legacy, therefore hardware-specific
30 * functions like panning/hardwarescrolling/blanking isn't
32 * - 29 Sep 97: Juergen: added Romans suggestion for pan_display
33 * (var->xoffset was changed even if no set_screen_base avail.)
34 * - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
35 * we know how to set the colors
36 * ext_*palette: read from ext_colors (former MV300_colors)
37 * write to ext_colors and RAMDAC
40 * - For the Falcon it is not possible to set random video modes on
41 * SM124 and SC/TV, only the bootup resolution is supported.
50 #include <linux/kernel.h>
51 #include <linux/errno.h>
52 #include <linux/string.h>
54 #include <linux/delay.h>
55 #include <linux/init.h>
56 #include <linux/interrupt.h>
57 #include <linux/platform_device.h>
59 #include <asm/setup.h>
60 #include <linux/uaccess.h>
64 #include <asm/atarihw.h>
65 #include <asm/atariints.h>
66 #include <asm/atari_stram.h>
69 #include <asm/atarikb.h>
74 #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
75 #define SWITCH_SND6 0x40
76 #define SWITCH_SND7 0x80
77 #define SWITCH_NONE 0x00
79 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
82 static int default_par
; /* default resolution (0=none) */
84 static unsigned long default_mem_req
;
86 static int hwscroll
= -1;
88 static int use_hwscroll
= 1;
90 static int sttt_xres
= 640, st_yres
= 400, tt_yres
= 480;
91 static int sttt_xres_virtual
= 640, sttt_yres_virtual
= 400;
92 static int ovsc_offset
, ovsc_addlen
;
95 * Hardware parameters for current mode
98 static struct atafb_par
{
102 #if defined ATAFB_TT || defined ATAFB_STE
111 /* Here are fields for storing a video mode, as direct
112 * parameters for the hardware.
122 short hht
, hbb
, hbe
, hdb
, hde
, hss
;
123 short vft
, vbb
, vbe
, vdb
, vde
, vss
;
124 /* auxiliary information */
128 u32 pseudo_palette
[16];
131 /* Nothing needed for external mode */
135 /* Don't calculate an own resolution, and thus don't change the one found when
136 * booting (currently used for the Falcon to keep settings for internal video
137 * hardware extensions (e.g. ScreenBlaster) */
138 static int DontCalcRes
= 0;
141 #define HHT hw.falcon.hht
142 #define HBB hw.falcon.hbb
143 #define HBE hw.falcon.hbe
144 #define HDB hw.falcon.hdb
145 #define HDE hw.falcon.hde
146 #define HSS hw.falcon.hss
147 #define VFT hw.falcon.vft
148 #define VBB hw.falcon.vbb
149 #define VBE hw.falcon.vbe
150 #define VDB hw.falcon.vdb
151 #define VDE hw.falcon.vde
152 #define VSS hw.falcon.vss
153 #define VCO_CLOCK25 0x04
154 #define VCO_CSYPOS 0x10
155 #define VCO_VSYPOS 0x20
156 #define VCO_HSYPOS 0x40
157 #define VCO_SHORTOFFS 0x100
158 #define VMO_DOUBLE 0x01
159 #define VMO_INTER 0x02
160 #define VMO_PREMASK 0x0c
163 static struct fb_info fb_info
= {
166 .visual
= FB_VISUAL_PSEUDOCOLOR
,
167 .accel
= FB_ACCEL_NONE
,
171 static void *screen_base
; /* base address of screen */
172 static unsigned long phys_screen_base
; /* (only for Overscan) */
174 static int screen_len
;
176 static int current_par_valid
;
178 static int mono_moni
;
183 /* external video handling */
184 static unsigned int external_xres
;
185 static unsigned int external_xres_virtual
;
186 static unsigned int external_yres
;
189 * not needed - atafb will never support panning/hardwarescroll with external
190 * static unsigned int external_yres_virtual;
192 static unsigned int external_depth
;
193 static int external_pmode
;
194 static void *external_screen_base
;
195 static unsigned long external_addr
;
196 static unsigned long external_len
;
197 static unsigned long external_vgaiobase
;
198 static unsigned int external_bitspercol
= 6;
201 * JOE <joe@amber.dinoco.de>:
202 * added card type for external driver, is only needed for
205 enum cardtype
{ IS_VGA
, IS_MV300
};
206 static enum cardtype external_card_type
= IS_VGA
;
209 * The MV300 mixes the color registers. So we need an array of munged
210 * indices in order to access the correct reg.
212 static int MV300_reg_1bit
[2] = {
215 static int MV300_reg_4bit
[16] = {
216 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
218 static int MV300_reg_8bit
[256] = {
219 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
220 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
221 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
222 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
223 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
224 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
225 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
226 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
227 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
228 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
229 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
230 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
231 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
232 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
233 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
234 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
237 static int *MV300_reg
= MV300_reg_8bit
;
238 #endif /* ATAFB_EXT */
245 * * open/release and usage marking
246 * struct module *owner;
247 * int (*fb_open)(struct fb_info *info, int user);
248 * int (*fb_release)(struct fb_info *info, int user);
250 * * For framebuffers with strange non linear layouts or that do not
251 * * work with normal memory mapped access
252 * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
253 * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
255 * * checks var and eventually tweaks it to something supported,
256 * * DOES NOT MODIFY PAR *
257 * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
259 * * set the video mode according to info->var *
260 * int (*fb_set_par)(struct fb_info *info);
262 * * set color register *
263 * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
264 * unsigned int blue, unsigned int transp, struct fb_info *info);
266 * * set color registers in batch *
267 * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
270 * int (*fb_blank)(int blank, struct fb_info *info);
273 * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
275 * *** The meat of the drawing engine ***
276 * * Draws a rectangle *
277 * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
278 * * Copy data from area to another *
279 * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
280 * * Draws a image to the display *
281 * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
284 * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
286 * * wait for blit idle, optional *
287 * int (*fb_sync)(struct fb_info *info);
289 * * perform fb specific ioctl (optional) *
290 * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
291 * unsigned long arg);
293 * * Handle 32bit compat ioctl (optional) *
294 * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
295 * unsigned long arg);
297 * * perform fb specific mmap *
298 * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
303 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
306 * int (*detect)(void)
307 * This function should detect the current video mode settings and
308 * store them in atafb_predefined[0] for later reference by the
309 * user. Return the index+1 of an equivalent predefined mode or 0
310 * if there is no such.
312 * int (*encode_fix)(struct fb_fix_screeninfo *fix,
313 * struct atafb_par *par)
314 * This function should fill in the 'fix' structure based on the
315 * values in the 'par' structure.
316 * !!! Obsolete, perhaps !!!
318 * int (*decode_var)(struct fb_var_screeninfo *var,
319 * struct atafb_par *par)
320 * Get the video params out of 'var'. If a value doesn't fit, round
321 * it up, if it's too big, return EINVAL.
322 * Round up in the following order: bits_per_pixel, xres, yres,
323 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
324 * horizontal timing, vertical timing.
326 * int (*encode_var)(struct fb_var_screeninfo *var,
327 * struct atafb_par *par);
328 * Fill the 'var' structure based on the values in 'par' and maybe
329 * other values read out of the hardware.
331 * void (*get_par)(struct atafb_par *par)
332 * Fill the hardware's 'par' structure.
333 * !!! Used only by detect() !!!
335 * void (*set_par)(struct atafb_par *par)
336 * Set the hardware according to 'par'.
338 * void (*set_screen_base)(void *s_base)
339 * Set the base address of the displayed frame buffer. Only called
340 * if yres_virtual > yres or xres_virtual > xres.
342 * int (*blank)(int blank_mode)
343 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
344 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
345 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
346 * doesn't support it. Implements VESA suspend and powerdown modes on
347 * hardware that supports disabling hsync/vsync:
348 * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
351 static struct fb_hwswitch
{
353 int (*encode_fix
)(struct fb_fix_screeninfo
*fix
,
354 struct atafb_par
*par
);
355 int (*decode_var
)(struct fb_var_screeninfo
*var
,
356 struct atafb_par
*par
);
357 int (*encode_var
)(struct fb_var_screeninfo
*var
,
358 struct atafb_par
*par
);
359 void (*get_par
)(struct atafb_par
*par
);
360 void (*set_par
)(struct atafb_par
*par
);
361 void (*set_screen_base
)(void *s_base
);
362 int (*blank
)(int blank_mode
);
363 int (*pan_display
)(struct fb_var_screeninfo
*var
,
364 struct fb_info
*info
);
367 static char *autodetect_names
[] = { "autodetect", NULL
};
368 static char *stlow_names
[] = { "stlow", NULL
};
369 static char *stmid_names
[] = { "stmid", "default5", NULL
};
370 static char *sthigh_names
[] = { "sthigh", "default4", NULL
};
371 static char *ttlow_names
[] = { "ttlow", NULL
};
372 static char *ttmid_names
[] = { "ttmid", "default1", NULL
};
373 static char *tthigh_names
[] = { "tthigh", "default2", NULL
};
374 static char *vga2_names
[] = { "vga2", NULL
};
375 static char *vga4_names
[] = { "vga4", NULL
};
376 static char *vga16_names
[] = { "vga16", "default3", NULL
};
377 static char *vga256_names
[] = { "vga256", NULL
};
378 static char *falh2_names
[] = { "falh2", NULL
};
379 static char *falh16_names
[] = { "falh16", NULL
};
381 static char **fb_var_names
[] = {
398 static struct fb_var_screeninfo atafb_predefined
[] = {
400 * yres_virtual == 0 means use hw-scrolling if possible, else yres
403 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
404 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
405 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
407 320, 200, 320, 0, 0, 0, 4, 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, 200, 640, 0, 0, 0, 2, 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 640, 400, 640, 0, 0, 0, 1, 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 320, 480, 320, 0, 0, 0, 8, 0,
420 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
421 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
423 640, 480, 640, 0, 0, 0, 4, 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 1280, 960, 1280, 0, 0, 0, 1, 0,
428 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
429 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
431 640, 480, 640, 0, 0, 0, 1, 0,
432 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
433 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
435 640, 480, 640, 0, 0, 0, 2, 0,
436 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
437 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
439 640, 480, 640, 0, 0, 0, 4, 0,
440 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
441 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
443 640, 480, 640, 0, 0, 0, 8, 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, 1, 0,
448 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
449 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
451 896, 608, 896, 0, 0, 0, 4, 0,
452 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
453 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
456 static int num_atafb_predefined
= ARRAY_SIZE(atafb_predefined
);
458 static struct fb_videomode atafb_modedb
[] __initdata
= {
462 * If you change these, make sure to update DEFMODE_* as well!
470 /* 320x200, 15 kHz, 60 Hz (ST low) */
471 "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
472 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
474 /* 640x200, 15 kHz, 60 Hz (ST medium) */
475 "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
476 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
478 /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
479 "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
480 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
482 /* 320x480, 15 kHz, 60 Hz (TT low) */
483 "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
484 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
486 /* 640x480, 29 kHz, 57 Hz (TT medium) */
487 "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
488 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
490 /* 1280x960, 29 kHz, 60 Hz (TT high) */
491 "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
492 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
500 /* 640x480, 31 kHz, 60 Hz (VGA) */
501 "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
502 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
504 /* 640x400, 31 kHz, 70 Hz (VGA) */
505 "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
506 FB_SYNC_VERT_HIGH_ACT
| FB_SYNC_COMP_HIGH_ACT
, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
510 * Falcon HiRes Video Modes
514 /* 896x608, 31 kHz, 60 Hz (Falcon High) */
515 "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
516 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
520 #define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb)
522 static char *mode_option __initdata
= NULL
;
526 #define DEFMODE_TT 5 /* "tt-high" for TT */
527 #define DEFMODE_F30 7 /* "vga70" for Falcon */
528 #define DEFMODE_STE 2 /* "st-high" for ST/E */
529 #define DEFMODE_EXT 6 /* "vga" for external */
532 static int get_video_mode(char *vname
)
538 name_list
= fb_var_names
;
539 for (i
= 0; i
< num_atafb_predefined
; i
++) {
544 if (!strcmp(vname
, *name
))
554 /* ------------------- TT specific functions ---------------------- */
558 static int tt_encode_fix(struct fb_fix_screeninfo
*fix
, struct atafb_par
*par
)
562 strcpy(fix
->id
, "Atari Builtin");
563 fix
->smem_start
= phys_screen_base
;
564 fix
->smem_len
= screen_len
;
565 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
567 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
568 mode
= par
->hw
.tt
.mode
& TT_SHIFTER_MODEMASK
;
569 if (mode
== TT_SHIFTER_TTHIGH
|| mode
== TT_SHIFTER_STHIGH
) {
570 fix
->type
= FB_TYPE_PACKED_PIXELS
;
572 if (mode
== TT_SHIFTER_TTHIGH
)
573 fix
->visual
= FB_VISUAL_MONO01
;
578 fix
->line_length
= par
->next_line
;
579 fix
->accel
= FB_ACCEL_ATARIBLITT
;
583 static int tt_decode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
585 int xres
= var
->xres
;
586 int yres
= var
->yres
;
587 int bpp
= var
->bits_per_pixel
;
589 int yres_virtual
= var
->yres_virtual
;
592 if (bpp
> 1 || xres
> sttt_xres
* 2 || yres
> tt_yres
* 2)
594 par
->hw
.tt
.mode
= TT_SHIFTER_TTHIGH
;
595 xres
= sttt_xres
* 2;
599 if (bpp
> 8 || xres
> sttt_xres
|| yres
> tt_yres
)
602 if (xres
> sttt_xres
/ 2 || yres
> tt_yres
)
604 par
->hw
.tt
.mode
= TT_SHIFTER_TTLOW
;
605 xres
= sttt_xres
/ 2;
608 } else if (bpp
> 2) {
609 if (xres
> sttt_xres
|| yres
> tt_yres
)
611 if (xres
> sttt_xres
/ 2 || yres
> st_yres
/ 2) {
612 par
->hw
.tt
.mode
= TT_SHIFTER_TTMID
;
617 par
->hw
.tt
.mode
= TT_SHIFTER_STLOW
;
618 xres
= sttt_xres
/ 2;
622 } else if (bpp
> 1) {
623 if (xres
> sttt_xres
|| yres
> st_yres
/ 2)
625 par
->hw
.tt
.mode
= TT_SHIFTER_STMID
;
629 } else if (var
->xres
> sttt_xres
|| var
->yres
> st_yres
) {
632 par
->hw
.tt
.mode
= TT_SHIFTER_STHIGH
;
638 if (yres_virtual
<= 0)
640 else if (yres_virtual
< yres
)
642 if (var
->sync
& FB_SYNC_EXT
)
646 linelen
= xres
* bpp
/ 8;
647 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
649 if (yres
* linelen
> screen_len
&& screen_len
)
651 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
653 par
->yres_virtual
= yres_virtual
;
654 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
655 par
->next_line
= linelen
;
659 static int tt_encode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
662 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
665 var
->red
.msb_right
= 0;
668 var
->pixclock
= 31041;
669 var
->left_margin
= 120; /* these may be incorrect */
670 var
->right_margin
= 100;
671 var
->upper_margin
= 8;
672 var
->lower_margin
= 16;
673 var
->hsync_len
= 140;
679 if (par
->hw
.tt
.sync
& 1)
682 var
->sync
= FB_SYNC_EXT
;
684 switch (par
->hw
.tt
.mode
& TT_SHIFTER_MODEMASK
) {
685 case TT_SHIFTER_STLOW
:
686 var
->xres
= sttt_xres
/ 2;
687 var
->xres_virtual
= sttt_xres_virtual
/ 2;
688 var
->yres
= st_yres
/ 2;
689 var
->bits_per_pixel
= 4;
691 case TT_SHIFTER_STMID
:
692 var
->xres
= sttt_xres
;
693 var
->xres_virtual
= sttt_xres_virtual
;
694 var
->yres
= st_yres
/ 2;
695 var
->bits_per_pixel
= 2;
697 case TT_SHIFTER_STHIGH
:
698 var
->xres
= sttt_xres
;
699 var
->xres_virtual
= sttt_xres_virtual
;
701 var
->bits_per_pixel
= 1;
703 case TT_SHIFTER_TTLOW
:
704 var
->xres
= sttt_xres
/ 2;
705 var
->xres_virtual
= sttt_xres_virtual
/ 2;
707 var
->bits_per_pixel
= 8;
709 case TT_SHIFTER_TTMID
:
710 var
->xres
= sttt_xres
;
711 var
->xres_virtual
= sttt_xres_virtual
;
713 var
->bits_per_pixel
= 4;
715 case TT_SHIFTER_TTHIGH
:
717 var
->xres
= sttt_xres
* 2;
718 var
->xres_virtual
= sttt_xres_virtual
* 2;
719 var
->yres
= tt_yres
* 2;
720 var
->bits_per_pixel
= 1;
723 var
->blue
= var
->green
= var
->red
;
724 var
->transp
.offset
= 0;
725 var
->transp
.length
= 0;
726 var
->transp
.msb_right
= 0;
727 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
729 var
->yres_virtual
= var
->yres
;
730 else if (screen_len
) {
731 if (par
->yres_virtual
)
732 var
->yres_virtual
= par
->yres_virtual
;
734 /* yres_virtual == 0 means use maximum */
735 var
->yres_virtual
= screen_len
/ linelen
;
738 var
->yres_virtual
= 2 * var
->yres
;
740 var
->yres_virtual
= var
->yres
+ hwscroll
* 16;
744 var
->yoffset
= (par
->screen_base
- screen_base
) / linelen
;
749 var
->vmode
= FB_VMODE_NONINTERLACED
;
753 static void tt_get_par(struct atafb_par
*par
)
756 par
->hw
.tt
.mode
= shifter_tt
.tt_shiftmode
;
757 par
->hw
.tt
.sync
= shifter_st
.syncmode
;
758 addr
= ((shifter_st
.bas_hi
& 0xff) << 16) |
759 ((shifter_st
.bas_md
& 0xff) << 8) |
760 ((shifter_st
.bas_lo
& 0xff));
761 par
->screen_base
= atari_stram_to_virt(addr
);
764 static void tt_set_par(struct atafb_par
*par
)
766 shifter_tt
.tt_shiftmode
= par
->hw
.tt
.mode
;
767 shifter_st
.syncmode
= par
->hw
.tt
.sync
;
768 /* only set screen_base if really necessary */
769 if (current_par
.screen_base
!= par
->screen_base
)
770 fbhw
->set_screen_base(par
->screen_base
);
773 static int tt_setcolreg(unsigned int regno
, unsigned int red
,
774 unsigned int green
, unsigned int blue
,
775 unsigned int transp
, struct fb_info
*info
)
777 if ((shifter_tt
.tt_shiftmode
& TT_SHIFTER_MODEMASK
) == TT_SHIFTER_STHIGH
)
781 tt_palette
[regno
] = (((red
>> 12) << 8) | ((green
>> 12) << 4) |
783 if ((shifter_tt
.tt_shiftmode
& TT_SHIFTER_MODEMASK
) ==
784 TT_SHIFTER_STHIGH
&& regno
== 254)
789 static int tt_detect(void)
791 struct atafb_par par
;
793 /* Determine the connected monitor: The DMA sound must be
794 * disabled before reading the MFP GPIP, because the Sound
795 * Done Signal and the Monochrome Detect are XORed together!
797 * Even on a TT, we should look if there is a DMA sound. It was
798 * announced that the Eagle is TT compatible, but only the PCM is
801 if (ATARIHW_PRESENT(PCM_8BIT
)) {
802 tt_dmasnd
.ctrl
= DMASND_CTRL_OFF
;
803 udelay(20); /* wait a while for things to settle down */
805 mono_moni
= (st_mfp
.par_dt_reg
& 0x80) == 0;
808 tt_encode_var(&atafb_predefined
[0], &par
);
813 #endif /* ATAFB_TT */
815 /* ------------------- Falcon specific functions ---------------------- */
819 static int mon_type
; /* Falcon connected monitor */
820 static int f030_bus_width
; /* Falcon ram bus width (for vid_control) */
826 static struct pixel_clock
{
827 unsigned long f
; /* f/[Hz] */
828 unsigned long t
; /* t/[ps] (=1/f) */
829 int right
, hsync
, left
; /* standard timing in clock cycles, not pixel */
830 /* hsync initialized in falcon_detect() */
831 int sync_mask
; /* or-mask for hw.falcon.sync to set this clock */
832 int control_mask
; /* ditto, for hw.falcon.vid_control */
834 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
836 32000000, 31250, 18, 0, 42, 0x0, 0
838 0, 0, 18, 0, 42, 0x1, 0
841 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
842 static int vdl_prescale
[4][3] = {
843 { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
846 /* Default hsync timing [mon_type] in picoseconds */
847 static long h_syncs
[4] = { 3000000, 4875000, 4000000, 4875000 };
849 static inline int hxx_prescale(struct falcon_hw
*hw
)
851 return hw
->ste_mode
? 16
852 : vdl_prescale
[mon_type
][hw
->vid_mode
>> 2 & 0x3];
855 static int falcon_encode_fix(struct fb_fix_screeninfo
*fix
,
856 struct atafb_par
*par
)
858 strcpy(fix
->id
, "Atari Builtin");
859 fix
->smem_start
= phys_screen_base
;
860 fix
->smem_len
= screen_len
;
861 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
863 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
867 if (par
->hw
.falcon
.mono
) {
868 fix
->type
= FB_TYPE_PACKED_PIXELS
;
870 /* no smooth scrolling with longword aligned video mem */
872 } else if (par
->hw
.falcon
.f_shift
& 0x100) {
873 fix
->type
= FB_TYPE_PACKED_PIXELS
;
875 /* Is this ok or should it be DIRECTCOLOR? */
876 fix
->visual
= FB_VISUAL_TRUECOLOR
;
879 fix
->line_length
= par
->next_line
;
880 fix
->accel
= FB_ACCEL_ATARIBLITT
;
884 static int falcon_decode_var(struct fb_var_screeninfo
*var
,
885 struct atafb_par
*par
)
887 int bpp
= var
->bits_per_pixel
;
888 int xres
= var
->xres
;
889 int yres
= var
->yres
;
890 int xres_virtual
= var
->xres_virtual
;
891 int yres_virtual
= var
->yres_virtual
;
892 int left_margin
, right_margin
, hsync_len
;
893 int upper_margin
, lower_margin
, vsync_len
;
895 int interlace
= 0, doubleline
= 0;
896 struct pixel_clock
*pclock
;
897 int plen
; /* width of pixel in clock cycles */
902 int hdb_off
, hde_off
, base_off
;
903 int gstart
, gend1
, gend2
, align
;
906 Get the video params out of 'var'. If a value doesn't fit, round
907 it up, if it's too big, return EINVAL.
908 Round up in the following order: bits_per_pixel, xres, yres,
909 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
910 horizontal timing, vertical timing.
912 There is a maximum of screen resolution determined by pixelclock
913 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
914 In interlace mode this is " * " *vfmin <= pixelclock.
915 Additional constraints: hfreq.
916 Frequency range for multisync monitors is given via command line.
917 For TV and SM124 both frequencies are fixed.
919 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
920 Y % 16 == 0 to fit 8x16 font
923 Currently interlace and doubleline mode in var are ignored.
924 On SM124 and TV only the standard resolutions can be used.
927 /* Reject uninitialized mode */
928 if (!xres
|| !yres
|| !bpp
)
931 if (mon_type
== F_MON_SM
&& bpp
!= 1)
936 par
->hw
.falcon
.f_shift
= 0x400;
937 par
->hw
.falcon
.st_shift
= 0x200;
938 } else if (bpp
<= 2) {
940 par
->hw
.falcon
.f_shift
= 0x000;
941 par
->hw
.falcon
.st_shift
= 0x100;
942 } else if (bpp
<= 4) {
944 par
->hw
.falcon
.f_shift
= 0x000;
945 par
->hw
.falcon
.st_shift
= 0x000;
946 } else if (bpp
<= 8) {
948 par
->hw
.falcon
.f_shift
= 0x010;
949 } else if (bpp
<= 16) {
950 bpp
= 16; /* packed pixel mode */
951 par
->hw
.falcon
.f_shift
= 0x100; /* hicolor, no overlay */
954 par
->hw
.falcon
.bpp
= bpp
;
956 if (mon_type
== F_MON_SM
|| DontCalcRes
) {
957 /* Skip all calculations. VGA/TV/SC1224 only supported. */
958 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
960 if (bpp
> myvar
->bits_per_pixel
||
961 var
->xres
> myvar
->xres
||
962 var
->yres
> myvar
->yres
)
964 fbhw
->get_par(par
); /* Current par will be new par */
965 goto set_screen_base
; /* Don't forget this */
968 /* Only some fixed resolutions < 640x400 */
971 else if (xres
<= 640 && bpp
!= 16)
975 else if (yres
<= 240)
977 else if (yres
<= 400)
980 /* 2 planes must use STE compatibility mode */
981 par
->hw
.falcon
.ste_mode
= bpp
== 2;
982 par
->hw
.falcon
.mono
= bpp
== 1;
984 /* Total and visible scanline length must be a multiple of one longword,
985 * this and the console fontwidth yields the alignment for xres and
987 * TODO: this way "odd" fontheights are not supported
989 * Special case in STE mode: blank and graphic positions don't align,
990 * avoid trash at right margin
992 if (par
->hw
.falcon
.ste_mode
)
993 xres
= (xres
+ 63) & ~63;
995 xres
= (xres
+ 31) & ~31;
997 xres
= (xres
+ 15) & ~15;
999 yres
= (yres
+ 15) & ~15;
1001 yres
= (yres
+ 7) & ~7;
1003 if (xres_virtual
< xres
)
1004 xres_virtual
= xres
;
1006 xres_virtual
= (xres_virtual
+ 31) & ~31;
1008 xres_virtual
= (xres_virtual
+ 15) & ~15;
1010 if (yres_virtual
<= 0)
1012 else if (yres_virtual
< yres
)
1013 yres_virtual
= yres
;
1015 /* backward bug-compatibility */
1016 if (var
->pixclock
> 1)
1019 par
->hw
.falcon
.line_width
= bpp
* xres
/ 16;
1020 par
->hw
.falcon
.line_offset
= bpp
* (xres_virtual
- xres
) / 16;
1022 /* single or double pixel width */
1023 xstretch
= (xres
< 640) ? 2 : 1;
1025 #if 0 /* SM124 supports only 640x400, this is rejected above */
1026 if (mon_type
== F_MON_SM
) {
1027 if (xres
!= 640 && yres
!= 400)
1031 /* SM124-mode is special */
1032 par
->hw
.falcon
.ste_mode
= 1;
1033 par
->hw
.falcon
.f_shift
= 0x000;
1034 par
->hw
.falcon
.st_shift
= 0x200;
1035 left_margin
= hsync_len
= 128 / plen
;
1037 /* TODO set all margins */
1040 if (mon_type
== F_MON_SC
|| mon_type
== F_MON_TV
) {
1041 plen
= 2 * xstretch
;
1042 if (var
->pixclock
> f32
.t
* plen
)
1047 if (var
->pixclock
== 0) {
1048 /* set some minimal margins which center the screen */
1051 hsync_len
= pclock
->hsync
/ plen
;
1054 vsync_len
= interlace
? 3 : 4;
1056 left_margin
= var
->left_margin
;
1057 right_margin
= var
->right_margin
;
1058 hsync_len
= var
->hsync_len
;
1059 upper_margin
= var
->upper_margin
;
1060 lower_margin
= var
->lower_margin
;
1061 vsync_len
= var
->vsync_len
;
1062 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1063 upper_margin
= (upper_margin
+ 1) / 2;
1064 lower_margin
= (lower_margin
+ 1) / 2;
1065 vsync_len
= (vsync_len
+ 1) / 2;
1066 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1072 } else { /* F_MON_VGA */
1074 xstretch
= 2; /* Double pixel width only for hicolor */
1075 /* Default values are used for vert./hor. timing if no pixelclock given. */
1076 if (var
->pixclock
== 0) {
1079 /* Choose master pixelclock depending on hor. timing */
1080 plen
= 1 * xstretch
;
1081 if ((plen
* xres
+ f25
.right
+ f25
.hsync
+ f25
.left
) *
1082 fb_info
.monspecs
.hfmin
< f25
.f
)
1084 else if ((plen
* xres
+ f32
.right
+ f32
.hsync
+
1085 f32
.left
) * fb_info
.monspecs
.hfmin
< f32
.f
)
1087 else if ((plen
* xres
+ fext
.right
+ fext
.hsync
+
1088 fext
.left
) * fb_info
.monspecs
.hfmin
< fext
.f
&&
1094 left_margin
= pclock
->left
/ plen
;
1095 right_margin
= pclock
->right
/ plen
;
1096 hsync_len
= pclock
->hsync
/ plen
;
1097 linesize
= left_margin
+ xres
+ right_margin
+ hsync_len
;
1102 /* Choose largest pixelclock <= wanted clock */
1104 unsigned long pcl
= ULONG_MAX
;
1106 for (i
= 1; i
<= 4; i
*= 2) {
1107 if (f25
.t
* i
>= var
->pixclock
&&
1112 if (f32
.t
* i
>= var
->pixclock
&&
1117 if (fext
.t
&& fext
.t
* i
>= var
->pixclock
&&
1125 plen
= pcl
/ pclock
->t
;
1127 left_margin
= var
->left_margin
;
1128 right_margin
= var
->right_margin
;
1129 hsync_len
= var
->hsync_len
;
1130 upper_margin
= var
->upper_margin
;
1131 lower_margin
= var
->lower_margin
;
1132 vsync_len
= var
->vsync_len
;
1133 /* Internal unit is [single lines per (half-)frame] */
1134 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1135 /* # lines in half frame */
1136 /* External unit is [lines per full frame] */
1137 upper_margin
= (upper_margin
+ 1) / 2;
1138 lower_margin
= (lower_margin
+ 1) / 2;
1139 vsync_len
= (vsync_len
+ 1) / 2;
1140 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1141 /* External unit is [double lines per frame] */
1147 if (pclock
== &fext
)
1148 longoffset
= 1; /* VIDEL doesn't synchronize on short offset */
1150 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1151 /* this is definitely wrong if bus clock != 32MHz */
1152 if (pclock
->f
/ plen
/ 8 * bpp
> 32000000L)
1158 /* include sync lengths in right/lower margin for all calculations */
1159 right_margin
+= hsync_len
;
1160 lower_margin
+= vsync_len
;
1162 /* ! In all calculations of margins we use # of lines in half frame
1163 * (which is a full frame in non-interlace mode), so we can switch
1164 * between interlace and non-interlace without messing around
1168 /* Set base_offset 128 and video bus width */
1169 par
->hw
.falcon
.vid_control
= mon_type
| f030_bus_width
;
1171 par
->hw
.falcon
.vid_control
|= VCO_SHORTOFFS
; /* base_offset 64 */
1172 if (var
->sync
& FB_SYNC_HOR_HIGH_ACT
)
1173 par
->hw
.falcon
.vid_control
|= VCO_HSYPOS
;
1174 if (var
->sync
& FB_SYNC_VERT_HIGH_ACT
)
1175 par
->hw
.falcon
.vid_control
|= VCO_VSYPOS
;
1177 par
->hw
.falcon
.vid_control
|= pclock
->control_mask
;
1178 /* External or internal clock */
1179 par
->hw
.falcon
.sync
= pclock
->sync_mask
| 0x2;
1180 /* Pixellength and prescale */
1181 par
->hw
.falcon
.vid_mode
= (2 / plen
) << 2;
1183 par
->hw
.falcon
.vid_mode
|= VMO_DOUBLE
;
1185 par
->hw
.falcon
.vid_mode
|= VMO_INTER
;
1187 /*********************
1188 * Horizontal timing: unit = [master clock cycles]
1189 * unit of hxx-registers: [master clock cycles * prescale]
1190 * Hxx-registers are 9 bit wide
1192 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1194 * graphic output = hdb & 0x200 ?
1195 * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1196 * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1197 * (this must be a multiple of plen*128/bpp, on VGA pixels
1198 * to the right may be cut off with a bigger right margin)
1200 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1201 * (hdb - hht - 2) * prescale + hdboff :
1202 * hdb * prescale + hdboff
1204 * end of graphics relative to start of 1st halfline =
1205 * (hde + hht + 2) * prescale + hdeoff
1206 *********************/
1207 /* Calculate VIDEL registers */
1209 prescale
= hxx_prescale(&par
->hw
.falcon
);
1210 base_off
= par
->hw
.falcon
.vid_control
& VCO_SHORTOFFS
? 64 : 128;
1212 /* Offsets depend on video mode */
1213 /* Offsets are in clock cycles, divide by prescale to
1214 * calculate hd[be]-registers
1216 if (par
->hw
.falcon
.f_shift
& 0x100) {
1219 hdb_off
= (base_off
+ 16 * plen
) + prescale
;
1222 hde_off
= ((128 / bpp
+ 2) * plen
);
1223 if (par
->hw
.falcon
.ste_mode
)
1224 hdb_off
= (64 + base_off
+ (128 / bpp
+ 2) * plen
) + prescale
;
1226 hdb_off
= (base_off
+ (128 / bpp
+ 18) * plen
) + prescale
;
1229 gstart
= (prescale
/ 2 + plen
* left_margin
) / prescale
;
1230 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1231 gend1
= gstart
+ roundup(xres
, align
) * plen
/ prescale
;
1232 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1233 gend2
= gstart
+ xres
* plen
/ prescale
;
1234 par
->HHT
= plen
* (left_margin
+ xres
+ right_margin
) /
1236 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1238 par
->HDB
= gstart
- hdb_off
/ prescale
;
1241 par
->HDB
+= par
->HHT
+ 2 + 0x200;
1242 par
->HDE
= gend1
- par
->HHT
- 2 - hde_off
/ prescale
;
1243 par
->HBB
= gend2
- par
->HHT
- 2;
1245 /* One more Videl constraint: data fetch of two lines must not overlap */
1246 if ((par
->HDB
& 0x200) && (par
->HDB
& ~0x200) - par
->HDE
<= 5) {
1247 /* if this happens increase margins, decrease hfreq. */
1250 if (hde_off
% prescale
)
1251 par
->HBB
++; /* compensate for non matching hde and hbb */
1252 par
->HSS
= par
->HHT
+ 2 - plen
* hsync_len
/ prescale
;
1253 if (par
->HSS
< par
->HBB
)
1254 par
->HSS
= par
->HBB
;
1257 /* check hor. frequency */
1258 hfreq
= pclock
->f
/ ((par
->HHT
+ 2) * prescale
* 2);
1259 if (hfreq
> fb_info
.monspecs
.hfmax
&& mon_type
!= F_MON_VGA
) {
1260 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1261 /* Too high -> enlarge margin */
1266 if (hfreq
> fb_info
.monspecs
.hfmax
|| hfreq
< fb_info
.monspecs
.hfmin
)
1270 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1271 * of the first displayed line!
1272 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1273 * non-interlace, odd in interlace mode for synchronisation.
1274 * Vxx-registers are 11 bit wide
1276 par
->VBE
= (upper_margin
* 2 + 1); /* must begin on odd halfline */
1277 par
->VDB
= par
->VBE
;
1282 par
->VDE
<<= 1; /* VDE now half lines per (half-)frame */
1283 par
->VDE
+= par
->VDB
;
1284 par
->VBB
= par
->VDE
;
1285 par
->VFT
= par
->VBB
+ (lower_margin
* 2 - 1) - 1;
1286 par
->VSS
= par
->VFT
+ 1 - (vsync_len
* 2 - 1);
1287 /* vbb,vss,vft must be even in interlace mode */
1294 /* V-frequency check, hope I didn't create any loop here. */
1295 /* Interlace and doubleline are mutually exclusive. */
1296 vfreq
= (hfreq
* 2) / (par
->VFT
+ 1);
1297 if (vfreq
> fb_info
.monspecs
.vfmax
&& !doubleline
&& !interlace
) {
1298 /* Too high -> try again with doubleline */
1301 } else if (vfreq
< fb_info
.monspecs
.vfmin
&& !interlace
&& !doubleline
) {
1302 /* Too low -> try again with interlace */
1305 } else if (vfreq
< fb_info
.monspecs
.vfmin
&& doubleline
) {
1306 /* Doubleline too low -> clear doubleline and enlarge margins */
1310 (hfreq
* 2) / (par
->VFT
+ 1 + 4 * lines
- 2 * yres
) >
1311 fb_info
.monspecs
.vfmax
;
1314 upper_margin
+= lines
;
1315 lower_margin
+= lines
;
1317 } else if (vfreq
> fb_info
.monspecs
.vfmax
&& doubleline
) {
1318 /* Doubleline too high -> enlarge margins */
1321 (hfreq
* 2) / (par
->VFT
+ 1 + 4 * lines
) >
1322 fb_info
.monspecs
.vfmax
;
1325 upper_margin
+= lines
;
1326 lower_margin
+= lines
;
1328 } else if (vfreq
> fb_info
.monspecs
.vfmax
&& interlace
) {
1329 /* Interlace, too high -> enlarge margins */
1332 (hfreq
* 2) / (par
->VFT
+ 1 + 4 * lines
) >
1333 fb_info
.monspecs
.vfmax
;
1336 upper_margin
+= lines
;
1337 lower_margin
+= lines
;
1339 } else if (vfreq
< fb_info
.monspecs
.vfmin
||
1340 vfreq
> fb_info
.monspecs
.vfmax
)
1344 linelen
= xres_virtual
* bpp
/ 8;
1345 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
1347 if (yres
* linelen
> screen_len
&& screen_len
)
1349 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
1351 par
->yres_virtual
= yres_virtual
;
1352 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
1353 par
->hw
.falcon
.xoffset
= 0;
1355 par
->next_line
= linelen
;
1360 static int falcon_encode_var(struct fb_var_screeninfo
*var
,
1361 struct atafb_par
*par
)
1363 /* !!! only for VGA !!! */
1366 int hdb_off
, hde_off
, base_off
;
1367 struct falcon_hw
*hw
= &par
->hw
.falcon
;
1369 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
1370 /* possible frequencies: 25.175 or 32MHz */
1371 var
->pixclock
= hw
->sync
& 0x1 ? fext
.t
:
1372 hw
->vid_control
& VCO_CLOCK25
? f25
.t
: f32
.t
;
1378 if (hw
->vid_control
& VCO_HSYPOS
)
1379 var
->sync
|= FB_SYNC_HOR_HIGH_ACT
;
1380 if (hw
->vid_control
& VCO_VSYPOS
)
1381 var
->sync
|= FB_SYNC_VERT_HIGH_ACT
;
1383 var
->vmode
= FB_VMODE_NONINTERLACED
;
1384 if (hw
->vid_mode
& VMO_INTER
)
1385 var
->vmode
|= FB_VMODE_INTERLACED
;
1386 if (hw
->vid_mode
& VMO_DOUBLE
)
1387 var
->vmode
|= FB_VMODE_DOUBLE
;
1389 /* visible y resolution:
1390 * Graphics display starts at line VDB and ends at line
1391 * VDE. If interlace mode off unit of VC-registers is
1392 * half lines, else lines.
1394 var
->yres
= hw
->vde
- hw
->vdb
;
1395 if (!(var
->vmode
& FB_VMODE_INTERLACED
))
1397 if (var
->vmode
& FB_VMODE_DOUBLE
)
1401 * to get bpp, we must examine f_shift and st_shift.
1402 * f_shift is valid if any of bits no. 10, 8 or 4
1403 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1404 * if bit 10 set then bit 8 and bit 4 don't care...
1405 * If all these bits are 0 get display depth from st_shift
1406 * (as for ST and STE)
1408 if (hw
->f_shift
& 0x400) /* 2 colors */
1409 var
->bits_per_pixel
= 1;
1410 else if (hw
->f_shift
& 0x100) /* hicolor */
1411 var
->bits_per_pixel
= 16;
1412 else if (hw
->f_shift
& 0x010) /* 8 bitplanes */
1413 var
->bits_per_pixel
= 8;
1414 else if (hw
->st_shift
== 0)
1415 var
->bits_per_pixel
= 4;
1416 else if (hw
->st_shift
== 0x100)
1417 var
->bits_per_pixel
= 2;
1418 else /* if (hw->st_shift == 0x200) */
1419 var
->bits_per_pixel
= 1;
1421 var
->xres
= hw
->line_width
* 16 / var
->bits_per_pixel
;
1422 var
->xres_virtual
= var
->xres
+ hw
->line_offset
* 16 / var
->bits_per_pixel
;
1424 var
->xres_virtual
+= 16;
1426 if (var
->bits_per_pixel
== 16) {
1427 var
->red
.offset
= 11;
1428 var
->red
.length
= 5;
1429 var
->red
.msb_right
= 0;
1430 var
->green
.offset
= 5;
1431 var
->green
.length
= 6;
1432 var
->green
.msb_right
= 0;
1433 var
->blue
.offset
= 0;
1434 var
->blue
.length
= 5;
1435 var
->blue
.msb_right
= 0;
1437 var
->red
.offset
= 0;
1438 var
->red
.length
= hw
->ste_mode
? 4 : 6;
1439 if (var
->red
.length
> var
->bits_per_pixel
)
1440 var
->red
.length
= var
->bits_per_pixel
;
1441 var
->red
.msb_right
= 0;
1443 var
->blue
= var
->green
= var
->red
;
1445 var
->transp
.offset
= 0;
1446 var
->transp
.length
= 0;
1447 var
->transp
.msb_right
= 0;
1449 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
1451 if (par
->yres_virtual
)
1452 var
->yres_virtual
= par
->yres_virtual
;
1454 /* yres_virtual == 0 means use maximum */
1455 var
->yres_virtual
= screen_len
/ linelen
;
1458 var
->yres_virtual
= 2 * var
->yres
;
1460 var
->yres_virtual
= var
->yres
+ hwscroll
* 16;
1462 var
->xoffset
= 0; /* TODO change this */
1465 prescale
= hxx_prescale(hw
);
1466 plen
= 4 >> (hw
->vid_mode
>> 2 & 0x3);
1467 base_off
= hw
->vid_control
& VCO_SHORTOFFS
? 64 : 128;
1468 if (hw
->f_shift
& 0x100) {
1470 hdb_off
= (base_off
+ 16 * plen
) + prescale
;
1472 hde_off
= ((128 / var
->bits_per_pixel
+ 2) * plen
);
1474 hdb_off
= (64 + base_off
+ (128 / var
->bits_per_pixel
+ 2) * plen
)
1477 hdb_off
= (base_off
+ (128 / var
->bits_per_pixel
+ 18) * plen
)
1481 /* Right margin includes hsync */
1482 var
->left_margin
= hdb_off
+ prescale
* ((hw
->hdb
& 0x1ff) -
1483 (hw
->hdb
& 0x200 ? 2 + hw
->hht
: 0));
1484 if (hw
->ste_mode
|| mon_type
!= F_MON_VGA
)
1485 var
->right_margin
= prescale
* (hw
->hht
+ 2 - hw
->hde
) - hde_off
;
1487 /* can't use this in ste_mode, because hbb is +1 off */
1488 var
->right_margin
= prescale
* (hw
->hht
+ 2 - hw
->hbb
);
1489 var
->hsync_len
= prescale
* (hw
->hht
+ 2 - hw
->hss
);
1491 /* Lower margin includes vsync */
1492 var
->upper_margin
= hw
->vdb
/ 2; /* round down to full lines */
1493 var
->lower_margin
= (hw
->vft
+ 1 - hw
->vde
+ 1) / 2; /* round up */
1494 var
->vsync_len
= (hw
->vft
+ 1 - hw
->vss
+ 1) / 2; /* round up */
1495 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1496 var
->upper_margin
*= 2;
1497 var
->lower_margin
*= 2;
1498 var
->vsync_len
*= 2;
1499 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1500 var
->upper_margin
= (var
->upper_margin
+ 1) / 2;
1501 var
->lower_margin
= (var
->lower_margin
+ 1) / 2;
1502 var
->vsync_len
= (var
->vsync_len
+ 1) / 2;
1505 var
->pixclock
*= plen
;
1506 var
->left_margin
/= plen
;
1507 var
->right_margin
/= plen
;
1508 var
->hsync_len
/= plen
;
1510 var
->right_margin
-= var
->hsync_len
;
1511 var
->lower_margin
-= var
->vsync_len
;
1514 var
->yoffset
= (par
->screen_base
- screen_base
) / linelen
;
1517 var
->nonstd
= 0; /* what is this for? */
1522 static int f_change_mode
;
1523 static struct falcon_hw f_new_mode
;
1524 static int f_pan_display
;
1526 static void falcon_get_par(struct atafb_par
*par
)
1529 struct falcon_hw
*hw
= &par
->hw
.falcon
;
1531 hw
->line_width
= shifter_f030
.scn_width
;
1532 hw
->line_offset
= shifter_f030
.off_next
;
1533 hw
->st_shift
= videl
.st_shift
& 0x300;
1534 hw
->f_shift
= videl
.f_shift
;
1535 hw
->vid_control
= videl
.control
;
1536 hw
->vid_mode
= videl
.mode
;
1537 hw
->sync
= shifter_st
.syncmode
& 0x1;
1538 hw
->xoffset
= videl
.xoffset
& 0xf;
1539 hw
->hht
= videl
.hht
;
1540 hw
->hbb
= videl
.hbb
;
1541 hw
->hbe
= videl
.hbe
;
1542 hw
->hdb
= videl
.hdb
;
1543 hw
->hde
= videl
.hde
;
1544 hw
->hss
= videl
.hss
;
1545 hw
->vft
= videl
.vft
;
1546 hw
->vbb
= videl
.vbb
;
1547 hw
->vbe
= videl
.vbe
;
1548 hw
->vdb
= videl
.vdb
;
1549 hw
->vde
= videl
.vde
;
1550 hw
->vss
= videl
.vss
;
1552 addr
= (shifter_st
.bas_hi
& 0xff) << 16 |
1553 (shifter_st
.bas_md
& 0xff) << 8 |
1554 (shifter_st
.bas_lo
& 0xff);
1555 par
->screen_base
= atari_stram_to_virt(addr
);
1557 /* derived parameters */
1558 hw
->ste_mode
= (hw
->f_shift
& 0x510) == 0 && hw
->st_shift
== 0x100;
1559 hw
->mono
= (hw
->f_shift
& 0x400) ||
1560 ((hw
->f_shift
& 0x510) == 0 && hw
->st_shift
== 0x200);
1563 static void falcon_set_par(struct atafb_par
*par
)
1567 /* only set screen_base if really necessary */
1568 if (current_par
.screen_base
!= par
->screen_base
)
1569 fbhw
->set_screen_base(par
->screen_base
);
1571 /* Don't touch any other registers if we keep the default resolution */
1575 /* Tell vbl-handler to change video mode.
1576 * We change modes only on next VBL, to avoid desynchronisation
1577 * (a shift to the right and wrap around by a random number of pixels
1578 * in all monochrome modes).
1579 * This seems to work on my Falcon.
1581 f_new_mode
= par
->hw
.falcon
;
1585 static irqreturn_t
falcon_vbl_switcher(int irq
, void *dummy
)
1587 struct falcon_hw
*hw
= &f_new_mode
;
1589 if (f_change_mode
) {
1592 if (hw
->sync
& 0x1) {
1593 /* Enable external pixelclock. This code only for ScreenWonder */
1594 *(volatile unsigned short *)0xffff9202 = 0xffbf;
1596 /* Turn off external clocks. Read sets all output bits to 1. */
1597 *(volatile unsigned short *)0xffff9202;
1599 shifter_st
.syncmode
= hw
->sync
;
1601 videl
.hht
= hw
->hht
;
1602 videl
.hbb
= hw
->hbb
;
1603 videl
.hbe
= hw
->hbe
;
1604 videl
.hdb
= hw
->hdb
;
1605 videl
.hde
= hw
->hde
;
1606 videl
.hss
= hw
->hss
;
1607 videl
.vft
= hw
->vft
;
1608 videl
.vbb
= hw
->vbb
;
1609 videl
.vbe
= hw
->vbe
;
1610 videl
.vdb
= hw
->vdb
;
1611 videl
.vde
= hw
->vde
;
1612 videl
.vss
= hw
->vss
;
1614 videl
.f_shift
= 0; /* write enables Falcon palette, 0: 4 planes */
1616 videl
.st_shift
= hw
->st_shift
; /* write enables STE palette */
1619 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1620 * Writing 0 to f_shift enables 4 plane Falcon mode but
1621 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1622 * with Falcon palette.
1625 /* now back to Falcon palette mode */
1626 videl
.f_shift
= hw
->f_shift
;
1628 /* writing to st_shift changed scn_width and vid_mode */
1629 videl
.xoffset
= hw
->xoffset
;
1630 shifter_f030
.scn_width
= hw
->line_width
;
1631 shifter_f030
.off_next
= hw
->line_offset
;
1632 videl
.control
= hw
->vid_control
;
1633 videl
.mode
= hw
->vid_mode
;
1635 if (f_pan_display
) {
1637 videl
.xoffset
= current_par
.hw
.falcon
.xoffset
;
1638 shifter_f030
.off_next
= current_par
.hw
.falcon
.line_offset
;
1643 static int falcon_pan_display(struct fb_var_screeninfo
*var
,
1644 struct fb_info
*info
)
1646 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
1649 int bpp
= info
->var
.bits_per_pixel
;
1652 var
->xoffset
= up(var
->xoffset
, 32);
1654 par
->hw
.falcon
.xoffset
= var
->xoffset
& 15;
1656 par
->hw
.falcon
.xoffset
= 0;
1657 var
->xoffset
= up(var
->xoffset
, 2);
1659 par
->hw
.falcon
.line_offset
= bpp
*
1660 (info
->var
.xres_virtual
- info
->var
.xres
) / 16;
1661 if (par
->hw
.falcon
.xoffset
)
1662 par
->hw
.falcon
.line_offset
-= bpp
;
1663 xoffset
= var
->xoffset
- par
->hw
.falcon
.xoffset
;
1665 par
->screen_base
= screen_base
+
1666 (var
->yoffset
* info
->var
.xres_virtual
+ xoffset
) * bpp
/ 8;
1667 if (fbhw
->set_screen_base
)
1668 fbhw
->set_screen_base(par
->screen_base
);
1670 return -EINVAL
; /* shouldn't happen */
1675 static int falcon_setcolreg(unsigned int regno
, unsigned int red
,
1676 unsigned int green
, unsigned int blue
,
1677 unsigned int transp
, struct fb_info
*info
)
1681 f030_col
[regno
] = (((red
& 0xfc00) << 16) |
1682 ((green
& 0xfc00) << 8) |
1683 ((blue
& 0xfc00) >> 8));
1685 shifter_tt
.color_reg
[regno
] =
1686 (((red
& 0xe000) >> 13) | ((red
& 0x1000) >> 12) << 8) |
1687 (((green
& 0xe000) >> 13) | ((green
& 0x1000) >> 12) << 4) |
1688 ((blue
& 0xe000) >> 13) | ((blue
& 0x1000) >> 12);
1689 ((u32
*)info
->pseudo_palette
)[regno
] = ((red
& 0xf800) |
1690 ((green
& 0xfc00) >> 5) |
1691 ((blue
& 0xf800) >> 11));
1696 static int falcon_blank(int blank_mode
)
1698 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1699 * so VIDEL doesn't hog the bus while saving.
1700 * (this may affect usleep()).
1702 int vdb
, vss
, hbe
, hss
;
1704 if (mon_type
== F_MON_SM
) /* this doesn't work on SM124 */
1707 vdb
= current_par
.VDB
;
1708 vss
= current_par
.VSS
;
1709 hbe
= current_par
.HBE
;
1710 hss
= current_par
.HSS
;
1712 if (blank_mode
>= 1) {
1713 /* disable graphics output (this speeds up the CPU) ... */
1714 vdb
= current_par
.VFT
+ 1;
1715 /* ... and blank all lines */
1716 hbe
= current_par
.HHT
+ 2;
1718 /* use VESA suspend modes on VGA monitors */
1719 if (mon_type
== F_MON_VGA
) {
1720 if (blank_mode
== 2 || blank_mode
== 4)
1721 vss
= current_par
.VFT
+ 1;
1722 if (blank_mode
== 3 || blank_mode
== 4)
1723 hss
= current_par
.HHT
+ 2;
1734 static int falcon_detect(void)
1736 struct atafb_par par
;
1739 /* Determine connected monitor and set monitor parameters */
1740 fhw
= *(unsigned char *)0xffff8006;
1741 mon_type
= fhw
>> 6 & 0x3;
1742 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1743 f030_bus_width
= fhw
<< 6 & 0x80;
1746 fb_info
.monspecs
.vfmin
= 70;
1747 fb_info
.monspecs
.vfmax
= 72;
1748 fb_info
.monspecs
.hfmin
= 35713;
1749 fb_info
.monspecs
.hfmax
= 35715;
1754 fb_info
.monspecs
.vfmin
= 49; /* not 50, since TOS defaults to 49.9x Hz */
1755 fb_info
.monspecs
.vfmax
= 60;
1756 fb_info
.monspecs
.hfmin
= 15620;
1757 fb_info
.monspecs
.hfmax
= 15755;
1760 /* initialize hsync-len */
1761 f25
.hsync
= h_syncs
[mon_type
] / f25
.t
;
1762 f32
.hsync
= h_syncs
[mon_type
] / f32
.t
;
1764 fext
.hsync
= h_syncs
[mon_type
] / fext
.t
;
1766 falcon_get_par(&par
);
1767 falcon_encode_var(&atafb_predefined
[0], &par
);
1769 /* Detected mode is always the "autodetect" slot */
1773 #endif /* ATAFB_FALCON */
1775 /* ------------------- ST(E) specific functions ---------------------- */
1779 static int stste_encode_fix(struct fb_fix_screeninfo
*fix
,
1780 struct atafb_par
*par
)
1784 strcpy(fix
->id
, "Atari Builtin");
1785 fix
->smem_start
= phys_screen_base
;
1786 fix
->smem_len
= screen_len
;
1787 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
1789 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
1790 mode
= par
->hw
.st
.mode
& 3;
1791 if (mode
== ST_HIGH
) {
1792 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1794 fix
->visual
= FB_VISUAL_MONO10
;
1796 if (ATARIHW_PRESENT(EXTD_SHIFTER
)) {
1804 fix
->line_length
= par
->next_line
;
1805 fix
->accel
= FB_ACCEL_ATARIBLITT
;
1809 static int stste_decode_var(struct fb_var_screeninfo
*var
,
1810 struct atafb_par
*par
)
1812 int xres
= var
->xres
;
1813 int yres
= var
->yres
;
1814 int bpp
= var
->bits_per_pixel
;
1816 int yres_virtual
= var
->yres_virtual
;
1819 if (bpp
> 1 || xres
> sttt_xres
|| yres
> st_yres
)
1821 par
->hw
.st
.mode
= ST_HIGH
;
1826 if (bpp
> 4 || xres
> sttt_xres
|| yres
> st_yres
)
1829 if (xres
> sttt_xres
/ 2 || yres
> st_yres
/ 2)
1831 par
->hw
.st
.mode
= ST_LOW
;
1832 xres
= sttt_xres
/ 2;
1835 } else if (bpp
> 1) {
1836 if (xres
> sttt_xres
|| yres
> st_yres
/ 2)
1838 par
->hw
.st
.mode
= ST_MID
;
1845 if (yres_virtual
<= 0)
1847 else if (yres_virtual
< yres
)
1848 yres_virtual
= yres
;
1849 if (var
->sync
& FB_SYNC_EXT
)
1850 par
->hw
.st
.sync
= (par
->hw
.st
.sync
& ~1) | 1;
1852 par
->hw
.st
.sync
= (par
->hw
.st
.sync
& ~1);
1853 linelen
= xres
* bpp
/ 8;
1854 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
1856 if (yres
* linelen
> screen_len
&& screen_len
)
1858 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
1860 par
->yres_virtual
= yres_virtual
;
1861 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
1862 par
->next_line
= linelen
;
1866 static int stste_encode_var(struct fb_var_screeninfo
*var
,
1867 struct atafb_par
*par
)
1870 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
1871 var
->red
.offset
= 0;
1872 var
->red
.length
= ATARIHW_PRESENT(EXTD_SHIFTER
) ? 4 : 3;
1873 var
->red
.msb_right
= 0;
1876 var
->pixclock
= 31041;
1877 var
->left_margin
= 120; /* these are incorrect */
1878 var
->right_margin
= 100;
1879 var
->upper_margin
= 8;
1880 var
->lower_margin
= 16;
1881 var
->hsync_len
= 140;
1882 var
->vsync_len
= 30;
1887 if (!(par
->hw
.st
.sync
& 1))
1890 var
->sync
= FB_SYNC_EXT
;
1892 switch (par
->hw
.st
.mode
& 3) {
1894 var
->xres
= sttt_xres
/ 2;
1895 var
->yres
= st_yres
/ 2;
1896 var
->bits_per_pixel
= 4;
1899 var
->xres
= sttt_xres
;
1900 var
->yres
= st_yres
/ 2;
1901 var
->bits_per_pixel
= 2;
1904 var
->xres
= sttt_xres
;
1905 var
->yres
= st_yres
;
1906 var
->bits_per_pixel
= 1;
1909 var
->blue
= var
->green
= var
->red
;
1910 var
->transp
.offset
= 0;
1911 var
->transp
.length
= 0;
1912 var
->transp
.msb_right
= 0;
1913 var
->xres_virtual
= sttt_xres_virtual
;
1914 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
1915 ovsc_addlen
= linelen
* (sttt_yres_virtual
- st_yres
);
1918 var
->yres_virtual
= var
->yres
;
1919 else if (screen_len
) {
1920 if (par
->yres_virtual
)
1921 var
->yres_virtual
= par
->yres_virtual
;
1923 /* yres_virtual == 0 means use maximum */
1924 var
->yres_virtual
= screen_len
/ linelen
;
1927 var
->yres_virtual
= 2 * var
->yres
;
1929 var
->yres_virtual
= var
->yres
+ hwscroll
* 16;
1933 var
->yoffset
= (par
->screen_base
- screen_base
) / linelen
;
1938 var
->vmode
= FB_VMODE_NONINTERLACED
;
1942 static void stste_get_par(struct atafb_par
*par
)
1945 par
->hw
.st
.mode
= shifter_tt
.st_shiftmode
;
1946 par
->hw
.st
.sync
= shifter_st
.syncmode
;
1947 addr
= ((shifter_st
.bas_hi
& 0xff) << 16) |
1948 ((shifter_st
.bas_md
& 0xff) << 8);
1949 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
1950 addr
|= (shifter_st
.bas_lo
& 0xff);
1951 par
->screen_base
= atari_stram_to_virt(addr
);
1954 static void stste_set_par(struct atafb_par
*par
)
1956 shifter_tt
.st_shiftmode
= par
->hw
.st
.mode
;
1957 shifter_st
.syncmode
= par
->hw
.st
.sync
;
1958 /* only set screen_base if really necessary */
1959 if (current_par
.screen_base
!= par
->screen_base
)
1960 fbhw
->set_screen_base(par
->screen_base
);
1963 static int stste_setcolreg(unsigned int regno
, unsigned int red
,
1964 unsigned int green
, unsigned int blue
,
1965 unsigned int transp
, struct fb_info
*info
)
1972 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
1973 shifter_tt
.color_reg
[regno
] =
1974 (((red
& 0xe) >> 1) | ((red
& 1) << 3) << 8) |
1975 (((green
& 0xe) >> 1) | ((green
& 1) << 3) << 4) |
1976 ((blue
& 0xe) >> 1) | ((blue
& 1) << 3);
1978 shifter_tt
.color_reg
[regno
] =
1979 ((red
& 0xe) << 7) |
1980 ((green
& 0xe) << 3) |
1981 ((blue
& 0xe) >> 1);
1985 static int stste_detect(void)
1987 struct atafb_par par
;
1989 /* Determine the connected monitor: The DMA sound must be
1990 * disabled before reading the MFP GPIP, because the Sound
1991 * Done Signal and the Monochrome Detect are XORed together!
1993 if (ATARIHW_PRESENT(PCM_8BIT
)) {
1994 tt_dmasnd
.ctrl
= DMASND_CTRL_OFF
;
1995 udelay(20); /* wait a while for things to settle down */
1997 mono_moni
= (st_mfp
.par_dt_reg
& 0x80) == 0;
1999 stste_get_par(&par
);
2000 stste_encode_var(&atafb_predefined
[0], &par
);
2002 if (!ATARIHW_PRESENT(EXTD_SHIFTER
))
2007 static void stste_set_screen_base(void *s_base
)
2010 addr
= atari_stram_to_phys(s_base
);
2011 /* Setup Screen Memory */
2012 shifter_st
.bas_hi
= (unsigned char)((addr
& 0xff0000) >> 16);
2013 shifter_st
.bas_md
= (unsigned char)((addr
& 0x00ff00) >> 8);
2014 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
2015 shifter_st
.bas_lo
= (unsigned char)(addr
& 0x0000ff);
2018 #endif /* ATAFB_STE */
2020 /* Switching the screen size should be done during vsync, otherwise
2021 * the margins may get messed up. This is a well known problem of
2022 * the ST's video system.
2024 * Unfortunately there is hardly any way to find the vsync, as the
2025 * vertical blank interrupt is no longer in time on machines with
2026 * overscan type modifications.
2028 * We can, however, use Timer B to safely detect the black shoulder,
2029 * but then we've got to guess an appropriate delay to find the vsync.
2030 * This might not work on every machine.
2032 * martin_rogge @ ki.maus.de, 8th Aug 1995
2035 #define LINE_DELAY (mono_moni ? 30 : 70)
2036 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2038 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2039 static void st_ovsc_switch(void)
2041 unsigned long flags
;
2042 register unsigned char old
, new;
2044 if (!(atari_switches
& ATARI_SWITCH_OVSC_MASK
))
2046 local_irq_save(flags
);
2048 st_mfp
.tim_ct_b
= 0x10;
2049 st_mfp
.active_edge
|= 8;
2050 st_mfp
.tim_ct_b
= 0;
2051 st_mfp
.tim_dt_b
= 0xf0;
2052 st_mfp
.tim_ct_b
= 8;
2053 while (st_mfp
.tim_dt_b
> 1) /* TOS does it this way, don't ask why */
2055 new = st_mfp
.tim_dt_b
;
2059 new = st_mfp
.tim_dt_b
;
2060 } while (old
!= new);
2061 st_mfp
.tim_ct_b
= 0x10;
2064 if (atari_switches
& ATARI_SWITCH_OVSC_IKBD
)
2065 acia
.key_ctrl
= ACIA_DIV64
| ACIA_D8N1S
| ACIA_RHTID
| ACIA_RIE
;
2066 if (atari_switches
& ATARI_SWITCH_OVSC_MIDI
)
2067 acia
.mid_ctrl
= ACIA_DIV16
| ACIA_D8N1S
| ACIA_RHTID
;
2068 if (atari_switches
& (ATARI_SWITCH_OVSC_SND6
|ATARI_SWITCH_OVSC_SND7
)) {
2069 sound_ym
.rd_data_reg_sel
= 14;
2070 sound_ym
.wd_data
= sound_ym
.rd_data_reg_sel
|
2071 ((atari_switches
& ATARI_SWITCH_OVSC_SND6
) ? 0x40:0) |
2072 ((atari_switches
& ATARI_SWITCH_OVSC_SND7
) ? 0x80:0);
2074 local_irq_restore(flags
);
2077 /* ------------------- External Video ---------------------- */
2081 static int ext_encode_fix(struct fb_fix_screeninfo
*fix
, struct atafb_par
*par
)
2083 strcpy(fix
->id
, "Unknown Extern");
2084 fix
->smem_start
= external_addr
;
2085 fix
->smem_len
= PAGE_ALIGN(external_len
);
2086 if (external_depth
== 1) {
2087 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2088 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2089 * for "normal" and "inverted", rsp., in the monochrome case */
2091 (external_pmode
== FB_TYPE_INTERLEAVED_PLANES
||
2092 external_pmode
== FB_TYPE_PACKED_PIXELS
) ?
2093 FB_VISUAL_MONO10
: FB_VISUAL_MONO01
;
2095 /* Use STATIC if we don't know how to access color registers */
2096 int visual
= external_vgaiobase
?
2097 FB_VISUAL_PSEUDOCOLOR
:
2098 FB_VISUAL_STATIC_PSEUDOCOLOR
;
2099 switch (external_pmode
) {
2100 case -1: /* truecolor */
2101 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2102 fix
->visual
= FB_VISUAL_TRUECOLOR
;
2104 case FB_TYPE_PACKED_PIXELS
:
2105 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2106 fix
->visual
= visual
;
2108 case FB_TYPE_PLANES
:
2109 fix
->type
= FB_TYPE_PLANES
;
2110 fix
->visual
= visual
;
2112 case FB_TYPE_INTERLEAVED_PLANES
:
2113 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
2115 fix
->visual
= visual
;
2122 fix
->line_length
= par
->next_line
;
2126 static int ext_decode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
2128 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
2130 if (var
->bits_per_pixel
> myvar
->bits_per_pixel
||
2131 var
->xres
> myvar
->xres
||
2132 var
->xres_virtual
> myvar
->xres_virtual
||
2133 var
->yres
> myvar
->yres
||
2138 par
->next_line
= external_xres_virtual
* external_depth
/ 8;
2142 static int ext_encode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
2144 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
2145 var
->red
.offset
= 0;
2146 var
->red
.length
= (external_pmode
== -1) ? external_depth
/ 3 :
2147 (external_vgaiobase
? external_bitspercol
: 0);
2148 var
->red
.msb_right
= 0;
2151 var
->pixclock
= 31041;
2152 var
->left_margin
= 120; /* these are surely incorrect */
2153 var
->right_margin
= 100;
2154 var
->upper_margin
= 8;
2155 var
->lower_margin
= 16;
2156 var
->hsync_len
= 140;
2157 var
->vsync_len
= 30;
2164 var
->xres
= external_xres
;
2165 var
->yres
= external_yres
;
2166 var
->xres_virtual
= external_xres_virtual
;
2167 var
->bits_per_pixel
= external_depth
;
2169 var
->blue
= var
->green
= var
->red
;
2170 var
->transp
.offset
= 0;
2171 var
->transp
.length
= 0;
2172 var
->transp
.msb_right
= 0;
2173 var
->yres_virtual
= var
->yres
;
2178 var
->vmode
= FB_VMODE_NONINTERLACED
;
2182 static void ext_get_par(struct atafb_par
*par
)
2184 par
->screen_base
= external_screen_base
;
2187 static void ext_set_par(struct atafb_par
*par
)
2191 #define OUTB(port,val) \
2192 *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2194 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2197 unsigned char tmp = INB(0x3da); \
2201 static int ext_setcolreg(unsigned int regno
, unsigned int red
,
2202 unsigned int green
, unsigned int blue
,
2203 unsigned int transp
, struct fb_info
*info
)
2205 unsigned char colmask
= (1 << external_bitspercol
) - 1;
2207 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
= (struct atafb_par
*)info
->par
;
2268 if (!fbhw
->set_screen_base
||
2269 (!ATARIHW_PRESENT(EXTD_SHIFTER
) && var
->xoffset
))
2271 var
->xoffset
= 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
));
2409 static int atafb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
2410 u_int transp
, struct fb_info
*info
)
2416 return info
->fbops
->fb_setcolreg(regno
, red
, green
, blue
, transp
, info
);
2420 atafb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2422 int xoffset
= var
->xoffset
;
2423 int yoffset
= var
->yoffset
;
2426 if (var
->vmode
& FB_VMODE_YWRAP
) {
2427 if (yoffset
< 0 || yoffset
>= info
->var
.yres_virtual
|| xoffset
)
2430 if (xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
2431 yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
2435 if (fbhw
->pan_display
) {
2436 err
= fbhw
->pan_display(var
, info
);
2442 info
->var
.xoffset
= xoffset
;
2443 info
->var
.yoffset
= yoffset
;
2445 if (var
->vmode
& FB_VMODE_YWRAP
)
2446 info
->var
.vmode
|= FB_VMODE_YWRAP
;
2448 info
->var
.vmode
&= ~FB_VMODE_YWRAP
;
2454 * generic drawing routines; imageblit needs updating for image depth > 1
2457 #if BITS_PER_LONG == 32
2458 #define BYTES_PER_LONG 4
2459 #define SHIFT_PER_LONG 5
2460 #elif BITS_PER_LONG == 64
2461 #define BYTES_PER_LONG 8
2462 #define SHIFT_PER_LONG 6
2464 #define Please update me
2468 static void atafb_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
2470 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
2474 if (!rect
->width
|| !rect
->height
)
2478 if (info
->var
.bits_per_pixel
== 16) {
2479 cfb_fillrect(info
, rect
);
2485 * We could use hardware clipping but on many cards you get around
2486 * hardware clipping by writing to framebuffer directly.
2488 x2
= rect
->dx
+ rect
->width
;
2489 y2
= rect
->dy
+ rect
->height
;
2490 x2
= x2
< info
->var
.xres_virtual
? x2
: info
->var
.xres_virtual
;
2491 y2
= y2
< info
->var
.yres_virtual
? y2
: info
->var
.yres_virtual
;
2492 width
= x2
- rect
->dx
;
2493 height
= y2
- rect
->dy
;
2495 if (info
->var
.bits_per_pixel
== 1)
2496 atafb_mfb_fillrect(info
, par
->next_line
, rect
->color
,
2497 rect
->dy
, rect
->dx
, height
, width
);
2498 else if (info
->var
.bits_per_pixel
== 2)
2499 atafb_iplan2p2_fillrect(info
, par
->next_line
, rect
->color
,
2500 rect
->dy
, rect
->dx
, height
, width
);
2501 else if (info
->var
.bits_per_pixel
== 4)
2502 atafb_iplan2p4_fillrect(info
, par
->next_line
, rect
->color
,
2503 rect
->dy
, rect
->dx
, height
, width
);
2505 atafb_iplan2p8_fillrect(info
, par
->next_line
, rect
->color
,
2506 rect
->dy
, rect
->dx
, height
, width
);
2511 static void atafb_copyarea(struct fb_info
*info
, const struct fb_copyarea
*area
)
2513 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
2515 u32 dx
, dy
, sx
, sy
, width
, height
;
2519 if (info
->var
.bits_per_pixel
== 16) {
2520 cfb_copyarea(info
, area
);
2525 /* clip the destination */
2526 x2
= area
->dx
+ area
->width
;
2527 y2
= area
->dy
+ area
->height
;
2528 dx
= area
->dx
> 0 ? area
->dx
: 0;
2529 dy
= area
->dy
> 0 ? area
->dy
: 0;
2530 x2
= x2
< info
->var
.xres_virtual
? x2
: info
->var
.xres_virtual
;
2531 y2
= y2
< info
->var
.yres_virtual
? y2
: info
->var
.yres_virtual
;
2535 if (area
->sx
+ dx
< area
->dx
|| area
->sy
+ dy
< area
->dy
)
2539 sx
= area
->sx
+ (dx
- area
->dx
);
2540 sy
= area
->sy
+ (dy
- area
->dy
);
2542 /* the source must be completely inside the virtual screen */
2543 if (sx
+ width
> info
->var
.xres_virtual
||
2544 sy
+ height
> info
->var
.yres_virtual
)
2547 if (dy
> sy
|| (dy
== sy
&& dx
> sx
)) {
2553 if (info
->var
.bits_per_pixel
== 1)
2554 atafb_mfb_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2555 else if (info
->var
.bits_per_pixel
== 2)
2556 atafb_iplan2p2_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2557 else if (info
->var
.bits_per_pixel
== 4)
2558 atafb_iplan2p4_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2560 atafb_iplan2p8_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2565 static void atafb_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
2567 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
2572 u32 dx
, dy
, width
, height
, pitch
;
2575 if (info
->var
.bits_per_pixel
== 16) {
2576 cfb_imageblit(info
, image
);
2582 * We could use hardware clipping but on many cards you get around
2583 * hardware clipping by writing to framebuffer directly like we are
2586 x2
= image
->dx
+ image
->width
;
2587 y2
= image
->dy
+ image
->height
;
2590 x2
= x2
< info
->var
.xres_virtual
? x2
: info
->var
.xres_virtual
;
2591 y2
= y2
< info
->var
.yres_virtual
? y2
: info
->var
.yres_virtual
;
2595 if (image
->depth
== 1) {
2596 // used for font data
2597 dst
= (unsigned long *)
2598 ((unsigned long)info
->screen_base
& ~(BYTES_PER_LONG
- 1));
2599 dst_idx
= ((unsigned long)info
->screen_base
& (BYTES_PER_LONG
- 1)) * 8;
2600 dst_idx
+= dy
* par
->next_line
* 8 + dx
;
2602 pitch
= (image
->width
+ 7) / 8;
2605 if (info
->var
.bits_per_pixel
== 1)
2606 atafb_mfb_linefill(info
, par
->next_line
,
2608 image
->bg_color
, image
->fg_color
);
2609 else if (info
->var
.bits_per_pixel
== 2)
2610 atafb_iplan2p2_linefill(info
, par
->next_line
,
2612 image
->bg_color
, image
->fg_color
);
2613 else if (info
->var
.bits_per_pixel
== 4)
2614 atafb_iplan2p4_linefill(info
, par
->next_line
,
2616 image
->bg_color
, image
->fg_color
);
2618 atafb_iplan2p8_linefill(info
, par
->next_line
,
2620 image
->bg_color
, image
->fg_color
);
2625 c2p_iplan2(info
->screen_base
, image
->data
, dx
, dy
, width
,
2626 height
, par
->next_line
, image
->width
,
2627 info
->var
.bits_per_pixel
);
2632 atafb_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
2635 #ifdef FBCMD_GET_CURRENTPAR
2636 case FBCMD_GET_CURRENTPAR
:
2637 if (copy_to_user((void *)arg
, (void *)¤t_par
,
2638 sizeof(struct atafb_par
)))
2642 #ifdef FBCMD_SET_CURRENTPAR
2643 case FBCMD_SET_CURRENTPAR
:
2644 if (copy_from_user((void *)¤t_par
, (void *)arg
,
2645 sizeof(struct atafb_par
)))
2647 ata_set_par(¤t_par
);
2654 /* (un)blank/poweroff
2661 static int atafb_blank(int blank
, struct fb_info
*info
)
2663 unsigned short black
[16];
2664 struct fb_cmap cmap
;
2665 if (fbhw
->blank
&& !fbhw
->blank(blank
))
2668 memset(black
, 0, 16 * sizeof(unsigned short));
2675 fb_set_cmap(&cmap
, info
);
2679 do_install_cmap(info
);
2685 * New fbcon interface ...
2688 /* check var by decoding var into hw par, rounding if necessary,
2689 * then encoding hw par back into new, validated var */
2690 static int atafb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2693 struct atafb_par par
;
2695 /* Validate wanted screen parameters */
2696 // if ((err = ata_decode_var(var, &par)))
2697 err
= fbhw
->decode_var(var
, &par
);
2701 /* Encode (possibly rounded) screen parameters */
2702 fbhw
->encode_var(var
, &par
);
2706 /* actually set hw par by decoding var, then setting hardware from
2707 * hw par just decoded */
2708 static int atafb_set_par(struct fb_info
*info
)
2710 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
2712 /* Decode wanted screen parameters */
2713 fbhw
->decode_var(&info
->var
, par
);
2714 mutex_lock(&info
->mm_lock
);
2715 fbhw
->encode_fix(&info
->fix
, par
);
2716 mutex_unlock(&info
->mm_lock
);
2718 /* Set new videomode */
2725 static struct fb_ops atafb_ops
= {
2726 .owner
= THIS_MODULE
,
2727 .fb_check_var
= atafb_check_var
,
2728 .fb_set_par
= atafb_set_par
,
2729 .fb_setcolreg
= atafb_setcolreg
,
2730 .fb_blank
= atafb_blank
,
2731 .fb_pan_display
= atafb_pan_display
,
2732 .fb_fillrect
= atafb_fillrect
,
2733 .fb_copyarea
= atafb_copyarea
,
2734 .fb_imageblit
= atafb_imageblit
,
2735 .fb_ioctl
= atafb_ioctl
,
2738 static void check_default_par(int detected_mode
)
2740 char default_name
[10];
2742 struct fb_var_screeninfo var
;
2743 unsigned long min_mem
;
2745 /* First try the user supplied mode */
2747 var
= atafb_predefined
[default_par
- 1];
2748 var
.activate
= FB_ACTIVATE_TEST
;
2749 if (do_fb_set_var(&var
, 1))
2750 default_par
= 0; /* failed */
2752 /* Next is the autodetected one */
2754 var
= atafb_predefined
[detected_mode
- 1]; /* autodetect */
2755 var
.activate
= FB_ACTIVATE_TEST
;
2756 if (!do_fb_set_var(&var
, 1))
2757 default_par
= detected_mode
;
2759 /* If that also failed, try some default modes... */
2761 /* try default1, default2... */
2762 for (i
= 1; i
< 10; i
++) {
2763 sprintf(default_name
,"default%d", i
);
2764 default_par
= get_video_mode(default_name
);
2766 panic("can't set default video mode");
2767 var
= atafb_predefined
[default_par
- 1];
2768 var
.activate
= FB_ACTIVATE_TEST
;
2769 if (!do_fb_set_var(&var
,1))
2773 min_mem
= var
.xres_virtual
* var
.yres_virtual
* var
.bits_per_pixel
/ 8;
2774 if (default_mem_req
< min_mem
)
2775 default_mem_req
= min_mem
;
2779 static void __init
atafb_setup_ext(char *spec
)
2781 int xres
, xres_virtual
, yres
, depth
, planes
;
2782 unsigned long addr
, len
;
2785 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2787 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2788 * [;<xres-virtual>]]]]]
2791 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2793 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2795 p
= strsep(&spec
, ";");
2798 xres_virtual
= xres
= simple_strtoul(p
, NULL
, 10);
2802 p
= strsep(&spec
, ";");
2805 yres
= simple_strtoul(p
, NULL
, 10);
2809 p
= strsep(&spec
, ";");
2812 depth
= simple_strtoul(p
, NULL
, 10);
2813 if (depth
!= 1 && depth
!= 2 && depth
!= 4 && depth
!= 8 &&
2814 depth
!= 16 && depth
!= 24)
2817 p
= strsep(&spec
, ";");
2821 planes
= FB_TYPE_INTERLEAVED_PLANES
;
2823 planes
= FB_TYPE_PACKED_PIXELS
;
2825 planes
= FB_TYPE_PLANES
;
2827 planes
= -1; /* true color */
2831 p
= strsep(&spec
, ";");
2834 addr
= simple_strtoul(p
, NULL
, 0);
2836 p
= strsep(&spec
, ";");
2838 len
= xres
* yres
* depth
/ 8;
2840 len
= simple_strtoul(p
, NULL
, 0);
2842 p
= strsep(&spec
, ";");
2844 external_vgaiobase
= simple_strtoul(p
, NULL
, 0);
2846 p
= strsep(&spec
, ";");
2848 external_bitspercol
= simple_strtoul(p
, NULL
, 0);
2849 if (external_bitspercol
> 8)
2850 external_bitspercol
= 8;
2851 else if (external_bitspercol
< 1)
2852 external_bitspercol
= 1;
2855 p
= strsep(&spec
, ";");
2857 if (!strcmp(p
, "vga"))
2858 external_card_type
= IS_VGA
;
2859 if (!strcmp(p
, "mv300"))
2860 external_card_type
= IS_MV300
;
2863 p
= strsep(&spec
, ";");
2865 xres_virtual
= simple_strtoul(p
, NULL
, 10);
2866 if (xres_virtual
< xres
)
2867 xres_virtual
= xres
;
2868 if (xres_virtual
* yres
* depth
/ 8 > len
)
2869 len
= xres_virtual
* yres
* depth
/ 8;
2872 external_xres
= xres
;
2873 external_xres_virtual
= xres_virtual
;
2874 external_yres
= yres
;
2875 external_depth
= depth
;
2876 external_pmode
= planes
;
2877 external_addr
= addr
;
2880 if (external_card_type
== IS_MV300
) {
2881 switch (external_depth
) {
2883 MV300_reg
= MV300_reg_1bit
;
2886 MV300_reg
= MV300_reg_4bit
;
2889 MV300_reg
= MV300_reg_8bit
;
2894 #endif /* ATAFB_EXT */
2896 static void __init
atafb_setup_int(char *spec
)
2898 /* Format to config extended internal video hardware like OverScan:
2899 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2901 * <xres>: x-resolution
2902 * <yres>: y-resolution
2903 * The following are only needed if you have an overscan which
2904 * needs a black border:
2905 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2906 * <yres_max>: max. number of lines your OverScan hardware would allow
2907 * <offset>: Offset from physical beginning to visible beginning
2908 * of screen in bytes
2913 if (!(p
= strsep(&spec
, ";")) || !*p
)
2915 xres
= simple_strtoul(p
, NULL
, 10);
2916 if (!(p
= strsep(&spec
, ";")) || !*p
)
2919 tt_yres
= st_yres
= simple_strtoul(p
, NULL
, 10);
2920 if ((p
= strsep(&spec
, ";")) && *p
)
2921 sttt_xres_virtual
= simple_strtoul(p
, NULL
, 10);
2922 if ((p
= strsep(&spec
, ";")) && *p
)
2923 sttt_yres_virtual
= simple_strtoul(p
, NULL
, 0);
2924 if ((p
= strsep(&spec
, ";")) && *p
)
2925 ovsc_offset
= simple_strtoul(p
, NULL
, 0);
2927 if (ovsc_offset
|| (sttt_yres_virtual
!= st_yres
))
2932 static void __init
atafb_setup_mcap(char *spec
)
2935 int vmin
, vmax
, hmin
, hmax
;
2937 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2938 * <V*> vertical freq. in Hz
2939 * <H*> horizontal freq. in kHz
2941 if (!(p
= strsep(&spec
, ";")) || !*p
)
2943 vmin
= simple_strtoul(p
, NULL
, 10);
2946 if (!(p
= strsep(&spec
, ";")) || !*p
)
2948 vmax
= simple_strtoul(p
, NULL
, 10);
2949 if (vmax
<= 0 || vmax
<= vmin
)
2951 if (!(p
= strsep(&spec
, ";")) || !*p
)
2953 hmin
= 1000 * simple_strtoul(p
, NULL
, 10);
2956 if (!(p
= strsep(&spec
, "")) || !*p
)
2958 hmax
= 1000 * simple_strtoul(p
, NULL
, 10);
2959 if (hmax
<= 0 || hmax
<= hmin
)
2962 fb_info
.monspecs
.vfmin
= vmin
;
2963 fb_info
.monspecs
.vfmax
= vmax
;
2964 fb_info
.monspecs
.hfmin
= hmin
;
2965 fb_info
.monspecs
.hfmax
= hmax
;
2967 #endif /* ATAFB_FALCON */
2969 static void __init
atafb_setup_user(char *spec
)
2971 /* Format of user defined video mode is: <xres>;<yres>;<depth>
2974 int xres
, yres
, depth
, temp
;
2976 p
= strsep(&spec
, ";");
2979 xres
= simple_strtoul(p
, NULL
, 10);
2980 p
= strsep(&spec
, ";");
2983 yres
= simple_strtoul(p
, NULL
, 10);
2984 p
= strsep(&spec
, "");
2987 depth
= simple_strtoul(p
, NULL
, 10);
2988 temp
= get_video_mode("user0");
2991 atafb_predefined
[default_par
- 1].xres
= xres
;
2992 atafb_predefined
[default_par
- 1].yres
= yres
;
2993 atafb_predefined
[default_par
- 1].bits_per_pixel
= depth
;
2997 int __init
atafb_setup(char *options
)
3002 if (!options
|| !*options
)
3005 while ((this_opt
= strsep(&options
, ",")) != NULL
) {
3008 if ((temp
= get_video_mode(this_opt
))) {
3010 mode_option
= this_opt
;
3011 } else if (!strcmp(this_opt
, "inverse"))
3013 else if (!strncmp(this_opt
, "hwscroll_", 9)) {
3014 hwscroll
= simple_strtoul(this_opt
+ 9, NULL
, 10);
3021 else if (!strcmp(this_opt
, "mv300")) {
3022 external_bitspercol
= 8;
3023 external_card_type
= IS_MV300
;
3024 } else if (!strncmp(this_opt
, "external:", 9))
3025 atafb_setup_ext(this_opt
+ 9);
3027 else if (!strncmp(this_opt
, "internal:", 9))
3028 atafb_setup_int(this_opt
+ 9);
3030 else if (!strncmp(this_opt
, "eclock:", 7)) {
3031 fext
.f
= simple_strtoul(this_opt
+ 7, NULL
, 10);
3032 /* external pixelclock in kHz --> ps */
3033 fext
.t
= 1000000000 / fext
.f
;
3035 } else if (!strncmp(this_opt
, "monitorcap:", 11))
3036 atafb_setup_mcap(this_opt
+ 11);
3038 else if (!strcmp(this_opt
, "keep"))
3040 else if (!strncmp(this_opt
, "R", 1))
3041 atafb_setup_user(this_opt
+ 1);
3046 static int __init
atafb_probe(struct platform_device
*pdev
)
3048 int pad
, detected_mode
, error
;
3049 unsigned int defmode
= 0;
3050 unsigned long mem_req
;
3051 char *option
= NULL
;
3053 if (fb_get_options("atafb", &option
))
3055 atafb_setup(option
);
3056 dev_dbg(&pdev
->dev
, "%s: start\n", __func__
);
3060 if (external_addr
) {
3061 dev_dbg(&pdev
->dev
, "initializing external hw\n");
3063 atafb_ops
.fb_setcolreg
= &ext_setcolreg
;
3064 defmode
= DEFMODE_EXT
;
3069 if (ATARIHW_PRESENT(TT_SHIFTER
)) {
3070 dev_dbg(&pdev
->dev
, "initializing TT hw\n");
3072 atafb_ops
.fb_setcolreg
= &tt_setcolreg
;
3073 defmode
= DEFMODE_TT
;
3078 if (ATARIHW_PRESENT(VIDEL_SHIFTER
)) {
3079 dev_dbg(&pdev
->dev
, "initializing Falcon hw\n");
3080 fbhw
= &falcon_switch
;
3081 atafb_ops
.fb_setcolreg
= &falcon_setcolreg
;
3082 error
= request_irq(IRQ_AUTO_4
, falcon_vbl_switcher
, 0,
3083 "framebuffer:modeswitch",
3084 falcon_vbl_switcher
);
3087 defmode
= DEFMODE_F30
;
3092 if (ATARIHW_PRESENT(STND_SHIFTER
) ||
3093 ATARIHW_PRESENT(EXTD_SHIFTER
)) {
3094 dev_dbg(&pdev
->dev
, "initializing ST/E hw\n");
3096 atafb_ops
.fb_setcolreg
= &stste_setcolreg
;
3097 defmode
= DEFMODE_STE
;
3101 atafb_ops
.fb_setcolreg
= &stste_setcolreg
;
3102 dev_warn(&pdev
->dev
,
3103 "Cannot determine video hardware; defaulting to ST(e)\n");
3104 #else /* ATAFB_STE */
3105 /* no default driver included */
3106 /* Nobody will ever see this message :-) */
3107 panic("Cannot initialize video hardware");
3111 /* Multisync monitor capabilities */
3112 /* Atari-TOS defaults if no boot option present */
3113 if (fb_info
.monspecs
.hfmin
== 0) {
3114 fb_info
.monspecs
.hfmin
= 31000;
3115 fb_info
.monspecs
.hfmax
= 32000;
3116 fb_info
.monspecs
.vfmin
= 58;
3117 fb_info
.monspecs
.vfmax
= 62;
3120 detected_mode
= fbhw
->detect();
3121 check_default_par(detected_mode
);
3123 if (!external_addr
) {
3124 #endif /* ATAFB_EXT */
3125 mem_req
= default_mem_req
+ ovsc_offset
+ ovsc_addlen
;
3126 mem_req
= PAGE_ALIGN(mem_req
) + PAGE_SIZE
;
3127 screen_base
= atari_stram_alloc(mem_req
, "atafb");
3129 panic("Cannot allocate screen memory");
3130 memset(screen_base
, 0, mem_req
);
3131 pad
= -(unsigned long)screen_base
& (PAGE_SIZE
- 1);
3133 phys_screen_base
= atari_stram_to_phys(screen_base
+ ovsc_offset
);
3134 screen_len
= (mem_req
- pad
- ovsc_offset
) & PAGE_MASK
;
3136 if (CPU_IS_040_OR_060
) {
3137 /* On a '040+, the cache mode of video RAM must be set to
3138 * write-through also for internal video hardware! */
3139 cache_push(atari_stram_to_phys(screen_base
), screen_len
);
3140 kernel_set_cachemode(screen_base
, screen_len
,
3141 IOMAP_WRITETHROUGH
);
3143 dev_info(&pdev
->dev
, "phys_screen_base %lx screen_len %d\n",
3144 phys_screen_base
, screen_len
);
3147 /* Map the video memory (physical address given) to somewhere
3148 * in the kernel address space.
3150 external_screen_base
= ioremap_wt(external_addr
, external_len
);
3151 if (external_vgaiobase
)
3152 external_vgaiobase
=
3153 (unsigned long)ioremap(external_vgaiobase
, 0x10000);
3154 screen_base
= external_screen_base
;
3155 phys_screen_base
= external_addr
;
3156 screen_len
= external_len
& PAGE_MASK
;
3157 memset (screen_base
, 0, external_len
);
3159 #endif /* ATAFB_EXT */
3161 // strcpy(fb_info.mode->name, "Atari Builtin ");
3162 fb_info
.fbops
= &atafb_ops
;
3163 // try to set default (detected; requested) var
3164 do_fb_set_var(&atafb_predefined
[default_par
- 1], 1);
3165 // reads hw state into current par, which may not be sane yet
3166 ata_get_par(¤t_par
);
3167 fb_info
.par
= ¤t_par
;
3168 // tries to read from HW which may not be initialized yet
3169 // so set sane var first, then call atafb_set_par
3170 atafb_get_var(&fb_info
.var
, &fb_info
);
3173 fb_info
.pseudo_palette
= current_par
.hw
.falcon
.pseudo_palette
;
3175 fb_info
.flags
= FBINFO_FLAG_DEFAULT
;
3177 if (!fb_find_mode(&fb_info
.var
, &fb_info
, mode_option
, atafb_modedb
,
3178 NUM_TOTAL_MODES
, &atafb_modedb
[defmode
],
3179 fb_info
.var
.bits_per_pixel
)) {
3183 fb_videomode_to_modelist(atafb_modedb
, NUM_TOTAL_MODES
,
3186 atafb_set_disp(&fb_info
);
3188 fb_alloc_cmap(&(fb_info
.cmap
), 1 << fb_info
.var
.bits_per_pixel
, 0);
3191 dev_info(&pdev
->dev
, "Determined %dx%d, depth %d\n", fb_info
.var
.xres
,
3192 fb_info
.var
.yres
, fb_info
.var
.bits_per_pixel
);
3193 if ((fb_info
.var
.xres
!= fb_info
.var
.xres_virtual
) ||
3194 (fb_info
.var
.yres
!= fb_info
.var
.yres_virtual
))
3195 dev_info(&pdev
->dev
, " virtual %dx%d\n",
3196 fb_info
.var
.xres_virtual
, fb_info
.var
.yres_virtual
);
3198 if (register_framebuffer(&fb_info
) < 0) {
3200 if (external_addr
) {
3201 iounmap(external_screen_base
);
3204 if (external_vgaiobase
) {
3205 iounmap((void*)external_vgaiobase
);
3206 external_vgaiobase
= 0;
3212 fb_info(&fb_info
, "frame buffer device, using %dK of video memory\n",
3215 /* TODO: This driver cannot be unloaded yet */
3219 static void atafb_shutdown(struct platform_device
*pdev
)
3221 /* Unblank before kexec */
3226 static struct platform_driver atafb_driver
= {
3227 .shutdown
= atafb_shutdown
,
3233 static int __init
atafb_init(void)
3235 struct platform_device
*pdev
;
3240 pdev
= platform_device_register_simple("atafb", -1, NULL
, 0);
3242 return PTR_ERR(pdev
);
3244 return platform_driver_probe(&atafb_driver
, atafb_probe
);
3247 device_initcall(atafb_init
);