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>
61 #include <asm/pgtable.h>
65 #include <asm/atarihw.h>
66 #include <asm/atariints.h>
67 #include <asm/atari_stram.h>
70 #include <asm/atarikb.h>
75 #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
76 #define SWITCH_SND6 0x40
77 #define SWITCH_SND7 0x80
78 #define SWITCH_NONE 0x00
80 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
83 static int default_par
; /* default resolution (0=none) */
85 static unsigned long default_mem_req
;
87 static int hwscroll
= -1;
89 static int use_hwscroll
= 1;
91 static int sttt_xres
= 640, st_yres
= 400, tt_yres
= 480;
92 static int sttt_xres_virtual
= 640, sttt_yres_virtual
= 400;
93 static int ovsc_offset
, ovsc_addlen
;
96 * Hardware parameters for current mode
99 static struct atafb_par
{
103 #if defined ATAFB_TT || defined ATAFB_STE
112 /* Here are fields for storing a video mode, as direct
113 * parameters for the hardware.
123 short hht
, hbb
, hbe
, hdb
, hde
, hss
;
124 short vft
, vbb
, vbe
, vdb
, vde
, vss
;
125 /* auxiliary information */
129 u32 pseudo_palette
[16];
132 /* Nothing needed for external mode */
136 /* Don't calculate an own resolution, and thus don't change the one found when
137 * booting (currently used for the Falcon to keep settings for internal video
138 * hardware extensions (e.g. ScreenBlaster) */
139 static int DontCalcRes
= 0;
142 #define HHT hw.falcon.hht
143 #define HBB hw.falcon.hbb
144 #define HBE hw.falcon.hbe
145 #define HDB hw.falcon.hdb
146 #define HDE hw.falcon.hde
147 #define HSS hw.falcon.hss
148 #define VFT hw.falcon.vft
149 #define VBB hw.falcon.vbb
150 #define VBE hw.falcon.vbe
151 #define VDB hw.falcon.vdb
152 #define VDE hw.falcon.vde
153 #define VSS hw.falcon.vss
154 #define VCO_CLOCK25 0x04
155 #define VCO_CSYPOS 0x10
156 #define VCO_VSYPOS 0x20
157 #define VCO_HSYPOS 0x40
158 #define VCO_SHORTOFFS 0x100
159 #define VMO_DOUBLE 0x01
160 #define VMO_INTER 0x02
161 #define VMO_PREMASK 0x0c
164 static struct fb_info fb_info
= {
167 .visual
= FB_VISUAL_PSEUDOCOLOR
,
168 .accel
= FB_ACCEL_NONE
,
172 static void *screen_base
; /* base address of screen */
173 static unsigned long phys_screen_base
; /* (only for Overscan) */
175 static int screen_len
;
177 static int current_par_valid
;
179 static int mono_moni
;
184 /* external video handling */
185 static unsigned int external_xres
;
186 static unsigned int external_xres_virtual
;
187 static unsigned int external_yres
;
190 * not needed - atafb will never support panning/hardwarescroll with external
191 * static unsigned int external_yres_virtual;
193 static unsigned int external_depth
;
194 static int external_pmode
;
195 static void *external_screen_base
;
196 static unsigned long external_addr
;
197 static unsigned long external_len
;
198 static unsigned long external_vgaiobase
;
199 static unsigned int external_bitspercol
= 6;
202 * JOE <joe@amber.dinoco.de>:
203 * added card type for external driver, is only needed for
206 enum cardtype
{ IS_VGA
, IS_MV300
};
207 static enum cardtype external_card_type
= IS_VGA
;
210 * The MV300 mixes the color registers. So we need an array of munged
211 * indices in order to access the correct reg.
213 static int MV300_reg_1bit
[2] = {
216 static int MV300_reg_4bit
[16] = {
217 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
219 static int MV300_reg_8bit
[256] = {
220 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
221 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
222 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
223 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
224 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
225 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
226 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
227 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
228 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
229 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
230 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
231 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
232 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
233 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
234 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
235 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
238 static int *MV300_reg
= MV300_reg_8bit
;
239 #endif /* ATAFB_EXT */
244 extern int fontheight_8x8
;
245 extern int fontwidth_8x8
;
246 extern unsigned char fontdata_8x8
[];
248 extern int fontheight_8x16
;
249 extern int fontwidth_8x16
;
250 extern unsigned char fontdata_8x16
[];
254 * * open/release and usage marking
255 * struct module *owner;
256 * int (*fb_open)(struct fb_info *info, int user);
257 * int (*fb_release)(struct fb_info *info, int user);
259 * * For framebuffers with strange non linear layouts or that do not
260 * * work with normal memory mapped access
261 * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
262 * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
264 * * checks var and eventually tweaks it to something supported,
265 * * DOES NOT MODIFY PAR *
266 * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
268 * * set the video mode according to info->var *
269 * int (*fb_set_par)(struct fb_info *info);
271 * * set color register *
272 * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
273 * unsigned int blue, unsigned int transp, struct fb_info *info);
275 * * set color registers in batch *
276 * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
279 * int (*fb_blank)(int blank, struct fb_info *info);
282 * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
284 * *** The meat of the drawing engine ***
285 * * Draws a rectangle *
286 * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
287 * * Copy data from area to another *
288 * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
289 * * Draws a image to the display *
290 * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
293 * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
295 * * wait for blit idle, optional *
296 * int (*fb_sync)(struct fb_info *info);
298 * * perform fb specific ioctl (optional) *
299 * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
300 * unsigned long arg);
302 * * Handle 32bit compat ioctl (optional) *
303 * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
304 * unsigned long arg);
306 * * perform fb specific mmap *
307 * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
312 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
315 * int (*detect)(void)
316 * This function should detect the current video mode settings and
317 * store them in atafb_predefined[0] for later reference by the
318 * user. Return the index+1 of an equivalent predefined mode or 0
319 * if there is no such.
321 * int (*encode_fix)(struct fb_fix_screeninfo *fix,
322 * struct atafb_par *par)
323 * This function should fill in the 'fix' structure based on the
324 * values in the 'par' structure.
325 * !!! Obsolete, perhaps !!!
327 * int (*decode_var)(struct fb_var_screeninfo *var,
328 * struct atafb_par *par)
329 * Get the video params out of 'var'. If a value doesn't fit, round
330 * it up, if it's too big, return EINVAL.
331 * Round up in the following order: bits_per_pixel, xres, yres,
332 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
333 * horizontal timing, vertical timing.
335 * int (*encode_var)(struct fb_var_screeninfo *var,
336 * struct atafb_par *par);
337 * Fill the 'var' structure based on the values in 'par' and maybe
338 * other values read out of the hardware.
340 * void (*get_par)(struct atafb_par *par)
341 * Fill the hardware's 'par' structure.
342 * !!! Used only by detect() !!!
344 * void (*set_par)(struct atafb_par *par)
345 * Set the hardware according to 'par'.
347 * void (*set_screen_base)(void *s_base)
348 * Set the base address of the displayed frame buffer. Only called
349 * if yres_virtual > yres or xres_virtual > xres.
351 * int (*blank)(int blank_mode)
352 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
353 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
354 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
355 * doesn't support it. Implements VESA suspend and powerdown modes on
356 * hardware that supports disabling hsync/vsync:
357 * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
360 static struct fb_hwswitch
{
362 int (*encode_fix
)(struct fb_fix_screeninfo
*fix
,
363 struct atafb_par
*par
);
364 int (*decode_var
)(struct fb_var_screeninfo
*var
,
365 struct atafb_par
*par
);
366 int (*encode_var
)(struct fb_var_screeninfo
*var
,
367 struct atafb_par
*par
);
368 void (*get_par
)(struct atafb_par
*par
);
369 void (*set_par
)(struct atafb_par
*par
);
370 void (*set_screen_base
)(void *s_base
);
371 int (*blank
)(int blank_mode
);
372 int (*pan_display
)(struct fb_var_screeninfo
*var
,
373 struct fb_info
*info
);
376 static char *autodetect_names
[] = { "autodetect", NULL
};
377 static char *stlow_names
[] = { "stlow", NULL
};
378 static char *stmid_names
[] = { "stmid", "default5", NULL
};
379 static char *sthigh_names
[] = { "sthigh", "default4", NULL
};
380 static char *ttlow_names
[] = { "ttlow", NULL
};
381 static char *ttmid_names
[] = { "ttmid", "default1", NULL
};
382 static char *tthigh_names
[] = { "tthigh", "default2", NULL
};
383 static char *vga2_names
[] = { "vga2", NULL
};
384 static char *vga4_names
[] = { "vga4", NULL
};
385 static char *vga16_names
[] = { "vga16", "default3", NULL
};
386 static char *vga256_names
[] = { "vga256", NULL
};
387 static char *falh2_names
[] = { "falh2", NULL
};
388 static char *falh16_names
[] = { "falh16", NULL
};
390 static char **fb_var_names
[] = {
407 static struct fb_var_screeninfo atafb_predefined
[] = {
409 * yres_virtual == 0 means use hw-scrolling if possible, else yres
412 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
413 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
414 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
416 320, 200, 320, 0, 0, 0, 4, 0,
417 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
418 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
420 640, 200, 640, 0, 0, 0, 2, 0,
421 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
422 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
424 640, 400, 640, 0, 0, 0, 1, 0,
425 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
426 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
428 320, 480, 320, 0, 0, 0, 8, 0,
429 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
430 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
432 640, 480, 640, 0, 0, 0, 4, 0,
433 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
434 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
436 1280, 960, 1280, 0, 0, 0, 1, 0,
437 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
438 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
440 640, 480, 640, 0, 0, 0, 1, 0,
441 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
442 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
444 640, 480, 640, 0, 0, 0, 2, 0,
445 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
446 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
448 640, 480, 640, 0, 0, 0, 4, 0,
449 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
450 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
452 640, 480, 640, 0, 0, 0, 8, 0,
453 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
454 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
456 896, 608, 896, 0, 0, 0, 1, 0,
457 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
458 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
460 896, 608, 896, 0, 0, 0, 4, 0,
461 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
462 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
465 static int num_atafb_predefined
= ARRAY_SIZE(atafb_predefined
);
467 static struct fb_videomode atafb_modedb
[] __initdata
= {
471 * If you change these, make sure to update DEFMODE_* as well!
479 /* 320x200, 15 kHz, 60 Hz (ST low) */
480 "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
481 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
483 /* 640x200, 15 kHz, 60 Hz (ST medium) */
484 "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
485 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
487 /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
488 "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
489 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
491 /* 320x480, 15 kHz, 60 Hz (TT low) */
492 "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
493 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
495 /* 640x480, 29 kHz, 57 Hz (TT medium) */
496 "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
497 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
499 /* 1280x960, 29 kHz, 60 Hz (TT high) */
500 "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
501 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
509 /* 640x480, 31 kHz, 60 Hz (VGA) */
510 "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
511 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
513 /* 640x400, 31 kHz, 70 Hz (VGA) */
514 "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
515 FB_SYNC_VERT_HIGH_ACT
| FB_SYNC_COMP_HIGH_ACT
, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
519 * Falcon HiRes Video Modes
523 /* 896x608, 31 kHz, 60 Hz (Falcon High) */
524 "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
525 0, FB_VMODE_NONINTERLACED
| FB_VMODE_YWRAP
529 #define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb)
531 static char *mode_option __initdata
= NULL
;
535 #define DEFMODE_TT 5 /* "tt-high" for TT */
536 #define DEFMODE_F30 7 /* "vga70" for Falcon */
537 #define DEFMODE_STE 2 /* "st-high" for ST/E */
538 #define DEFMODE_EXT 6 /* "vga" for external */
541 static int get_video_mode(char *vname
)
547 name_list
= fb_var_names
;
548 for (i
= 0; i
< num_atafb_predefined
; i
++) {
553 if (!strcmp(vname
, *name
))
563 /* ------------------- TT specific functions ---------------------- */
567 static int tt_encode_fix(struct fb_fix_screeninfo
*fix
, struct atafb_par
*par
)
571 strcpy(fix
->id
, "Atari Builtin");
572 fix
->smem_start
= phys_screen_base
;
573 fix
->smem_len
= screen_len
;
574 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
576 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
577 mode
= par
->hw
.tt
.mode
& TT_SHIFTER_MODEMASK
;
578 if (mode
== TT_SHIFTER_TTHIGH
|| mode
== TT_SHIFTER_STHIGH
) {
579 fix
->type
= FB_TYPE_PACKED_PIXELS
;
581 if (mode
== TT_SHIFTER_TTHIGH
)
582 fix
->visual
= FB_VISUAL_MONO01
;
587 fix
->line_length
= par
->next_line
;
588 fix
->accel
= FB_ACCEL_ATARIBLITT
;
592 static int tt_decode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
594 int xres
= var
->xres
;
595 int yres
= var
->yres
;
596 int bpp
= var
->bits_per_pixel
;
598 int yres_virtual
= var
->yres_virtual
;
601 if (bpp
> 1 || xres
> sttt_xres
* 2 || yres
> tt_yres
* 2)
603 par
->hw
.tt
.mode
= TT_SHIFTER_TTHIGH
;
604 xres
= sttt_xres
* 2;
608 if (bpp
> 8 || xres
> sttt_xres
|| yres
> tt_yres
)
611 if (xres
> sttt_xres
/ 2 || yres
> tt_yres
)
613 par
->hw
.tt
.mode
= TT_SHIFTER_TTLOW
;
614 xres
= sttt_xres
/ 2;
617 } else if (bpp
> 2) {
618 if (xres
> sttt_xres
|| yres
> tt_yres
)
620 if (xres
> sttt_xres
/ 2 || yres
> st_yres
/ 2) {
621 par
->hw
.tt
.mode
= TT_SHIFTER_TTMID
;
626 par
->hw
.tt
.mode
= TT_SHIFTER_STLOW
;
627 xres
= sttt_xres
/ 2;
631 } else if (bpp
> 1) {
632 if (xres
> sttt_xres
|| yres
> st_yres
/ 2)
634 par
->hw
.tt
.mode
= TT_SHIFTER_STMID
;
638 } else if (var
->xres
> sttt_xres
|| var
->yres
> st_yres
) {
641 par
->hw
.tt
.mode
= TT_SHIFTER_STHIGH
;
647 if (yres_virtual
<= 0)
649 else if (yres_virtual
< yres
)
651 if (var
->sync
& FB_SYNC_EXT
)
655 linelen
= xres
* bpp
/ 8;
656 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
658 if (yres
* linelen
> screen_len
&& screen_len
)
660 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
662 par
->yres_virtual
= yres_virtual
;
663 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
664 par
->next_line
= linelen
;
668 static int tt_encode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
671 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
674 var
->red
.msb_right
= 0;
677 var
->pixclock
= 31041;
678 var
->left_margin
= 120; /* these may be incorrect */
679 var
->right_margin
= 100;
680 var
->upper_margin
= 8;
681 var
->lower_margin
= 16;
682 var
->hsync_len
= 140;
688 if (par
->hw
.tt
.sync
& 1)
691 var
->sync
= FB_SYNC_EXT
;
693 switch (par
->hw
.tt
.mode
& TT_SHIFTER_MODEMASK
) {
694 case TT_SHIFTER_STLOW
:
695 var
->xres
= sttt_xres
/ 2;
696 var
->xres_virtual
= sttt_xres_virtual
/ 2;
697 var
->yres
= st_yres
/ 2;
698 var
->bits_per_pixel
= 4;
700 case TT_SHIFTER_STMID
:
701 var
->xres
= sttt_xres
;
702 var
->xres_virtual
= sttt_xres_virtual
;
703 var
->yres
= st_yres
/ 2;
704 var
->bits_per_pixel
= 2;
706 case TT_SHIFTER_STHIGH
:
707 var
->xres
= sttt_xres
;
708 var
->xres_virtual
= sttt_xres_virtual
;
710 var
->bits_per_pixel
= 1;
712 case TT_SHIFTER_TTLOW
:
713 var
->xres
= sttt_xres
/ 2;
714 var
->xres_virtual
= sttt_xres_virtual
/ 2;
716 var
->bits_per_pixel
= 8;
718 case TT_SHIFTER_TTMID
:
719 var
->xres
= sttt_xres
;
720 var
->xres_virtual
= sttt_xres_virtual
;
722 var
->bits_per_pixel
= 4;
724 case TT_SHIFTER_TTHIGH
:
726 var
->xres
= sttt_xres
* 2;
727 var
->xres_virtual
= sttt_xres_virtual
* 2;
728 var
->yres
= tt_yres
* 2;
729 var
->bits_per_pixel
= 1;
732 var
->blue
= var
->green
= var
->red
;
733 var
->transp
.offset
= 0;
734 var
->transp
.length
= 0;
735 var
->transp
.msb_right
= 0;
736 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
738 var
->yres_virtual
= var
->yres
;
739 else if (screen_len
) {
740 if (par
->yres_virtual
)
741 var
->yres_virtual
= par
->yres_virtual
;
743 /* yres_virtual == 0 means use maximum */
744 var
->yres_virtual
= screen_len
/ linelen
;
747 var
->yres_virtual
= 2 * var
->yres
;
749 var
->yres_virtual
= var
->yres
+ hwscroll
* 16;
753 var
->yoffset
= (par
->screen_base
- screen_base
) / linelen
;
758 var
->vmode
= FB_VMODE_NONINTERLACED
;
762 static void tt_get_par(struct atafb_par
*par
)
765 par
->hw
.tt
.mode
= shifter_tt
.tt_shiftmode
;
766 par
->hw
.tt
.sync
= shifter_st
.syncmode
;
767 addr
= ((shifter_st
.bas_hi
& 0xff) << 16) |
768 ((shifter_st
.bas_md
& 0xff) << 8) |
769 ((shifter_st
.bas_lo
& 0xff));
770 par
->screen_base
= atari_stram_to_virt(addr
);
773 static void tt_set_par(struct atafb_par
*par
)
775 shifter_tt
.tt_shiftmode
= par
->hw
.tt
.mode
;
776 shifter_st
.syncmode
= par
->hw
.tt
.sync
;
777 /* only set screen_base if really necessary */
778 if (current_par
.screen_base
!= par
->screen_base
)
779 fbhw
->set_screen_base(par
->screen_base
);
782 static int tt_setcolreg(unsigned int regno
, unsigned int red
,
783 unsigned int green
, unsigned int blue
,
784 unsigned int transp
, struct fb_info
*info
)
786 if ((shifter_tt
.tt_shiftmode
& TT_SHIFTER_MODEMASK
) == TT_SHIFTER_STHIGH
)
790 tt_palette
[regno
] = (((red
>> 12) << 8) | ((green
>> 12) << 4) |
792 if ((shifter_tt
.tt_shiftmode
& TT_SHIFTER_MODEMASK
) ==
793 TT_SHIFTER_STHIGH
&& regno
== 254)
798 static int tt_detect(void)
800 struct atafb_par par
;
802 /* Determine the connected monitor: The DMA sound must be
803 * disabled before reading the MFP GPIP, because the Sound
804 * Done Signal and the Monochrome Detect are XORed together!
806 * Even on a TT, we should look if there is a DMA sound. It was
807 * announced that the Eagle is TT compatible, but only the PCM is
810 if (ATARIHW_PRESENT(PCM_8BIT
)) {
811 tt_dmasnd
.ctrl
= DMASND_CTRL_OFF
;
812 udelay(20); /* wait a while for things to settle down */
814 mono_moni
= (st_mfp
.par_dt_reg
& 0x80) == 0;
817 tt_encode_var(&atafb_predefined
[0], &par
);
822 #endif /* ATAFB_TT */
824 /* ------------------- Falcon specific functions ---------------------- */
828 static int mon_type
; /* Falcon connected monitor */
829 static int f030_bus_width
; /* Falcon ram bus width (for vid_control) */
835 static struct pixel_clock
{
836 unsigned long f
; /* f/[Hz] */
837 unsigned long t
; /* t/[ps] (=1/f) */
838 int right
, hsync
, left
; /* standard timing in clock cycles, not pixel */
839 /* hsync initialized in falcon_detect() */
840 int sync_mask
; /* or-mask for hw.falcon.sync to set this clock */
841 int control_mask
; /* ditto, for hw.falcon.vid_control */
843 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
845 32000000, 31250, 18, 0, 42, 0x0, 0
847 0, 0, 18, 0, 42, 0x1, 0
850 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
851 static int vdl_prescale
[4][3] = {
852 { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
855 /* Default hsync timing [mon_type] in picoseconds */
856 static long h_syncs
[4] = { 3000000, 4875000, 4000000, 4875000 };
858 static inline int hxx_prescale(struct falcon_hw
*hw
)
860 return hw
->ste_mode
? 16
861 : vdl_prescale
[mon_type
][hw
->vid_mode
>> 2 & 0x3];
864 static int falcon_encode_fix(struct fb_fix_screeninfo
*fix
,
865 struct atafb_par
*par
)
867 strcpy(fix
->id
, "Atari Builtin");
868 fix
->smem_start
= phys_screen_base
;
869 fix
->smem_len
= screen_len
;
870 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
872 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
876 if (par
->hw
.falcon
.mono
) {
877 fix
->type
= FB_TYPE_PACKED_PIXELS
;
879 /* no smooth scrolling with longword aligned video mem */
881 } else if (par
->hw
.falcon
.f_shift
& 0x100) {
882 fix
->type
= FB_TYPE_PACKED_PIXELS
;
884 /* Is this ok or should it be DIRECTCOLOR? */
885 fix
->visual
= FB_VISUAL_TRUECOLOR
;
888 fix
->line_length
= par
->next_line
;
889 fix
->accel
= FB_ACCEL_ATARIBLITT
;
893 static int falcon_decode_var(struct fb_var_screeninfo
*var
,
894 struct atafb_par
*par
)
896 int bpp
= var
->bits_per_pixel
;
897 int xres
= var
->xres
;
898 int yres
= var
->yres
;
899 int xres_virtual
= var
->xres_virtual
;
900 int yres_virtual
= var
->yres_virtual
;
901 int left_margin
, right_margin
, hsync_len
;
902 int upper_margin
, lower_margin
, vsync_len
;
904 int interlace
= 0, doubleline
= 0;
905 struct pixel_clock
*pclock
;
906 int plen
; /* width of pixel in clock cycles */
911 int hdb_off
, hde_off
, base_off
;
912 int gstart
, gend1
, gend2
, align
;
915 Get the video params out of 'var'. If a value doesn't fit, round
916 it up, if it's too big, return EINVAL.
917 Round up in the following order: bits_per_pixel, xres, yres,
918 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
919 horizontal timing, vertical timing.
921 There is a maximum of screen resolution determined by pixelclock
922 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
923 In interlace mode this is " * " *vfmin <= pixelclock.
924 Additional constraints: hfreq.
925 Frequency range for multisync monitors is given via command line.
926 For TV and SM124 both frequencies are fixed.
928 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
929 Y % 16 == 0 to fit 8x16 font
932 Currently interlace and doubleline mode in var are ignored.
933 On SM124 and TV only the standard resolutions can be used.
936 /* Reject uninitialized mode */
937 if (!xres
|| !yres
|| !bpp
)
940 if (mon_type
== F_MON_SM
&& bpp
!= 1)
945 par
->hw
.falcon
.f_shift
= 0x400;
946 par
->hw
.falcon
.st_shift
= 0x200;
947 } else if (bpp
<= 2) {
949 par
->hw
.falcon
.f_shift
= 0x000;
950 par
->hw
.falcon
.st_shift
= 0x100;
951 } else if (bpp
<= 4) {
953 par
->hw
.falcon
.f_shift
= 0x000;
954 par
->hw
.falcon
.st_shift
= 0x000;
955 } else if (bpp
<= 8) {
957 par
->hw
.falcon
.f_shift
= 0x010;
958 } else if (bpp
<= 16) {
959 bpp
= 16; /* packed pixel mode */
960 par
->hw
.falcon
.f_shift
= 0x100; /* hicolor, no overlay */
963 par
->hw
.falcon
.bpp
= bpp
;
965 if (mon_type
== F_MON_SM
|| DontCalcRes
) {
966 /* Skip all calculations. VGA/TV/SC1224 only supported. */
967 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
969 if (bpp
> myvar
->bits_per_pixel
||
970 var
->xres
> myvar
->xres
||
971 var
->yres
> myvar
->yres
)
973 fbhw
->get_par(par
); /* Current par will be new par */
974 goto set_screen_base
; /* Don't forget this */
977 /* Only some fixed resolutions < 640x400 */
980 else if (xres
<= 640 && bpp
!= 16)
984 else if (yres
<= 240)
986 else if (yres
<= 400)
989 /* 2 planes must use STE compatibility mode */
990 par
->hw
.falcon
.ste_mode
= bpp
== 2;
991 par
->hw
.falcon
.mono
= bpp
== 1;
993 /* Total and visible scanline length must be a multiple of one longword,
994 * this and the console fontwidth yields the alignment for xres and
996 * TODO: this way "odd" fontheights are not supported
998 * Special case in STE mode: blank and graphic positions don't align,
999 * avoid trash at right margin
1001 if (par
->hw
.falcon
.ste_mode
)
1002 xres
= (xres
+ 63) & ~63;
1004 xres
= (xres
+ 31) & ~31;
1006 xres
= (xres
+ 15) & ~15;
1008 yres
= (yres
+ 15) & ~15;
1010 yres
= (yres
+ 7) & ~7;
1012 if (xres_virtual
< xres
)
1013 xres_virtual
= xres
;
1015 xres_virtual
= (xres_virtual
+ 31) & ~31;
1017 xres_virtual
= (xres_virtual
+ 15) & ~15;
1019 if (yres_virtual
<= 0)
1021 else if (yres_virtual
< yres
)
1022 yres_virtual
= yres
;
1024 /* backward bug-compatibility */
1025 if (var
->pixclock
> 1)
1028 par
->hw
.falcon
.line_width
= bpp
* xres
/ 16;
1029 par
->hw
.falcon
.line_offset
= bpp
* (xres_virtual
- xres
) / 16;
1031 /* single or double pixel width */
1032 xstretch
= (xres
< 640) ? 2 : 1;
1034 #if 0 /* SM124 supports only 640x400, this is rejected above */
1035 if (mon_type
== F_MON_SM
) {
1036 if (xres
!= 640 && yres
!= 400)
1040 /* SM124-mode is special */
1041 par
->hw
.falcon
.ste_mode
= 1;
1042 par
->hw
.falcon
.f_shift
= 0x000;
1043 par
->hw
.falcon
.st_shift
= 0x200;
1044 left_margin
= hsync_len
= 128 / plen
;
1046 /* TODO set all margins */
1049 if (mon_type
== F_MON_SC
|| mon_type
== F_MON_TV
) {
1050 plen
= 2 * xstretch
;
1051 if (var
->pixclock
> f32
.t
* plen
)
1056 if (var
->pixclock
== 0) {
1057 /* set some minimal margins which center the screen */
1060 hsync_len
= pclock
->hsync
/ plen
;
1063 vsync_len
= interlace
? 3 : 4;
1065 left_margin
= var
->left_margin
;
1066 right_margin
= var
->right_margin
;
1067 hsync_len
= var
->hsync_len
;
1068 upper_margin
= var
->upper_margin
;
1069 lower_margin
= var
->lower_margin
;
1070 vsync_len
= var
->vsync_len
;
1071 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1072 upper_margin
= (upper_margin
+ 1) / 2;
1073 lower_margin
= (lower_margin
+ 1) / 2;
1074 vsync_len
= (vsync_len
+ 1) / 2;
1075 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1081 } else { /* F_MON_VGA */
1083 xstretch
= 2; /* Double pixel width only for hicolor */
1084 /* Default values are used for vert./hor. timing if no pixelclock given. */
1085 if (var
->pixclock
== 0) {
1088 /* Choose master pixelclock depending on hor. timing */
1089 plen
= 1 * xstretch
;
1090 if ((plen
* xres
+ f25
.right
+ f25
.hsync
+ f25
.left
) *
1091 fb_info
.monspecs
.hfmin
< f25
.f
)
1093 else if ((plen
* xres
+ f32
.right
+ f32
.hsync
+
1094 f32
.left
) * fb_info
.monspecs
.hfmin
< f32
.f
)
1096 else if ((plen
* xres
+ fext
.right
+ fext
.hsync
+
1097 fext
.left
) * fb_info
.monspecs
.hfmin
< fext
.f
&&
1103 left_margin
= pclock
->left
/ plen
;
1104 right_margin
= pclock
->right
/ plen
;
1105 hsync_len
= pclock
->hsync
/ plen
;
1106 linesize
= left_margin
+ xres
+ right_margin
+ hsync_len
;
1111 /* Choose largest pixelclock <= wanted clock */
1113 unsigned long pcl
= ULONG_MAX
;
1115 for (i
= 1; i
<= 4; i
*= 2) {
1116 if (f25
.t
* i
>= var
->pixclock
&&
1121 if (f32
.t
* i
>= var
->pixclock
&&
1126 if (fext
.t
&& fext
.t
* i
>= var
->pixclock
&&
1134 plen
= pcl
/ pclock
->t
;
1136 left_margin
= var
->left_margin
;
1137 right_margin
= var
->right_margin
;
1138 hsync_len
= var
->hsync_len
;
1139 upper_margin
= var
->upper_margin
;
1140 lower_margin
= var
->lower_margin
;
1141 vsync_len
= var
->vsync_len
;
1142 /* Internal unit is [single lines per (half-)frame] */
1143 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1144 /* # lines in half frame */
1145 /* External unit is [lines per full frame] */
1146 upper_margin
= (upper_margin
+ 1) / 2;
1147 lower_margin
= (lower_margin
+ 1) / 2;
1148 vsync_len
= (vsync_len
+ 1) / 2;
1149 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1150 /* External unit is [double lines per frame] */
1156 if (pclock
== &fext
)
1157 longoffset
= 1; /* VIDEL doesn't synchronize on short offset */
1159 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1160 /* this is definitely wrong if bus clock != 32MHz */
1161 if (pclock
->f
/ plen
/ 8 * bpp
> 32000000L)
1167 /* include sync lengths in right/lower margin for all calculations */
1168 right_margin
+= hsync_len
;
1169 lower_margin
+= vsync_len
;
1171 /* ! In all calculations of margins we use # of lines in half frame
1172 * (which is a full frame in non-interlace mode), so we can switch
1173 * between interlace and non-interlace without messing around
1177 /* Set base_offset 128 and video bus width */
1178 par
->hw
.falcon
.vid_control
= mon_type
| f030_bus_width
;
1180 par
->hw
.falcon
.vid_control
|= VCO_SHORTOFFS
; /* base_offset 64 */
1181 if (var
->sync
& FB_SYNC_HOR_HIGH_ACT
)
1182 par
->hw
.falcon
.vid_control
|= VCO_HSYPOS
;
1183 if (var
->sync
& FB_SYNC_VERT_HIGH_ACT
)
1184 par
->hw
.falcon
.vid_control
|= VCO_VSYPOS
;
1186 par
->hw
.falcon
.vid_control
|= pclock
->control_mask
;
1187 /* External or internal clock */
1188 par
->hw
.falcon
.sync
= pclock
->sync_mask
| 0x2;
1189 /* Pixellength and prescale */
1190 par
->hw
.falcon
.vid_mode
= (2 / plen
) << 2;
1192 par
->hw
.falcon
.vid_mode
|= VMO_DOUBLE
;
1194 par
->hw
.falcon
.vid_mode
|= VMO_INTER
;
1196 /*********************
1197 * Horizontal timing: unit = [master clock cycles]
1198 * unit of hxx-registers: [master clock cycles * prescale]
1199 * Hxx-registers are 9 bit wide
1201 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1203 * graphic output = hdb & 0x200 ?
1204 * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1205 * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1206 * (this must be a multiple of plen*128/bpp, on VGA pixels
1207 * to the right may be cut off with a bigger right margin)
1209 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1210 * (hdb - hht - 2) * prescale + hdboff :
1211 * hdb * prescale + hdboff
1213 * end of graphics relative to start of 1st halfline =
1214 * (hde + hht + 2) * prescale + hdeoff
1215 *********************/
1216 /* Calculate VIDEL registers */
1218 prescale
= hxx_prescale(&par
->hw
.falcon
);
1219 base_off
= par
->hw
.falcon
.vid_control
& VCO_SHORTOFFS
? 64 : 128;
1221 /* Offsets depend on video mode */
1222 /* Offsets are in clock cycles, divide by prescale to
1223 * calculate hd[be]-registers
1225 if (par
->hw
.falcon
.f_shift
& 0x100) {
1228 hdb_off
= (base_off
+ 16 * plen
) + prescale
;
1231 hde_off
= ((128 / bpp
+ 2) * plen
);
1232 if (par
->hw
.falcon
.ste_mode
)
1233 hdb_off
= (64 + base_off
+ (128 / bpp
+ 2) * plen
) + prescale
;
1235 hdb_off
= (base_off
+ (128 / bpp
+ 18) * plen
) + prescale
;
1238 gstart
= (prescale
/ 2 + plen
* left_margin
) / prescale
;
1239 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1240 gend1
= gstart
+ roundup(xres
, align
) * plen
/ prescale
;
1241 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1242 gend2
= gstart
+ xres
* plen
/ prescale
;
1243 par
->HHT
= plen
* (left_margin
+ xres
+ right_margin
) /
1245 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1247 par
->HDB
= gstart
- hdb_off
/ prescale
;
1250 par
->HDB
+= par
->HHT
+ 2 + 0x200;
1251 par
->HDE
= gend1
- par
->HHT
- 2 - hde_off
/ prescale
;
1252 par
->HBB
= gend2
- par
->HHT
- 2;
1254 /* One more Videl constraint: data fetch of two lines must not overlap */
1255 if ((par
->HDB
& 0x200) && (par
->HDB
& ~0x200) - par
->HDE
<= 5) {
1256 /* if this happens increase margins, decrease hfreq. */
1259 if (hde_off
% prescale
)
1260 par
->HBB
++; /* compensate for non matching hde and hbb */
1261 par
->HSS
= par
->HHT
+ 2 - plen
* hsync_len
/ prescale
;
1262 if (par
->HSS
< par
->HBB
)
1263 par
->HSS
= par
->HBB
;
1266 /* check hor. frequency */
1267 hfreq
= pclock
->f
/ ((par
->HHT
+ 2) * prescale
* 2);
1268 if (hfreq
> fb_info
.monspecs
.hfmax
&& mon_type
!= F_MON_VGA
) {
1269 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1270 /* Too high -> enlarge margin */
1275 if (hfreq
> fb_info
.monspecs
.hfmax
|| hfreq
< fb_info
.monspecs
.hfmin
)
1279 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1280 * of the first displayed line!
1281 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1282 * non-interlace, odd in interlace mode for synchronisation.
1283 * Vxx-registers are 11 bit wide
1285 par
->VBE
= (upper_margin
* 2 + 1); /* must begin on odd halfline */
1286 par
->VDB
= par
->VBE
;
1291 par
->VDE
<<= 1; /* VDE now half lines per (half-)frame */
1292 par
->VDE
+= par
->VDB
;
1293 par
->VBB
= par
->VDE
;
1294 par
->VFT
= par
->VBB
+ (lower_margin
* 2 - 1) - 1;
1295 par
->VSS
= par
->VFT
+ 1 - (vsync_len
* 2 - 1);
1296 /* vbb,vss,vft must be even in interlace mode */
1303 /* V-frequency check, hope I didn't create any loop here. */
1304 /* Interlace and doubleline are mutually exclusive. */
1305 vfreq
= (hfreq
* 2) / (par
->VFT
+ 1);
1306 if (vfreq
> fb_info
.monspecs
.vfmax
&& !doubleline
&& !interlace
) {
1307 /* Too high -> try again with doubleline */
1310 } else if (vfreq
< fb_info
.monspecs
.vfmin
&& !interlace
&& !doubleline
) {
1311 /* Too low -> try again with interlace */
1314 } else if (vfreq
< fb_info
.monspecs
.vfmin
&& doubleline
) {
1315 /* Doubleline too low -> clear doubleline and enlarge margins */
1319 (hfreq
* 2) / (par
->VFT
+ 1 + 4 * lines
- 2 * yres
) >
1320 fb_info
.monspecs
.vfmax
;
1323 upper_margin
+= lines
;
1324 lower_margin
+= lines
;
1326 } else if (vfreq
> fb_info
.monspecs
.vfmax
&& doubleline
) {
1327 /* Doubleline too high -> enlarge margins */
1330 (hfreq
* 2) / (par
->VFT
+ 1 + 4 * lines
) >
1331 fb_info
.monspecs
.vfmax
;
1334 upper_margin
+= lines
;
1335 lower_margin
+= lines
;
1337 } else if (vfreq
> fb_info
.monspecs
.vfmax
&& interlace
) {
1338 /* Interlace, too high -> enlarge margins */
1341 (hfreq
* 2) / (par
->VFT
+ 1 + 4 * lines
) >
1342 fb_info
.monspecs
.vfmax
;
1345 upper_margin
+= lines
;
1346 lower_margin
+= lines
;
1348 } else if (vfreq
< fb_info
.monspecs
.vfmin
||
1349 vfreq
> fb_info
.monspecs
.vfmax
)
1353 linelen
= xres_virtual
* bpp
/ 8;
1354 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
1356 if (yres
* linelen
> screen_len
&& screen_len
)
1358 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
1360 par
->yres_virtual
= yres_virtual
;
1361 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
1362 par
->hw
.falcon
.xoffset
= 0;
1364 par
->next_line
= linelen
;
1369 static int falcon_encode_var(struct fb_var_screeninfo
*var
,
1370 struct atafb_par
*par
)
1372 /* !!! only for VGA !!! */
1375 int hdb_off
, hde_off
, base_off
;
1376 struct falcon_hw
*hw
= &par
->hw
.falcon
;
1378 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
1379 /* possible frequencies: 25.175 or 32MHz */
1380 var
->pixclock
= hw
->sync
& 0x1 ? fext
.t
:
1381 hw
->vid_control
& VCO_CLOCK25
? f25
.t
: f32
.t
;
1387 if (hw
->vid_control
& VCO_HSYPOS
)
1388 var
->sync
|= FB_SYNC_HOR_HIGH_ACT
;
1389 if (hw
->vid_control
& VCO_VSYPOS
)
1390 var
->sync
|= FB_SYNC_VERT_HIGH_ACT
;
1392 var
->vmode
= FB_VMODE_NONINTERLACED
;
1393 if (hw
->vid_mode
& VMO_INTER
)
1394 var
->vmode
|= FB_VMODE_INTERLACED
;
1395 if (hw
->vid_mode
& VMO_DOUBLE
)
1396 var
->vmode
|= FB_VMODE_DOUBLE
;
1398 /* visible y resolution:
1399 * Graphics display starts at line VDB and ends at line
1400 * VDE. If interlace mode off unit of VC-registers is
1401 * half lines, else lines.
1403 var
->yres
= hw
->vde
- hw
->vdb
;
1404 if (!(var
->vmode
& FB_VMODE_INTERLACED
))
1406 if (var
->vmode
& FB_VMODE_DOUBLE
)
1410 * to get bpp, we must examine f_shift and st_shift.
1411 * f_shift is valid if any of bits no. 10, 8 or 4
1412 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1413 * if bit 10 set then bit 8 and bit 4 don't care...
1414 * If all these bits are 0 get display depth from st_shift
1415 * (as for ST and STE)
1417 if (hw
->f_shift
& 0x400) /* 2 colors */
1418 var
->bits_per_pixel
= 1;
1419 else if (hw
->f_shift
& 0x100) /* hicolor */
1420 var
->bits_per_pixel
= 16;
1421 else if (hw
->f_shift
& 0x010) /* 8 bitplanes */
1422 var
->bits_per_pixel
= 8;
1423 else if (hw
->st_shift
== 0)
1424 var
->bits_per_pixel
= 4;
1425 else if (hw
->st_shift
== 0x100)
1426 var
->bits_per_pixel
= 2;
1427 else /* if (hw->st_shift == 0x200) */
1428 var
->bits_per_pixel
= 1;
1430 var
->xres
= hw
->line_width
* 16 / var
->bits_per_pixel
;
1431 var
->xres_virtual
= var
->xres
+ hw
->line_offset
* 16 / var
->bits_per_pixel
;
1433 var
->xres_virtual
+= 16;
1435 if (var
->bits_per_pixel
== 16) {
1436 var
->red
.offset
= 11;
1437 var
->red
.length
= 5;
1438 var
->red
.msb_right
= 0;
1439 var
->green
.offset
= 5;
1440 var
->green
.length
= 6;
1441 var
->green
.msb_right
= 0;
1442 var
->blue
.offset
= 0;
1443 var
->blue
.length
= 5;
1444 var
->blue
.msb_right
= 0;
1446 var
->red
.offset
= 0;
1447 var
->red
.length
= hw
->ste_mode
? 4 : 6;
1448 if (var
->red
.length
> var
->bits_per_pixel
)
1449 var
->red
.length
= var
->bits_per_pixel
;
1450 var
->red
.msb_right
= 0;
1452 var
->blue
= var
->green
= var
->red
;
1454 var
->transp
.offset
= 0;
1455 var
->transp
.length
= 0;
1456 var
->transp
.msb_right
= 0;
1458 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
1460 if (par
->yres_virtual
)
1461 var
->yres_virtual
= par
->yres_virtual
;
1463 /* yres_virtual == 0 means use maximum */
1464 var
->yres_virtual
= screen_len
/ linelen
;
1467 var
->yres_virtual
= 2 * var
->yres
;
1469 var
->yres_virtual
= var
->yres
+ hwscroll
* 16;
1471 var
->xoffset
= 0; /* TODO change this */
1474 prescale
= hxx_prescale(hw
);
1475 plen
= 4 >> (hw
->vid_mode
>> 2 & 0x3);
1476 base_off
= hw
->vid_control
& VCO_SHORTOFFS
? 64 : 128;
1477 if (hw
->f_shift
& 0x100) {
1479 hdb_off
= (base_off
+ 16 * plen
) + prescale
;
1481 hde_off
= ((128 / var
->bits_per_pixel
+ 2) * plen
);
1483 hdb_off
= (64 + base_off
+ (128 / var
->bits_per_pixel
+ 2) * plen
)
1486 hdb_off
= (base_off
+ (128 / var
->bits_per_pixel
+ 18) * plen
)
1490 /* Right margin includes hsync */
1491 var
->left_margin
= hdb_off
+ prescale
* ((hw
->hdb
& 0x1ff) -
1492 (hw
->hdb
& 0x200 ? 2 + hw
->hht
: 0));
1493 if (hw
->ste_mode
|| mon_type
!= F_MON_VGA
)
1494 var
->right_margin
= prescale
* (hw
->hht
+ 2 - hw
->hde
) - hde_off
;
1496 /* can't use this in ste_mode, because hbb is +1 off */
1497 var
->right_margin
= prescale
* (hw
->hht
+ 2 - hw
->hbb
);
1498 var
->hsync_len
= prescale
* (hw
->hht
+ 2 - hw
->hss
);
1500 /* Lower margin includes vsync */
1501 var
->upper_margin
= hw
->vdb
/ 2; /* round down to full lines */
1502 var
->lower_margin
= (hw
->vft
+ 1 - hw
->vde
+ 1) / 2; /* round up */
1503 var
->vsync_len
= (hw
->vft
+ 1 - hw
->vss
+ 1) / 2; /* round up */
1504 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1505 var
->upper_margin
*= 2;
1506 var
->lower_margin
*= 2;
1507 var
->vsync_len
*= 2;
1508 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1509 var
->upper_margin
= (var
->upper_margin
+ 1) / 2;
1510 var
->lower_margin
= (var
->lower_margin
+ 1) / 2;
1511 var
->vsync_len
= (var
->vsync_len
+ 1) / 2;
1514 var
->pixclock
*= plen
;
1515 var
->left_margin
/= plen
;
1516 var
->right_margin
/= plen
;
1517 var
->hsync_len
/= plen
;
1519 var
->right_margin
-= var
->hsync_len
;
1520 var
->lower_margin
-= var
->vsync_len
;
1523 var
->yoffset
= (par
->screen_base
- screen_base
) / linelen
;
1526 var
->nonstd
= 0; /* what is this for? */
1531 static int f_change_mode
;
1532 static struct falcon_hw f_new_mode
;
1533 static int f_pan_display
;
1535 static void falcon_get_par(struct atafb_par
*par
)
1538 struct falcon_hw
*hw
= &par
->hw
.falcon
;
1540 hw
->line_width
= shifter_f030
.scn_width
;
1541 hw
->line_offset
= shifter_f030
.off_next
;
1542 hw
->st_shift
= videl
.st_shift
& 0x300;
1543 hw
->f_shift
= videl
.f_shift
;
1544 hw
->vid_control
= videl
.control
;
1545 hw
->vid_mode
= videl
.mode
;
1546 hw
->sync
= shifter_st
.syncmode
& 0x1;
1547 hw
->xoffset
= videl
.xoffset
& 0xf;
1548 hw
->hht
= videl
.hht
;
1549 hw
->hbb
= videl
.hbb
;
1550 hw
->hbe
= videl
.hbe
;
1551 hw
->hdb
= videl
.hdb
;
1552 hw
->hde
= videl
.hde
;
1553 hw
->hss
= videl
.hss
;
1554 hw
->vft
= videl
.vft
;
1555 hw
->vbb
= videl
.vbb
;
1556 hw
->vbe
= videl
.vbe
;
1557 hw
->vdb
= videl
.vdb
;
1558 hw
->vde
= videl
.vde
;
1559 hw
->vss
= videl
.vss
;
1561 addr
= (shifter_st
.bas_hi
& 0xff) << 16 |
1562 (shifter_st
.bas_md
& 0xff) << 8 |
1563 (shifter_st
.bas_lo
& 0xff);
1564 par
->screen_base
= atari_stram_to_virt(addr
);
1566 /* derived parameters */
1567 hw
->ste_mode
= (hw
->f_shift
& 0x510) == 0 && hw
->st_shift
== 0x100;
1568 hw
->mono
= (hw
->f_shift
& 0x400) ||
1569 ((hw
->f_shift
& 0x510) == 0 && hw
->st_shift
== 0x200);
1572 static void falcon_set_par(struct atafb_par
*par
)
1576 /* only set screen_base if really necessary */
1577 if (current_par
.screen_base
!= par
->screen_base
)
1578 fbhw
->set_screen_base(par
->screen_base
);
1580 /* Don't touch any other registers if we keep the default resolution */
1584 /* Tell vbl-handler to change video mode.
1585 * We change modes only on next VBL, to avoid desynchronisation
1586 * (a shift to the right and wrap around by a random number of pixels
1587 * in all monochrome modes).
1588 * This seems to work on my Falcon.
1590 f_new_mode
= par
->hw
.falcon
;
1594 static irqreturn_t
falcon_vbl_switcher(int irq
, void *dummy
)
1596 struct falcon_hw
*hw
= &f_new_mode
;
1598 if (f_change_mode
) {
1601 if (hw
->sync
& 0x1) {
1602 /* Enable external pixelclock. This code only for ScreenWonder */
1603 *(volatile unsigned short *)0xffff9202 = 0xffbf;
1605 /* Turn off external clocks. Read sets all output bits to 1. */
1606 *(volatile unsigned short *)0xffff9202;
1608 shifter_st
.syncmode
= hw
->sync
;
1610 videl
.hht
= hw
->hht
;
1611 videl
.hbb
= hw
->hbb
;
1612 videl
.hbe
= hw
->hbe
;
1613 videl
.hdb
= hw
->hdb
;
1614 videl
.hde
= hw
->hde
;
1615 videl
.hss
= hw
->hss
;
1616 videl
.vft
= hw
->vft
;
1617 videl
.vbb
= hw
->vbb
;
1618 videl
.vbe
= hw
->vbe
;
1619 videl
.vdb
= hw
->vdb
;
1620 videl
.vde
= hw
->vde
;
1621 videl
.vss
= hw
->vss
;
1623 videl
.f_shift
= 0; /* write enables Falcon palette, 0: 4 planes */
1625 videl
.st_shift
= hw
->st_shift
; /* write enables STE palette */
1628 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1629 * Writing 0 to f_shift enables 4 plane Falcon mode but
1630 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1631 * with Falcon palette.
1634 /* now back to Falcon palette mode */
1635 videl
.f_shift
= hw
->f_shift
;
1637 /* writing to st_shift changed scn_width and vid_mode */
1638 videl
.xoffset
= hw
->xoffset
;
1639 shifter_f030
.scn_width
= hw
->line_width
;
1640 shifter_f030
.off_next
= hw
->line_offset
;
1641 videl
.control
= hw
->vid_control
;
1642 videl
.mode
= hw
->vid_mode
;
1644 if (f_pan_display
) {
1646 videl
.xoffset
= current_par
.hw
.falcon
.xoffset
;
1647 shifter_f030
.off_next
= current_par
.hw
.falcon
.line_offset
;
1652 static int falcon_pan_display(struct fb_var_screeninfo
*var
,
1653 struct fb_info
*info
)
1655 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
1658 int bpp
= info
->var
.bits_per_pixel
;
1661 var
->xoffset
= up(var
->xoffset
, 32);
1663 par
->hw
.falcon
.xoffset
= var
->xoffset
& 15;
1665 par
->hw
.falcon
.xoffset
= 0;
1666 var
->xoffset
= up(var
->xoffset
, 2);
1668 par
->hw
.falcon
.line_offset
= bpp
*
1669 (info
->var
.xres_virtual
- info
->var
.xres
) / 16;
1670 if (par
->hw
.falcon
.xoffset
)
1671 par
->hw
.falcon
.line_offset
-= bpp
;
1672 xoffset
= var
->xoffset
- par
->hw
.falcon
.xoffset
;
1674 par
->screen_base
= screen_base
+
1675 (var
->yoffset
* info
->var
.xres_virtual
+ xoffset
) * bpp
/ 8;
1676 if (fbhw
->set_screen_base
)
1677 fbhw
->set_screen_base(par
->screen_base
);
1679 return -EINVAL
; /* shouldn't happen */
1684 static int falcon_setcolreg(unsigned int regno
, unsigned int red
,
1685 unsigned int green
, unsigned int blue
,
1686 unsigned int transp
, struct fb_info
*info
)
1690 f030_col
[regno
] = (((red
& 0xfc00) << 16) |
1691 ((green
& 0xfc00) << 8) |
1692 ((blue
& 0xfc00) >> 8));
1694 shifter_tt
.color_reg
[regno
] =
1695 (((red
& 0xe000) >> 13) | ((red
& 0x1000) >> 12) << 8) |
1696 (((green
& 0xe000) >> 13) | ((green
& 0x1000) >> 12) << 4) |
1697 ((blue
& 0xe000) >> 13) | ((blue
& 0x1000) >> 12);
1698 ((u32
*)info
->pseudo_palette
)[regno
] = ((red
& 0xf800) |
1699 ((green
& 0xfc00) >> 5) |
1700 ((blue
& 0xf800) >> 11));
1705 static int falcon_blank(int blank_mode
)
1707 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1708 * so VIDEL doesn't hog the bus while saving.
1709 * (this may affect usleep()).
1711 int vdb
, vss
, hbe
, hss
;
1713 if (mon_type
== F_MON_SM
) /* this doesn't work on SM124 */
1716 vdb
= current_par
.VDB
;
1717 vss
= current_par
.VSS
;
1718 hbe
= current_par
.HBE
;
1719 hss
= current_par
.HSS
;
1721 if (blank_mode
>= 1) {
1722 /* disable graphics output (this speeds up the CPU) ... */
1723 vdb
= current_par
.VFT
+ 1;
1724 /* ... and blank all lines */
1725 hbe
= current_par
.HHT
+ 2;
1727 /* use VESA suspend modes on VGA monitors */
1728 if (mon_type
== F_MON_VGA
) {
1729 if (blank_mode
== 2 || blank_mode
== 4)
1730 vss
= current_par
.VFT
+ 1;
1731 if (blank_mode
== 3 || blank_mode
== 4)
1732 hss
= current_par
.HHT
+ 2;
1743 static int falcon_detect(void)
1745 struct atafb_par par
;
1748 /* Determine connected monitor and set monitor parameters */
1749 fhw
= *(unsigned char *)0xffff8006;
1750 mon_type
= fhw
>> 6 & 0x3;
1751 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1752 f030_bus_width
= fhw
<< 6 & 0x80;
1755 fb_info
.monspecs
.vfmin
= 70;
1756 fb_info
.monspecs
.vfmax
= 72;
1757 fb_info
.monspecs
.hfmin
= 35713;
1758 fb_info
.monspecs
.hfmax
= 35715;
1763 fb_info
.monspecs
.vfmin
= 49; /* not 50, since TOS defaults to 49.9x Hz */
1764 fb_info
.monspecs
.vfmax
= 60;
1765 fb_info
.monspecs
.hfmin
= 15620;
1766 fb_info
.monspecs
.hfmax
= 15755;
1769 /* initialize hsync-len */
1770 f25
.hsync
= h_syncs
[mon_type
] / f25
.t
;
1771 f32
.hsync
= h_syncs
[mon_type
] / f32
.t
;
1773 fext
.hsync
= h_syncs
[mon_type
] / fext
.t
;
1775 falcon_get_par(&par
);
1776 falcon_encode_var(&atafb_predefined
[0], &par
);
1778 /* Detected mode is always the "autodetect" slot */
1782 #endif /* ATAFB_FALCON */
1784 /* ------------------- ST(E) specific functions ---------------------- */
1788 static int stste_encode_fix(struct fb_fix_screeninfo
*fix
,
1789 struct atafb_par
*par
)
1793 strcpy(fix
->id
, "Atari Builtin");
1794 fix
->smem_start
= phys_screen_base
;
1795 fix
->smem_len
= screen_len
;
1796 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
1798 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
1799 mode
= par
->hw
.st
.mode
& 3;
1800 if (mode
== ST_HIGH
) {
1801 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1803 fix
->visual
= FB_VISUAL_MONO10
;
1805 if (ATARIHW_PRESENT(EXTD_SHIFTER
)) {
1813 fix
->line_length
= par
->next_line
;
1814 fix
->accel
= FB_ACCEL_ATARIBLITT
;
1818 static int stste_decode_var(struct fb_var_screeninfo
*var
,
1819 struct atafb_par
*par
)
1821 int xres
= var
->xres
;
1822 int yres
= var
->yres
;
1823 int bpp
= var
->bits_per_pixel
;
1825 int yres_virtual
= var
->yres_virtual
;
1828 if (bpp
> 1 || xres
> sttt_xres
|| yres
> st_yres
)
1830 par
->hw
.st
.mode
= ST_HIGH
;
1835 if (bpp
> 4 || xres
> sttt_xres
|| yres
> st_yres
)
1838 if (xres
> sttt_xres
/ 2 || yres
> st_yres
/ 2)
1840 par
->hw
.st
.mode
= ST_LOW
;
1841 xres
= sttt_xres
/ 2;
1844 } else if (bpp
> 1) {
1845 if (xres
> sttt_xres
|| yres
> st_yres
/ 2)
1847 par
->hw
.st
.mode
= ST_MID
;
1854 if (yres_virtual
<= 0)
1856 else if (yres_virtual
< yres
)
1857 yres_virtual
= yres
;
1858 if (var
->sync
& FB_SYNC_EXT
)
1859 par
->hw
.st
.sync
= (par
->hw
.st
.sync
& ~1) | 1;
1861 par
->hw
.st
.sync
= (par
->hw
.st
.sync
& ~1);
1862 linelen
= xres
* bpp
/ 8;
1863 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
1865 if (yres
* linelen
> screen_len
&& screen_len
)
1867 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
1869 par
->yres_virtual
= yres_virtual
;
1870 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
1871 par
->next_line
= linelen
;
1875 static int stste_encode_var(struct fb_var_screeninfo
*var
,
1876 struct atafb_par
*par
)
1879 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
1880 var
->red
.offset
= 0;
1881 var
->red
.length
= ATARIHW_PRESENT(EXTD_SHIFTER
) ? 4 : 3;
1882 var
->red
.msb_right
= 0;
1885 var
->pixclock
= 31041;
1886 var
->left_margin
= 120; /* these are incorrect */
1887 var
->right_margin
= 100;
1888 var
->upper_margin
= 8;
1889 var
->lower_margin
= 16;
1890 var
->hsync_len
= 140;
1891 var
->vsync_len
= 30;
1896 if (!(par
->hw
.st
.sync
& 1))
1899 var
->sync
= FB_SYNC_EXT
;
1901 switch (par
->hw
.st
.mode
& 3) {
1903 var
->xres
= sttt_xres
/ 2;
1904 var
->yres
= st_yres
/ 2;
1905 var
->bits_per_pixel
= 4;
1908 var
->xres
= sttt_xres
;
1909 var
->yres
= st_yres
/ 2;
1910 var
->bits_per_pixel
= 2;
1913 var
->xres
= sttt_xres
;
1914 var
->yres
= st_yres
;
1915 var
->bits_per_pixel
= 1;
1918 var
->blue
= var
->green
= var
->red
;
1919 var
->transp
.offset
= 0;
1920 var
->transp
.length
= 0;
1921 var
->transp
.msb_right
= 0;
1922 var
->xres_virtual
= sttt_xres_virtual
;
1923 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
1924 ovsc_addlen
= linelen
* (sttt_yres_virtual
- st_yres
);
1927 var
->yres_virtual
= var
->yres
;
1928 else if (screen_len
) {
1929 if (par
->yres_virtual
)
1930 var
->yres_virtual
= par
->yres_virtual
;
1932 /* yres_virtual == 0 means use maximum */
1933 var
->yres_virtual
= screen_len
/ linelen
;
1936 var
->yres_virtual
= 2 * var
->yres
;
1938 var
->yres_virtual
= var
->yres
+ hwscroll
* 16;
1942 var
->yoffset
= (par
->screen_base
- screen_base
) / linelen
;
1947 var
->vmode
= FB_VMODE_NONINTERLACED
;
1951 static void stste_get_par(struct atafb_par
*par
)
1954 par
->hw
.st
.mode
= shifter_tt
.st_shiftmode
;
1955 par
->hw
.st
.sync
= shifter_st
.syncmode
;
1956 addr
= ((shifter_st
.bas_hi
& 0xff) << 16) |
1957 ((shifter_st
.bas_md
& 0xff) << 8);
1958 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
1959 addr
|= (shifter_st
.bas_lo
& 0xff);
1960 par
->screen_base
= atari_stram_to_virt(addr
);
1963 static void stste_set_par(struct atafb_par
*par
)
1965 shifter_tt
.st_shiftmode
= par
->hw
.st
.mode
;
1966 shifter_st
.syncmode
= par
->hw
.st
.sync
;
1967 /* only set screen_base if really necessary */
1968 if (current_par
.screen_base
!= par
->screen_base
)
1969 fbhw
->set_screen_base(par
->screen_base
);
1972 static int stste_setcolreg(unsigned int regno
, unsigned int red
,
1973 unsigned int green
, unsigned int blue
,
1974 unsigned int transp
, struct fb_info
*info
)
1981 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
1982 shifter_tt
.color_reg
[regno
] =
1983 (((red
& 0xe) >> 1) | ((red
& 1) << 3) << 8) |
1984 (((green
& 0xe) >> 1) | ((green
& 1) << 3) << 4) |
1985 ((blue
& 0xe) >> 1) | ((blue
& 1) << 3);
1987 shifter_tt
.color_reg
[regno
] =
1988 ((red
& 0xe) << 7) |
1989 ((green
& 0xe) << 3) |
1990 ((blue
& 0xe) >> 1);
1994 static int stste_detect(void)
1996 struct atafb_par par
;
1998 /* Determine the connected monitor: The DMA sound must be
1999 * disabled before reading the MFP GPIP, because the Sound
2000 * Done Signal and the Monochrome Detect are XORed together!
2002 if (ATARIHW_PRESENT(PCM_8BIT
)) {
2003 tt_dmasnd
.ctrl
= DMASND_CTRL_OFF
;
2004 udelay(20); /* wait a while for things to settle down */
2006 mono_moni
= (st_mfp
.par_dt_reg
& 0x80) == 0;
2008 stste_get_par(&par
);
2009 stste_encode_var(&atafb_predefined
[0], &par
);
2011 if (!ATARIHW_PRESENT(EXTD_SHIFTER
))
2016 static void stste_set_screen_base(void *s_base
)
2019 addr
= atari_stram_to_phys(s_base
);
2020 /* Setup Screen Memory */
2021 shifter_st
.bas_hi
= (unsigned char)((addr
& 0xff0000) >> 16);
2022 shifter_st
.bas_md
= (unsigned char)((addr
& 0x00ff00) >> 8);
2023 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
2024 shifter_st
.bas_lo
= (unsigned char)(addr
& 0x0000ff);
2027 #endif /* ATAFB_STE */
2029 /* Switching the screen size should be done during vsync, otherwise
2030 * the margins may get messed up. This is a well known problem of
2031 * the ST's video system.
2033 * Unfortunately there is hardly any way to find the vsync, as the
2034 * vertical blank interrupt is no longer in time on machines with
2035 * overscan type modifications.
2037 * We can, however, use Timer B to safely detect the black shoulder,
2038 * but then we've got to guess an appropriate delay to find the vsync.
2039 * This might not work on every machine.
2041 * martin_rogge @ ki.maus.de, 8th Aug 1995
2044 #define LINE_DELAY (mono_moni ? 30 : 70)
2045 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2047 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2048 static void st_ovsc_switch(void)
2050 unsigned long flags
;
2051 register unsigned char old
, new;
2053 if (!(atari_switches
& ATARI_SWITCH_OVSC_MASK
))
2055 local_irq_save(flags
);
2057 st_mfp
.tim_ct_b
= 0x10;
2058 st_mfp
.active_edge
|= 8;
2059 st_mfp
.tim_ct_b
= 0;
2060 st_mfp
.tim_dt_b
= 0xf0;
2061 st_mfp
.tim_ct_b
= 8;
2062 while (st_mfp
.tim_dt_b
> 1) /* TOS does it this way, don't ask why */
2064 new = st_mfp
.tim_dt_b
;
2068 new = st_mfp
.tim_dt_b
;
2069 } while (old
!= new);
2070 st_mfp
.tim_ct_b
= 0x10;
2073 if (atari_switches
& ATARI_SWITCH_OVSC_IKBD
)
2074 acia
.key_ctrl
= ACIA_DIV64
| ACIA_D8N1S
| ACIA_RHTID
| ACIA_RIE
;
2075 if (atari_switches
& ATARI_SWITCH_OVSC_MIDI
)
2076 acia
.mid_ctrl
= ACIA_DIV16
| ACIA_D8N1S
| ACIA_RHTID
;
2077 if (atari_switches
& (ATARI_SWITCH_OVSC_SND6
|ATARI_SWITCH_OVSC_SND7
)) {
2078 sound_ym
.rd_data_reg_sel
= 14;
2079 sound_ym
.wd_data
= sound_ym
.rd_data_reg_sel
|
2080 ((atari_switches
& ATARI_SWITCH_OVSC_SND6
) ? 0x40:0) |
2081 ((atari_switches
& ATARI_SWITCH_OVSC_SND7
) ? 0x80:0);
2083 local_irq_restore(flags
);
2086 /* ------------------- External Video ---------------------- */
2090 static int ext_encode_fix(struct fb_fix_screeninfo
*fix
, struct atafb_par
*par
)
2092 strcpy(fix
->id
, "Unknown Extern");
2093 fix
->smem_start
= external_addr
;
2094 fix
->smem_len
= PAGE_ALIGN(external_len
);
2095 if (external_depth
== 1) {
2096 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2097 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2098 * for "normal" and "inverted", rsp., in the monochrome case */
2100 (external_pmode
== FB_TYPE_INTERLEAVED_PLANES
||
2101 external_pmode
== FB_TYPE_PACKED_PIXELS
) ?
2102 FB_VISUAL_MONO10
: FB_VISUAL_MONO01
;
2104 /* Use STATIC if we don't know how to access color registers */
2105 int visual
= external_vgaiobase
?
2106 FB_VISUAL_PSEUDOCOLOR
:
2107 FB_VISUAL_STATIC_PSEUDOCOLOR
;
2108 switch (external_pmode
) {
2109 case -1: /* truecolor */
2110 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2111 fix
->visual
= FB_VISUAL_TRUECOLOR
;
2113 case FB_TYPE_PACKED_PIXELS
:
2114 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2115 fix
->visual
= visual
;
2117 case FB_TYPE_PLANES
:
2118 fix
->type
= FB_TYPE_PLANES
;
2119 fix
->visual
= visual
;
2121 case FB_TYPE_INTERLEAVED_PLANES
:
2122 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
2124 fix
->visual
= visual
;
2131 fix
->line_length
= par
->next_line
;
2135 static int ext_decode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
2137 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
2139 if (var
->bits_per_pixel
> myvar
->bits_per_pixel
||
2140 var
->xres
> myvar
->xres
||
2141 var
->xres_virtual
> myvar
->xres_virtual
||
2142 var
->yres
> myvar
->yres
||
2147 par
->next_line
= external_xres_virtual
* external_depth
/ 8;
2151 static int ext_encode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
2153 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
2154 var
->red
.offset
= 0;
2155 var
->red
.length
= (external_pmode
== -1) ? external_depth
/ 3 :
2156 (external_vgaiobase
? external_bitspercol
: 0);
2157 var
->red
.msb_right
= 0;
2160 var
->pixclock
= 31041;
2161 var
->left_margin
= 120; /* these are surely incorrect */
2162 var
->right_margin
= 100;
2163 var
->upper_margin
= 8;
2164 var
->lower_margin
= 16;
2165 var
->hsync_len
= 140;
2166 var
->vsync_len
= 30;
2173 var
->xres
= external_xres
;
2174 var
->yres
= external_yres
;
2175 var
->xres_virtual
= external_xres_virtual
;
2176 var
->bits_per_pixel
= external_depth
;
2178 var
->blue
= var
->green
= var
->red
;
2179 var
->transp
.offset
= 0;
2180 var
->transp
.length
= 0;
2181 var
->transp
.msb_right
= 0;
2182 var
->yres_virtual
= var
->yres
;
2187 var
->vmode
= FB_VMODE_NONINTERLACED
;
2191 static void ext_get_par(struct atafb_par
*par
)
2193 par
->screen_base
= external_screen_base
;
2196 static void ext_set_par(struct atafb_par
*par
)
2200 #define OUTB(port,val) \
2201 *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2203 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2206 unsigned char tmp = INB(0x3da); \
2210 static int ext_setcolreg(unsigned int regno
, unsigned int red
,
2211 unsigned int green
, unsigned int blue
,
2212 unsigned int transp
, struct fb_info
*info
)
2214 unsigned char colmask
= (1 << external_bitspercol
) - 1;
2216 if (!external_vgaiobase
)
2222 switch (external_card_type
) {
2226 OUTB(0x3c9, red
& colmask
);
2228 OUTB(0x3c9, green
& colmask
);
2230 OUTB(0x3c9, blue
& colmask
);
2235 OUTB((MV300_reg
[regno
] << 2) + 1, red
);
2236 OUTB((MV300_reg
[regno
] << 2) + 1, green
);
2237 OUTB((MV300_reg
[regno
] << 2) + 1, blue
);
2245 static int ext_detect(void)
2247 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
2248 struct atafb_par dummy_par
;
2250 myvar
->xres
= external_xres
;
2251 myvar
->xres_virtual
= external_xres_virtual
;
2252 myvar
->yres
= external_yres
;
2253 myvar
->bits_per_pixel
= external_depth
;
2254 ext_encode_var(myvar
, &dummy_par
);
2258 #endif /* ATAFB_EXT */
2260 /* ------ This is the same for most hardware types -------- */
2262 static void set_screen_base(void *s_base
)
2266 addr
= atari_stram_to_phys(s_base
);
2267 /* Setup Screen Memory */
2268 shifter_st
.bas_hi
= (unsigned char)((addr
& 0xff0000) >> 16);
2269 shifter_st
.bas_md
= (unsigned char)((addr
& 0x00ff00) >> 8);
2270 shifter_st
.bas_lo
= (unsigned char)(addr
& 0x0000ff);
2273 static int pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2275 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
2277 if (!fbhw
->set_screen_base
||
2278 (!ATARIHW_PRESENT(EXTD_SHIFTER
) && var
->xoffset
))
2280 var
->xoffset
= up(var
->xoffset
, 16);
2281 par
->screen_base
= screen_base
+
2282 (var
->yoffset
* info
->var
.xres_virtual
+ var
->xoffset
)
2283 * info
->var
.bits_per_pixel
/ 8;
2284 fbhw
->set_screen_base(par
->screen_base
);
2288 /* ------------ Interfaces to hardware functions ------------ */
2291 static struct fb_hwswitch tt_switch
= {
2292 .detect
= tt_detect
,
2293 .encode_fix
= tt_encode_fix
,
2294 .decode_var
= tt_decode_var
,
2295 .encode_var
= tt_encode_var
,
2296 .get_par
= tt_get_par
,
2297 .set_par
= tt_set_par
,
2298 .set_screen_base
= set_screen_base
,
2299 .pan_display
= pan_display
,
2304 static struct fb_hwswitch falcon_switch
= {
2305 .detect
= falcon_detect
,
2306 .encode_fix
= falcon_encode_fix
,
2307 .decode_var
= falcon_decode_var
,
2308 .encode_var
= falcon_encode_var
,
2309 .get_par
= falcon_get_par
,
2310 .set_par
= falcon_set_par
,
2311 .set_screen_base
= set_screen_base
,
2312 .blank
= falcon_blank
,
2313 .pan_display
= falcon_pan_display
,
2318 static struct fb_hwswitch st_switch
= {
2319 .detect
= stste_detect
,
2320 .encode_fix
= stste_encode_fix
,
2321 .decode_var
= stste_decode_var
,
2322 .encode_var
= stste_encode_var
,
2323 .get_par
= stste_get_par
,
2324 .set_par
= stste_set_par
,
2325 .set_screen_base
= stste_set_screen_base
,
2326 .pan_display
= pan_display
2331 static struct fb_hwswitch ext_switch
= {
2332 .detect
= ext_detect
,
2333 .encode_fix
= ext_encode_fix
,
2334 .decode_var
= ext_decode_var
,
2335 .encode_var
= ext_encode_var
,
2336 .get_par
= ext_get_par
,
2337 .set_par
= ext_set_par
,
2341 static void ata_get_par(struct atafb_par
*par
)
2343 if (current_par_valid
)
2349 static void ata_set_par(struct atafb_par
*par
)
2353 current_par_valid
= 1;
2357 /* =========================================================== */
2358 /* ============== Hardware Independent Functions ============= */
2359 /* =========================================================== */
2361 /* used for hardware scrolling */
2363 static int do_fb_set_var(struct fb_var_screeninfo
*var
, int isactive
)
2366 struct atafb_par par
;
2368 err
= fbhw
->decode_var(var
, &par
);
2371 activate
= var
->activate
;
2372 if (((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) && isactive
)
2374 fbhw
->encode_var(var
, &par
);
2375 var
->activate
= activate
;
2379 /* fbhw->encode_fix() must be called with fb_info->mm_lock held
2380 * if it is called after the register_framebuffer() - not a case here
2382 static int atafb_get_fix(struct fb_fix_screeninfo
*fix
, struct fb_info
*info
)
2384 struct atafb_par par
;
2386 // Get fix directly (case con == -1 before)??
2387 err
= fbhw
->decode_var(&info
->var
, &par
);
2390 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
2391 err
= fbhw
->encode_fix(fix
, &par
);
2395 static int atafb_get_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2397 struct atafb_par par
;
2400 fbhw
->encode_var(var
, &par
);
2405 // No longer called by fbcon!
2406 // Still called by set_var internally
2408 static void atafb_set_disp(struct fb_info
*info
)
2410 atafb_get_var(&info
->var
, info
);
2411 atafb_get_fix(&info
->fix
, info
);
2413 /* Note: smem_start derives from phys_screen_base, not screen_base! */
2414 info
->screen_base
= (external_addr
? external_screen_base
:
2415 atari_stram_to_virt(info
->fix
.smem_start
));
2418 static int atafb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
2419 u_int transp
, struct fb_info
*info
)
2425 return info
->fbops
->fb_setcolreg(regno
, red
, green
, blue
, transp
, info
);
2429 atafb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2431 int xoffset
= var
->xoffset
;
2432 int yoffset
= var
->yoffset
;
2435 if (var
->vmode
& FB_VMODE_YWRAP
) {
2436 if (yoffset
< 0 || yoffset
>= info
->var
.yres_virtual
|| xoffset
)
2439 if (xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
2440 yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
2444 if (fbhw
->pan_display
) {
2445 err
= fbhw
->pan_display(var
, info
);
2451 info
->var
.xoffset
= xoffset
;
2452 info
->var
.yoffset
= yoffset
;
2454 if (var
->vmode
& FB_VMODE_YWRAP
)
2455 info
->var
.vmode
|= FB_VMODE_YWRAP
;
2457 info
->var
.vmode
&= ~FB_VMODE_YWRAP
;
2463 * generic drawing routines; imageblit needs updating for image depth > 1
2466 #if BITS_PER_LONG == 32
2467 #define BYTES_PER_LONG 4
2468 #define SHIFT_PER_LONG 5
2469 #elif BITS_PER_LONG == 64
2470 #define BYTES_PER_LONG 8
2471 #define SHIFT_PER_LONG 6
2473 #define Please update me
2477 static void atafb_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
2479 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
2483 if (!rect
->width
|| !rect
->height
)
2487 if (info
->var
.bits_per_pixel
== 16) {
2488 cfb_fillrect(info
, rect
);
2494 * We could use hardware clipping but on many cards you get around
2495 * hardware clipping by writing to framebuffer directly.
2497 x2
= rect
->dx
+ rect
->width
;
2498 y2
= rect
->dy
+ rect
->height
;
2499 x2
= x2
< info
->var
.xres_virtual
? x2
: info
->var
.xres_virtual
;
2500 y2
= y2
< info
->var
.yres_virtual
? y2
: info
->var
.yres_virtual
;
2501 width
= x2
- rect
->dx
;
2502 height
= y2
- rect
->dy
;
2504 if (info
->var
.bits_per_pixel
== 1)
2505 atafb_mfb_fillrect(info
, par
->next_line
, rect
->color
,
2506 rect
->dy
, rect
->dx
, height
, width
);
2507 else if (info
->var
.bits_per_pixel
== 2)
2508 atafb_iplan2p2_fillrect(info
, par
->next_line
, rect
->color
,
2509 rect
->dy
, rect
->dx
, height
, width
);
2510 else if (info
->var
.bits_per_pixel
== 4)
2511 atafb_iplan2p4_fillrect(info
, par
->next_line
, rect
->color
,
2512 rect
->dy
, rect
->dx
, height
, width
);
2514 atafb_iplan2p8_fillrect(info
, par
->next_line
, rect
->color
,
2515 rect
->dy
, rect
->dx
, height
, width
);
2520 static void atafb_copyarea(struct fb_info
*info
, const struct fb_copyarea
*area
)
2522 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
2524 u32 dx
, dy
, sx
, sy
, width
, height
;
2528 if (info
->var
.bits_per_pixel
== 16) {
2529 cfb_copyarea(info
, area
);
2534 /* clip the destination */
2535 x2
= area
->dx
+ area
->width
;
2536 y2
= area
->dy
+ area
->height
;
2537 dx
= area
->dx
> 0 ? area
->dx
: 0;
2538 dy
= area
->dy
> 0 ? area
->dy
: 0;
2539 x2
= x2
< info
->var
.xres_virtual
? x2
: info
->var
.xres_virtual
;
2540 y2
= y2
< info
->var
.yres_virtual
? y2
: info
->var
.yres_virtual
;
2544 if (area
->sx
+ dx
< area
->dx
|| area
->sy
+ dy
< area
->dy
)
2548 sx
= area
->sx
+ (dx
- area
->dx
);
2549 sy
= area
->sy
+ (dy
- area
->dy
);
2551 /* the source must be completely inside the virtual screen */
2552 if (sx
+ width
> info
->var
.xres_virtual
||
2553 sy
+ height
> info
->var
.yres_virtual
)
2556 if (dy
> sy
|| (dy
== sy
&& dx
> sx
)) {
2562 if (info
->var
.bits_per_pixel
== 1)
2563 atafb_mfb_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2564 else if (info
->var
.bits_per_pixel
== 2)
2565 atafb_iplan2p2_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2566 else if (info
->var
.bits_per_pixel
== 4)
2567 atafb_iplan2p4_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2569 atafb_iplan2p8_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2574 static void atafb_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
2576 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
2581 u32 dx
, dy
, width
, height
, pitch
;
2584 if (info
->var
.bits_per_pixel
== 16) {
2585 cfb_imageblit(info
, image
);
2591 * We could use hardware clipping but on many cards you get around
2592 * hardware clipping by writing to framebuffer directly like we are
2595 x2
= image
->dx
+ image
->width
;
2596 y2
= image
->dy
+ image
->height
;
2599 x2
= x2
< info
->var
.xres_virtual
? x2
: info
->var
.xres_virtual
;
2600 y2
= y2
< info
->var
.yres_virtual
? y2
: info
->var
.yres_virtual
;
2604 if (image
->depth
== 1) {
2605 // used for font data
2606 dst
= (unsigned long *)
2607 ((unsigned long)info
->screen_base
& ~(BYTES_PER_LONG
- 1));
2608 dst_idx
= ((unsigned long)info
->screen_base
& (BYTES_PER_LONG
- 1)) * 8;
2609 dst_idx
+= dy
* par
->next_line
* 8 + dx
;
2611 pitch
= (image
->width
+ 7) / 8;
2614 if (info
->var
.bits_per_pixel
== 1)
2615 atafb_mfb_linefill(info
, par
->next_line
,
2617 image
->bg_color
, image
->fg_color
);
2618 else if (info
->var
.bits_per_pixel
== 2)
2619 atafb_iplan2p2_linefill(info
, par
->next_line
,
2621 image
->bg_color
, image
->fg_color
);
2622 else if (info
->var
.bits_per_pixel
== 4)
2623 atafb_iplan2p4_linefill(info
, par
->next_line
,
2625 image
->bg_color
, image
->fg_color
);
2627 atafb_iplan2p8_linefill(info
, par
->next_line
,
2629 image
->bg_color
, image
->fg_color
);
2634 c2p_iplan2(info
->screen_base
, image
->data
, dx
, dy
, width
,
2635 height
, par
->next_line
, image
->width
,
2636 info
->var
.bits_per_pixel
);
2641 atafb_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
2644 #ifdef FBCMD_GET_CURRENTPAR
2645 case FBCMD_GET_CURRENTPAR
:
2646 if (copy_to_user((void *)arg
, (void *)¤t_par
,
2647 sizeof(struct atafb_par
)))
2651 #ifdef FBCMD_SET_CURRENTPAR
2652 case FBCMD_SET_CURRENTPAR
:
2653 if (copy_from_user((void *)¤t_par
, (void *)arg
,
2654 sizeof(struct atafb_par
)))
2656 ata_set_par(¤t_par
);
2663 /* (un)blank/poweroff
2670 static int atafb_blank(int blank
, struct fb_info
*info
)
2672 unsigned short black
[16];
2673 struct fb_cmap cmap
;
2674 if (fbhw
->blank
&& !fbhw
->blank(blank
))
2677 memset(black
, 0, 16 * sizeof(unsigned short));
2684 fb_set_cmap(&cmap
, info
);
2688 do_install_cmap(info
);
2694 * New fbcon interface ...
2697 /* check var by decoding var into hw par, rounding if necessary,
2698 * then encoding hw par back into new, validated var */
2699 static int atafb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2702 struct atafb_par par
;
2704 /* Validate wanted screen parameters */
2705 // if ((err = ata_decode_var(var, &par)))
2706 err
= fbhw
->decode_var(var
, &par
);
2710 /* Encode (possibly rounded) screen parameters */
2711 fbhw
->encode_var(var
, &par
);
2715 /* actually set hw par by decoding var, then setting hardware from
2716 * hw par just decoded */
2717 static int atafb_set_par(struct fb_info
*info
)
2719 struct atafb_par
*par
= (struct atafb_par
*)info
->par
;
2721 /* Decode wanted screen parameters */
2722 fbhw
->decode_var(&info
->var
, par
);
2723 mutex_lock(&info
->mm_lock
);
2724 fbhw
->encode_fix(&info
->fix
, par
);
2725 mutex_unlock(&info
->mm_lock
);
2727 /* Set new videomode */
2734 static struct fb_ops atafb_ops
= {
2735 .owner
= THIS_MODULE
,
2736 .fb_check_var
= atafb_check_var
,
2737 .fb_set_par
= atafb_set_par
,
2738 .fb_setcolreg
= atafb_setcolreg
,
2739 .fb_blank
= atafb_blank
,
2740 .fb_pan_display
= atafb_pan_display
,
2741 .fb_fillrect
= atafb_fillrect
,
2742 .fb_copyarea
= atafb_copyarea
,
2743 .fb_imageblit
= atafb_imageblit
,
2744 .fb_ioctl
= atafb_ioctl
,
2747 static void check_default_par(int detected_mode
)
2749 char default_name
[10];
2751 struct fb_var_screeninfo var
;
2752 unsigned long min_mem
;
2754 /* First try the user supplied mode */
2756 var
= atafb_predefined
[default_par
- 1];
2757 var
.activate
= FB_ACTIVATE_TEST
;
2758 if (do_fb_set_var(&var
, 1))
2759 default_par
= 0; /* failed */
2761 /* Next is the autodetected one */
2763 var
= atafb_predefined
[detected_mode
- 1]; /* autodetect */
2764 var
.activate
= FB_ACTIVATE_TEST
;
2765 if (!do_fb_set_var(&var
, 1))
2766 default_par
= detected_mode
;
2768 /* If that also failed, try some default modes... */
2770 /* try default1, default2... */
2771 for (i
= 1; i
< 10; i
++) {
2772 sprintf(default_name
,"default%d", i
);
2773 default_par
= get_video_mode(default_name
);
2775 panic("can't set default video mode");
2776 var
= atafb_predefined
[default_par
- 1];
2777 var
.activate
= FB_ACTIVATE_TEST
;
2778 if (!do_fb_set_var(&var
,1))
2782 min_mem
= var
.xres_virtual
* var
.yres_virtual
* var
.bits_per_pixel
/ 8;
2783 if (default_mem_req
< min_mem
)
2784 default_mem_req
= min_mem
;
2788 static void __init
atafb_setup_ext(char *spec
)
2790 int xres
, xres_virtual
, yres
, depth
, planes
;
2791 unsigned long addr
, len
;
2794 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2796 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2797 * [;<xres-virtual>]]]]]
2800 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2802 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2804 p
= strsep(&spec
, ";");
2807 xres_virtual
= xres
= simple_strtoul(p
, NULL
, 10);
2811 p
= strsep(&spec
, ";");
2814 yres
= simple_strtoul(p
, NULL
, 10);
2818 p
= strsep(&spec
, ";");
2821 depth
= simple_strtoul(p
, NULL
, 10);
2822 if (depth
!= 1 && depth
!= 2 && depth
!= 4 && depth
!= 8 &&
2823 depth
!= 16 && depth
!= 24)
2826 p
= strsep(&spec
, ";");
2830 planes
= FB_TYPE_INTERLEAVED_PLANES
;
2832 planes
= FB_TYPE_PACKED_PIXELS
;
2834 planes
= FB_TYPE_PLANES
;
2836 planes
= -1; /* true color */
2840 p
= strsep(&spec
, ";");
2843 addr
= simple_strtoul(p
, NULL
, 0);
2845 p
= strsep(&spec
, ";");
2847 len
= xres
* yres
* depth
/ 8;
2849 len
= simple_strtoul(p
, NULL
, 0);
2851 p
= strsep(&spec
, ";");
2853 external_vgaiobase
= simple_strtoul(p
, NULL
, 0);
2855 p
= strsep(&spec
, ";");
2857 external_bitspercol
= simple_strtoul(p
, NULL
, 0);
2858 if (external_bitspercol
> 8)
2859 external_bitspercol
= 8;
2860 else if (external_bitspercol
< 1)
2861 external_bitspercol
= 1;
2864 p
= strsep(&spec
, ";");
2866 if (!strcmp(p
, "vga"))
2867 external_card_type
= IS_VGA
;
2868 if (!strcmp(p
, "mv300"))
2869 external_card_type
= IS_MV300
;
2872 p
= strsep(&spec
, ";");
2874 xres_virtual
= simple_strtoul(p
, NULL
, 10);
2875 if (xres_virtual
< xres
)
2876 xres_virtual
= xres
;
2877 if (xres_virtual
* yres
* depth
/ 8 > len
)
2878 len
= xres_virtual
* yres
* depth
/ 8;
2881 external_xres
= xres
;
2882 external_xres_virtual
= xres_virtual
;
2883 external_yres
= yres
;
2884 external_depth
= depth
;
2885 external_pmode
= planes
;
2886 external_addr
= addr
;
2889 if (external_card_type
== IS_MV300
) {
2890 switch (external_depth
) {
2892 MV300_reg
= MV300_reg_1bit
;
2895 MV300_reg
= MV300_reg_4bit
;
2898 MV300_reg
= MV300_reg_8bit
;
2903 #endif /* ATAFB_EXT */
2905 static void __init
atafb_setup_int(char *spec
)
2907 /* Format to config extended internal video hardware like OverScan:
2908 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2910 * <xres>: x-resolution
2911 * <yres>: y-resolution
2912 * The following are only needed if you have an overscan which
2913 * needs a black border:
2914 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2915 * <yres_max>: max. number of lines your OverScan hardware would allow
2916 * <offset>: Offset from physical beginning to visible beginning
2917 * of screen in bytes
2922 if (!(p
= strsep(&spec
, ";")) || !*p
)
2924 xres
= simple_strtoul(p
, NULL
, 10);
2925 if (!(p
= strsep(&spec
, ";")) || !*p
)
2928 tt_yres
= st_yres
= simple_strtoul(p
, NULL
, 10);
2929 if ((p
= strsep(&spec
, ";")) && *p
)
2930 sttt_xres_virtual
= simple_strtoul(p
, NULL
, 10);
2931 if ((p
= strsep(&spec
, ";")) && *p
)
2932 sttt_yres_virtual
= simple_strtoul(p
, NULL
, 0);
2933 if ((p
= strsep(&spec
, ";")) && *p
)
2934 ovsc_offset
= simple_strtoul(p
, NULL
, 0);
2936 if (ovsc_offset
|| (sttt_yres_virtual
!= st_yres
))
2941 static void __init
atafb_setup_mcap(char *spec
)
2944 int vmin
, vmax
, hmin
, hmax
;
2946 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2947 * <V*> vertical freq. in Hz
2948 * <H*> horizontal freq. in kHz
2950 if (!(p
= strsep(&spec
, ";")) || !*p
)
2952 vmin
= simple_strtoul(p
, NULL
, 10);
2955 if (!(p
= strsep(&spec
, ";")) || !*p
)
2957 vmax
= simple_strtoul(p
, NULL
, 10);
2958 if (vmax
<= 0 || vmax
<= vmin
)
2960 if (!(p
= strsep(&spec
, ";")) || !*p
)
2962 hmin
= 1000 * simple_strtoul(p
, NULL
, 10);
2965 if (!(p
= strsep(&spec
, "")) || !*p
)
2967 hmax
= 1000 * simple_strtoul(p
, NULL
, 10);
2968 if (hmax
<= 0 || hmax
<= hmin
)
2971 fb_info
.monspecs
.vfmin
= vmin
;
2972 fb_info
.monspecs
.vfmax
= vmax
;
2973 fb_info
.monspecs
.hfmin
= hmin
;
2974 fb_info
.monspecs
.hfmax
= hmax
;
2976 #endif /* ATAFB_FALCON */
2978 static void __init
atafb_setup_user(char *spec
)
2980 /* Format of user defined video mode is: <xres>;<yres>;<depth>
2983 int xres
, yres
, depth
, temp
;
2985 p
= strsep(&spec
, ";");
2988 xres
= simple_strtoul(p
, NULL
, 10);
2989 p
= strsep(&spec
, ";");
2992 yres
= simple_strtoul(p
, NULL
, 10);
2993 p
= strsep(&spec
, "");
2996 depth
= simple_strtoul(p
, NULL
, 10);
2997 temp
= get_video_mode("user0");
3000 atafb_predefined
[default_par
- 1].xres
= xres
;
3001 atafb_predefined
[default_par
- 1].yres
= yres
;
3002 atafb_predefined
[default_par
- 1].bits_per_pixel
= depth
;
3006 int __init
atafb_setup(char *options
)
3011 if (!options
|| !*options
)
3014 while ((this_opt
= strsep(&options
, ",")) != NULL
) {
3017 if ((temp
= get_video_mode(this_opt
))) {
3019 mode_option
= this_opt
;
3020 } else if (!strcmp(this_opt
, "inverse"))
3022 else if (!strncmp(this_opt
, "hwscroll_", 9)) {
3023 hwscroll
= simple_strtoul(this_opt
+ 9, NULL
, 10);
3030 else if (!strcmp(this_opt
, "mv300")) {
3031 external_bitspercol
= 8;
3032 external_card_type
= IS_MV300
;
3033 } else if (!strncmp(this_opt
, "external:", 9))
3034 atafb_setup_ext(this_opt
+ 9);
3036 else if (!strncmp(this_opt
, "internal:", 9))
3037 atafb_setup_int(this_opt
+ 9);
3039 else if (!strncmp(this_opt
, "eclock:", 7)) {
3040 fext
.f
= simple_strtoul(this_opt
+ 7, NULL
, 10);
3041 /* external pixelclock in kHz --> ps */
3042 fext
.t
= 1000000000 / fext
.f
;
3044 } else if (!strncmp(this_opt
, "monitorcap:", 11))
3045 atafb_setup_mcap(this_opt
+ 11);
3047 else if (!strcmp(this_opt
, "keep"))
3049 else if (!strncmp(this_opt
, "R", 1))
3050 atafb_setup_user(this_opt
+ 1);
3055 static int __init
atafb_probe(struct platform_device
*pdev
)
3057 int pad
, detected_mode
, error
;
3058 unsigned int defmode
= 0;
3059 unsigned long mem_req
;
3060 char *option
= NULL
;
3062 if (fb_get_options("atafb", &option
))
3064 atafb_setup(option
);
3065 dev_dbg(&pdev
->dev
, "%s: start\n", __func__
);
3069 if (external_addr
) {
3070 dev_dbg(&pdev
->dev
, "initializing external hw\n");
3072 atafb_ops
.fb_setcolreg
= &ext_setcolreg
;
3073 defmode
= DEFMODE_EXT
;
3078 if (ATARIHW_PRESENT(TT_SHIFTER
)) {
3079 dev_dbg(&pdev
->dev
, "initializing TT hw\n");
3081 atafb_ops
.fb_setcolreg
= &tt_setcolreg
;
3082 defmode
= DEFMODE_TT
;
3087 if (ATARIHW_PRESENT(VIDEL_SHIFTER
)) {
3088 dev_dbg(&pdev
->dev
, "initializing Falcon hw\n");
3089 fbhw
= &falcon_switch
;
3090 atafb_ops
.fb_setcolreg
= &falcon_setcolreg
;
3091 error
= request_irq(IRQ_AUTO_4
, falcon_vbl_switcher
, 0,
3092 "framebuffer:modeswitch",
3093 falcon_vbl_switcher
);
3096 defmode
= DEFMODE_F30
;
3101 if (ATARIHW_PRESENT(STND_SHIFTER
) ||
3102 ATARIHW_PRESENT(EXTD_SHIFTER
)) {
3103 dev_dbg(&pdev
->dev
, "initializing ST/E hw\n");
3105 atafb_ops
.fb_setcolreg
= &stste_setcolreg
;
3106 defmode
= DEFMODE_STE
;
3110 atafb_ops
.fb_setcolreg
= &stste_setcolreg
;
3111 dev_warn(&pdev
->dev
,
3112 "Cannot determine video hardware; defaulting to ST(e)\n");
3113 #else /* ATAFB_STE */
3114 /* no default driver included */
3115 /* Nobody will ever see this message :-) */
3116 panic("Cannot initialize video hardware");
3120 /* Multisync monitor capabilities */
3121 /* Atari-TOS defaults if no boot option present */
3122 if (fb_info
.monspecs
.hfmin
== 0) {
3123 fb_info
.monspecs
.hfmin
= 31000;
3124 fb_info
.monspecs
.hfmax
= 32000;
3125 fb_info
.monspecs
.vfmin
= 58;
3126 fb_info
.monspecs
.vfmax
= 62;
3129 detected_mode
= fbhw
->detect();
3130 check_default_par(detected_mode
);
3132 if (!external_addr
) {
3133 #endif /* ATAFB_EXT */
3134 mem_req
= default_mem_req
+ ovsc_offset
+ ovsc_addlen
;
3135 mem_req
= PAGE_ALIGN(mem_req
) + PAGE_SIZE
;
3136 screen_base
= atari_stram_alloc(mem_req
, "atafb");
3138 panic("Cannot allocate screen memory");
3139 memset(screen_base
, 0, mem_req
);
3140 pad
= -(unsigned long)screen_base
& (PAGE_SIZE
- 1);
3142 phys_screen_base
= atari_stram_to_phys(screen_base
+ ovsc_offset
);
3143 screen_len
= (mem_req
- pad
- ovsc_offset
) & PAGE_MASK
;
3145 if (CPU_IS_040_OR_060
) {
3146 /* On a '040+, the cache mode of video RAM must be set to
3147 * write-through also for internal video hardware! */
3148 cache_push(atari_stram_to_phys(screen_base
), screen_len
);
3149 kernel_set_cachemode(screen_base
, screen_len
,
3150 IOMAP_WRITETHROUGH
);
3152 dev_info(&pdev
->dev
, "phys_screen_base %lx screen_len %d\n",
3153 phys_screen_base
, screen_len
);
3156 /* Map the video memory (physical address given) to somewhere
3157 * in the kernel address space.
3159 external_screen_base
= ioremap_wt(external_addr
, external_len
);
3160 if (external_vgaiobase
)
3161 external_vgaiobase
=
3162 (unsigned long)ioremap(external_vgaiobase
, 0x10000);
3163 screen_base
= external_screen_base
;
3164 phys_screen_base
= external_addr
;
3165 screen_len
= external_len
& PAGE_MASK
;
3166 memset (screen_base
, 0, external_len
);
3168 #endif /* ATAFB_EXT */
3170 // strcpy(fb_info.mode->name, "Atari Builtin ");
3171 fb_info
.fbops
= &atafb_ops
;
3172 // try to set default (detected; requested) var
3173 do_fb_set_var(&atafb_predefined
[default_par
- 1], 1);
3174 // reads hw state into current par, which may not be sane yet
3175 ata_get_par(¤t_par
);
3176 fb_info
.par
= ¤t_par
;
3177 // tries to read from HW which may not be initialized yet
3178 // so set sane var first, then call atafb_set_par
3179 atafb_get_var(&fb_info
.var
, &fb_info
);
3182 fb_info
.pseudo_palette
= current_par
.hw
.falcon
.pseudo_palette
;
3184 fb_info
.flags
= FBINFO_FLAG_DEFAULT
;
3186 if (!fb_find_mode(&fb_info
.var
, &fb_info
, mode_option
, atafb_modedb
,
3187 NUM_TOTAL_MODES
, &atafb_modedb
[defmode
],
3188 fb_info
.var
.bits_per_pixel
)) {
3192 fb_videomode_to_modelist(atafb_modedb
, NUM_TOTAL_MODES
,
3195 atafb_set_disp(&fb_info
);
3197 fb_alloc_cmap(&(fb_info
.cmap
), 1 << fb_info
.var
.bits_per_pixel
, 0);
3200 dev_info(&pdev
->dev
, "Determined %dx%d, depth %d\n", fb_info
.var
.xres
,
3201 fb_info
.var
.yres
, fb_info
.var
.bits_per_pixel
);
3202 if ((fb_info
.var
.xres
!= fb_info
.var
.xres_virtual
) ||
3203 (fb_info
.var
.yres
!= fb_info
.var
.yres_virtual
))
3204 dev_info(&pdev
->dev
, " virtual %dx%d\n",
3205 fb_info
.var
.xres_virtual
, fb_info
.var
.yres_virtual
);
3207 if (register_framebuffer(&fb_info
) < 0) {
3209 if (external_addr
) {
3210 iounmap(external_screen_base
);
3213 if (external_vgaiobase
) {
3214 iounmap((void*)external_vgaiobase
);
3215 external_vgaiobase
= 0;
3221 fb_info(&fb_info
, "frame buffer device, using %dK of video memory\n",
3224 /* TODO: This driver cannot be unloaded yet */
3228 static void atafb_shutdown(struct platform_device
*pdev
)
3230 /* Unblank before kexec */
3235 static struct platform_driver atafb_driver
= {
3236 .shutdown
= atafb_shutdown
,
3242 static int __init
atafb_init(void)
3244 struct platform_device
*pdev
;
3249 pdev
= platform_device_register_simple("atafb", -1, NULL
, 0);
3251 return PTR_ERR(pdev
);
3253 return platform_driver_probe(&atafb_driver
, atafb_probe
);
3256 device_initcall(atafb_init
);