2 * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
4 * Copyright (C) 1994 Martin Schaller & Roman Hodek
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
11 * - 03 Jan 95: Original version by Martin Schaller: The TT driver and
12 * all the device independent stuff
13 * - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
14 * and wrote the Falcon, ST(E), and External drivers
15 * based on the original TT driver.
16 * - 07 May 95: Martin: Added colormap operations for the external driver
17 * - 21 May 95: Martin: Added support for overscan
18 * Andreas: some bug fixes for this
19 * - Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
20 * Programmable Falcon video modes
21 * (thanks to Christian Cartus for documentation
22 * of VIDEL registers).
23 * - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
24 * on minor 24...31. "user0" may be set on commandline by
25 * "R<x>;<y>;<depth>". (Makes sense only on Falcon)
26 * Video mode switch on Falcon now done at next VBL interrupt
27 * to avoid the annoying right shift of the screen.
28 * - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
29 * The external-part is legacy, therefore hardware-specific
30 * functions like panning/hardwarescrolling/blanking isn't
32 * - 29 Sep 97: Juergen: added Romans suggestion for pan_display
33 * (var->xoffset was changed even if no set_screen_base avail.)
34 * - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
35 * we know how to set the colors
36 * ext_*palette: read from ext_colors (former MV300_colors)
37 * write to ext_colors and RAMDAC
40 * - For the Falcon it is not possible to set random video modes on
41 * SM124 and SC/TV, only the bootup resolution is supported.
50 #include <linux/kernel.h>
51 #include <linux/errno.h>
52 #include <linux/string.h>
54 #include <linux/delay.h>
55 #include <linux/init.h>
56 #include <linux/interrupt.h>
57 #include <linux/platform_device.h>
59 #include <asm/setup.h>
60 #include <linux/uaccess.h>
64 #include <asm/atarihw.h>
65 #include <asm/atariints.h>
66 #include <asm/atari_stram.h>
69 #include <asm/atarikb.h>
74 #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
75 #define SWITCH_SND6 0x40
76 #define SWITCH_SND7 0x80
77 #define SWITCH_NONE 0x00
80 static int default_par
; /* default resolution (0=none) */
82 static unsigned long default_mem_req
;
84 static int hwscroll
= -1;
86 static int use_hwscroll
= 1;
88 static int sttt_xres
= 640, st_yres
= 400, tt_yres
= 480;
89 static int sttt_xres_virtual
= 640, sttt_yres_virtual
= 400;
90 static int ovsc_offset
, ovsc_addlen
;
93 * Hardware parameters for current mode
96 static struct atafb_par
{
100 #if defined ATAFB_TT || defined ATAFB_STE
109 /* Here are fields for storing a video mode, as direct
110 * parameters for the hardware.
120 short hht
, hbb
, hbe
, hdb
, hde
, hss
;
121 short vft
, vbb
, vbe
, vdb
, vde
, vss
;
122 /* auxiliary information */
126 u32 pseudo_palette
[16];
129 /* Nothing needed for external mode */
133 /* Don't calculate an own resolution, and thus don't change the one found when
134 * booting (currently used for the Falcon to keep settings for internal video
135 * hardware extensions (e.g. ScreenBlaster) */
136 static int DontCalcRes
= 0;
139 #define HHT hw.falcon.hht
140 #define HBB hw.falcon.hbb
141 #define HBE hw.falcon.hbe
142 #define HDB hw.falcon.hdb
143 #define HDE hw.falcon.hde
144 #define HSS hw.falcon.hss
145 #define VFT hw.falcon.vft
146 #define VBB hw.falcon.vbb
147 #define VBE hw.falcon.vbe
148 #define VDB hw.falcon.vdb
149 #define VDE hw.falcon.vde
150 #define VSS hw.falcon.vss
151 #define VCO_CLOCK25 0x04
152 #define VCO_CSYPOS 0x10
153 #define VCO_VSYPOS 0x20
154 #define VCO_HSYPOS 0x40
155 #define VCO_SHORTOFFS 0x100
156 #define VMO_DOUBLE 0x01
157 #define VMO_INTER 0x02
158 #define VMO_PREMASK 0x0c
161 static struct fb_info fb_info
= {
164 .visual
= FB_VISUAL_PSEUDOCOLOR
,
165 .accel
= FB_ACCEL_NONE
,
169 static void *screen_base
; /* base address of screen */
170 static unsigned long phys_screen_base
; /* (only for Overscan) */
172 static int screen_len
;
174 static int current_par_valid
;
176 static int mono_moni
;
181 /* external video handling */
182 static unsigned int external_xres
;
183 static unsigned int external_xres_virtual
;
184 static unsigned int external_yres
;
187 * not needed - atafb will never support panning/hardwarescroll with external
188 * static unsigned int external_yres_virtual;
190 static unsigned int external_depth
;
191 static int external_pmode
;
192 static void *external_screen_base
;
193 static unsigned long external_addr
;
194 static unsigned long external_len
;
195 static unsigned long external_vgaiobase
;
196 static unsigned int external_bitspercol
= 6;
199 * JOE <joe@amber.dinoco.de>:
200 * added card type for external driver, is only needed for
203 enum cardtype
{ IS_VGA
, IS_MV300
};
204 static enum cardtype external_card_type
= IS_VGA
;
207 * The MV300 mixes the color registers. So we need an array of munged
208 * indices in order to access the correct reg.
210 static int MV300_reg_1bit
[2] = {
213 static int MV300_reg_4bit
[16] = {
214 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
216 static int MV300_reg_8bit
[256] = {
217 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
218 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
219 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
220 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
221 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
222 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
223 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
224 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
225 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
226 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
227 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
228 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
229 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
230 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
231 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
232 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
235 static int *MV300_reg
= MV300_reg_8bit
;
236 #endif /* ATAFB_EXT */
241 * * open/release and usage marking
242 * struct module *owner;
243 * int (*fb_open)(struct fb_info *info, int user);
244 * int (*fb_release)(struct fb_info *info, int user);
246 * * For framebuffers with strange non linear layouts or that do not
247 * * work with normal memory mapped access
248 * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
249 * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
251 * * checks var and eventually tweaks it to something supported,
252 * * DOES NOT MODIFY PAR *
253 * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
255 * * set the video mode according to info->var *
256 * int (*fb_set_par)(struct fb_info *info);
258 * * set color register *
259 * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
260 * unsigned int blue, unsigned int transp, struct fb_info *info);
262 * * set color registers in batch *
263 * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
266 * int (*fb_blank)(int blank, struct fb_info *info);
269 * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
271 * *** The meat of the drawing engine ***
272 * * Draws a rectangle *
273 * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
274 * * Copy data from area to another *
275 * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
276 * * Draws a image to the display *
277 * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
280 * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
282 * * wait for blit idle, optional *
283 * int (*fb_sync)(struct fb_info *info);
285 * * perform fb specific ioctl (optional) *
286 * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
287 * unsigned long arg);
289 * * Handle 32bit compat ioctl (optional) *
290 * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
291 * unsigned long arg);
293 * * perform fb specific mmap *
294 * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
299 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
302 * int (*detect)(void)
303 * This function should detect the current video mode settings and
304 * store them in atafb_predefined[0] for later reference by the
305 * user. Return the index+1 of an equivalent predefined mode or 0
306 * if there is no such.
308 * int (*encode_fix)(struct fb_fix_screeninfo *fix,
309 * struct atafb_par *par)
310 * This function should fill in the 'fix' structure based on the
311 * values in the 'par' structure.
312 * !!! Obsolete, perhaps !!!
314 * int (*decode_var)(struct fb_var_screeninfo *var,
315 * struct atafb_par *par)
316 * Get the video params out of 'var'. If a value doesn't fit, round
317 * it up, if it's too big, return EINVAL.
318 * Round up in the following order: bits_per_pixel, xres, yres,
319 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
320 * horizontal timing, vertical timing.
322 * int (*encode_var)(struct fb_var_screeninfo *var,
323 * struct atafb_par *par);
324 * Fill the 'var' structure based on the values in 'par' and maybe
325 * other values read out of the hardware.
327 * void (*get_par)(struct atafb_par *par)
328 * Fill the hardware's 'par' structure.
329 * !!! Used only by detect() !!!
331 * void (*set_par)(struct atafb_par *par)
332 * Set the hardware according to 'par'.
334 * void (*set_screen_base)(void *s_base)
335 * Set the base address of the displayed frame buffer. Only called
336 * if yres_virtual > yres or xres_virtual > xres.
338 * int (*blank)(int blank_mode)
339 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
340 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
341 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
342 * doesn't support it. Implements VESA suspend and powerdown modes on
343 * hardware that supports disabling hsync/vsync:
344 * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
347 static struct fb_hwswitch
{
349 int (*encode_fix
)(struct fb_fix_screeninfo
*fix
,
350 struct atafb_par
*par
);
351 int (*decode_var
)(struct fb_var_screeninfo
*var
,
352 struct atafb_par
*par
);
353 int (*encode_var
)(struct fb_var_screeninfo
*var
,
354 struct atafb_par
*par
);
355 void (*get_par
)(struct atafb_par
*par
);
356 void (*set_par
)(struct atafb_par
*par
);
357 void (*set_screen_base
)(void *s_base
);
358 int (*blank
)(int blank_mode
);
359 int (*pan_display
)(struct fb_var_screeninfo
*var
,
360 struct fb_info
*info
);
363 static char *autodetect_names
[] = { "autodetect", NULL
};
364 static char *stlow_names
[] = { "stlow", NULL
};
365 static char *stmid_names
[] = { "stmid", "default5", NULL
};
366 static char *sthigh_names
[] = { "sthigh", "default4", NULL
};
367 static char *ttlow_names
[] = { "ttlow", NULL
};
368 static char *ttmid_names
[] = { "ttmid", "default1", NULL
};
369 static char *tthigh_names
[] = { "tthigh", "default2", NULL
};
370 static char *vga2_names
[] = { "vga2", NULL
};
371 static char *vga4_names
[] = { "vga4", NULL
};
372 static char *vga16_names
[] = { "vga16", "default3", NULL
};
373 static char *vga256_names
[] = { "vga256", NULL
};
374 static char *falh2_names
[] = { "falh2", NULL
};
375 static char *falh16_names
[] = { "falh16", NULL
};
377 static char **fb_var_names
[] = {
394 static struct fb_var_screeninfo atafb_predefined
[] = {
396 * yres_virtual == 0 means use hw-scrolling if possible, else yres
399 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
400 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
401 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
403 320, 200, 320, 0, 0, 0, 4, 0,
404 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
405 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
407 640, 200, 640, 0, 0, 0, 2, 0,
408 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
409 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
411 640, 400, 640, 0, 0, 0, 1, 0,
412 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
413 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
415 320, 480, 320, 0, 0, 0, 8, 0,
416 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
417 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
419 640, 480, 640, 0, 0, 0, 4, 0,
420 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
421 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
423 1280, 960, 1280, 0, 0, 0, 1, 0,
424 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
425 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
427 640, 480, 640, 0, 0, 0, 1, 0,
428 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
429 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
431 640, 480, 640, 0, 0, 0, 2, 0,
432 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
433 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
435 640, 480, 640, 0, 0, 0, 4, 0,
436 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
437 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
439 640, 480, 640, 0, 0, 0, 8, 0,
440 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
441 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
443 896, 608, 896, 0, 0, 0, 1, 0,
444 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
445 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
447 896, 608, 896, 0, 0, 0, 4, 0,
448 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
449 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
452 static int num_atafb_predefined
= ARRAY_SIZE(atafb_predefined
);
454 static struct fb_videomode atafb_modedb
[] __initdata
= {
458 * If you change these, make sure to update DEFMODE_* as well!
466 /* 320x200, 15 kHz, 60 Hz (ST low) */
467 "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
468 0, FB_VMODE_NONINTERLACED
470 /* 640x200, 15 kHz, 60 Hz (ST medium) */
471 "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
472 0, FB_VMODE_NONINTERLACED
474 /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
475 "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
476 0, FB_VMODE_NONINTERLACED
478 /* 320x480, 15 kHz, 60 Hz (TT low) */
479 "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
480 0, FB_VMODE_NONINTERLACED
482 /* 640x480, 29 kHz, 57 Hz (TT medium) */
483 "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
484 0, FB_VMODE_NONINTERLACED
486 /* 1280x960, 72 kHz, 72 Hz (TT high) */
487 "tt-high", 72, 1280, 960, 7760, 260, 60, 36, 4, 192, 4,
488 0, FB_VMODE_NONINTERLACED
496 /* 640x480, 31 kHz, 60 Hz (VGA) */
497 "vga", 60, 640, 480, 39721, 42, 18, 31, 11, 100, 3,
498 0, FB_VMODE_NONINTERLACED
500 /* 640x400, 31 kHz, 70 Hz (VGA) */
501 "vga70", 70, 640, 400, 39721, 42, 18, 31, 11, 100, 3,
502 FB_SYNC_VERT_HIGH_ACT
| FB_SYNC_COMP_HIGH_ACT
, FB_VMODE_NONINTERLACED
506 * Falcon HiRes Video Modes
510 /* 896x608, 31 kHz, 60 Hz (Falcon High) */
511 "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
512 0, FB_VMODE_NONINTERLACED
516 #define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb)
518 static char *mode_option __initdata
= NULL
;
522 #define DEFMODE_TT 5 /* "tt-high" for TT */
523 #define DEFMODE_F30 7 /* "vga70" for Falcon */
524 #define DEFMODE_STE 2 /* "st-high" for ST/E */
525 #define DEFMODE_EXT 6 /* "vga" for external */
528 static int get_video_mode(char *vname
)
534 name_list
= fb_var_names
;
535 for (i
= 0; i
< num_atafb_predefined
; i
++) {
540 if (!strcmp(vname
, *name
))
550 /* ------------------- TT specific functions ---------------------- */
554 static int tt_encode_fix(struct fb_fix_screeninfo
*fix
, struct atafb_par
*par
)
558 strcpy(fix
->id
, "Atari Builtin");
559 fix
->smem_start
= phys_screen_base
;
560 fix
->smem_len
= screen_len
;
561 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
563 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
564 mode
= par
->hw
.tt
.mode
& TT_SHIFTER_MODEMASK
;
565 if (mode
== TT_SHIFTER_TTHIGH
|| mode
== TT_SHIFTER_STHIGH
) {
566 fix
->type
= FB_TYPE_PACKED_PIXELS
;
568 if (mode
== TT_SHIFTER_TTHIGH
)
569 fix
->visual
= FB_VISUAL_MONO01
;
574 fix
->line_length
= par
->next_line
;
575 fix
->accel
= FB_ACCEL_ATARIBLITT
;
579 static int tt_decode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
581 int xres
= var
->xres
;
582 int yres
= var
->yres
;
583 int bpp
= var
->bits_per_pixel
;
585 int yres_virtual
= var
->yres_virtual
;
588 if (bpp
> 1 || xres
> sttt_xres
* 2 || yres
> tt_yres
* 2)
590 par
->hw
.tt
.mode
= TT_SHIFTER_TTHIGH
;
591 xres
= sttt_xres
* 2;
595 if (bpp
> 8 || xres
> sttt_xres
|| yres
> tt_yres
)
598 if (xres
> sttt_xres
/ 2 || yres
> tt_yres
)
600 par
->hw
.tt
.mode
= TT_SHIFTER_TTLOW
;
601 xres
= sttt_xres
/ 2;
604 } else if (bpp
> 2) {
605 if (xres
> sttt_xres
|| yres
> tt_yres
)
607 if (xres
> sttt_xres
/ 2 || yres
> st_yres
/ 2) {
608 par
->hw
.tt
.mode
= TT_SHIFTER_TTMID
;
613 par
->hw
.tt
.mode
= TT_SHIFTER_STLOW
;
614 xres
= sttt_xres
/ 2;
618 } else if (bpp
> 1) {
619 if (xres
> sttt_xres
|| yres
> st_yres
/ 2)
621 par
->hw
.tt
.mode
= TT_SHIFTER_STMID
;
625 } else if (var
->xres
> sttt_xres
|| var
->yres
> st_yres
) {
628 par
->hw
.tt
.mode
= TT_SHIFTER_STHIGH
;
634 if (yres_virtual
<= 0)
636 else if (yres_virtual
< yres
)
638 if (var
->sync
& FB_SYNC_EXT
)
642 linelen
= xres
* bpp
/ 8;
643 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
645 if (yres
* linelen
> screen_len
&& screen_len
)
647 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
649 par
->yres_virtual
= yres_virtual
;
650 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
651 par
->next_line
= linelen
;
655 static int tt_encode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
658 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
661 var
->red
.msb_right
= 0;
664 var
->pixclock
= 31041;
665 var
->left_margin
= 120; /* these may be incorrect */
666 var
->right_margin
= 100;
667 var
->upper_margin
= 8;
668 var
->lower_margin
= 16;
669 var
->hsync_len
= 140;
675 if (par
->hw
.tt
.sync
& 1)
678 var
->sync
= FB_SYNC_EXT
;
680 switch (par
->hw
.tt
.mode
& TT_SHIFTER_MODEMASK
) {
681 case TT_SHIFTER_STLOW
:
682 var
->xres
= sttt_xres
/ 2;
683 var
->xres_virtual
= sttt_xres_virtual
/ 2;
684 var
->yres
= st_yres
/ 2;
685 var
->bits_per_pixel
= 4;
687 case TT_SHIFTER_STMID
:
688 var
->xres
= sttt_xres
;
689 var
->xres_virtual
= sttt_xres_virtual
;
690 var
->yres
= st_yres
/ 2;
691 var
->bits_per_pixel
= 2;
693 case TT_SHIFTER_STHIGH
:
694 var
->xres
= sttt_xres
;
695 var
->xres_virtual
= sttt_xres_virtual
;
697 var
->bits_per_pixel
= 1;
699 case TT_SHIFTER_TTLOW
:
700 var
->xres
= sttt_xres
/ 2;
701 var
->xres_virtual
= sttt_xres_virtual
/ 2;
703 var
->bits_per_pixel
= 8;
705 case TT_SHIFTER_TTMID
:
706 var
->xres
= sttt_xres
;
707 var
->xres_virtual
= sttt_xres_virtual
;
709 var
->bits_per_pixel
= 4;
711 case TT_SHIFTER_TTHIGH
:
713 var
->xres
= sttt_xres
* 2;
714 var
->xres_virtual
= sttt_xres_virtual
* 2;
715 var
->yres
= tt_yres
* 2;
716 var
->bits_per_pixel
= 1;
719 var
->blue
= var
->green
= var
->red
;
720 var
->transp
.offset
= 0;
721 var
->transp
.length
= 0;
722 var
->transp
.msb_right
= 0;
723 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
725 var
->yres_virtual
= var
->yres
;
726 else if (screen_len
) {
727 if (par
->yres_virtual
)
728 var
->yres_virtual
= par
->yres_virtual
;
730 /* yres_virtual == 0 means use maximum */
731 var
->yres_virtual
= screen_len
/ linelen
;
734 var
->yres_virtual
= 2 * var
->yres
;
736 var
->yres_virtual
= var
->yres
+ hwscroll
* 16;
740 var
->yoffset
= (par
->screen_base
- screen_base
) / linelen
;
745 var
->vmode
= FB_VMODE_NONINTERLACED
;
749 static void tt_get_par(struct atafb_par
*par
)
752 par
->hw
.tt
.mode
= shifter_tt
.tt_shiftmode
;
753 par
->hw
.tt
.sync
= shifter_st
.syncmode
;
754 addr
= ((shifter_st
.bas_hi
& 0xff) << 16) |
755 ((shifter_st
.bas_md
& 0xff) << 8) |
756 ((shifter_st
.bas_lo
& 0xff));
757 par
->screen_base
= atari_stram_to_virt(addr
);
760 static void tt_set_par(struct atafb_par
*par
)
762 shifter_tt
.tt_shiftmode
= par
->hw
.tt
.mode
;
763 shifter_st
.syncmode
= par
->hw
.tt
.sync
;
764 /* only set screen_base if really necessary */
765 if (current_par
.screen_base
!= par
->screen_base
)
766 fbhw
->set_screen_base(par
->screen_base
);
769 static int tt_setcolreg(unsigned int regno
, unsigned int red
,
770 unsigned int green
, unsigned int blue
,
771 unsigned int transp
, struct fb_info
*info
)
773 if ((shifter_tt
.tt_shiftmode
& TT_SHIFTER_MODEMASK
) == TT_SHIFTER_STHIGH
)
777 tt_palette
[regno
] = (((red
>> 12) << 8) | ((green
>> 12) << 4) |
779 if ((shifter_tt
.tt_shiftmode
& TT_SHIFTER_MODEMASK
) ==
780 TT_SHIFTER_STHIGH
&& regno
== 254)
785 static int tt_detect(void)
787 struct atafb_par par
;
789 /* Determine the connected monitor: The DMA sound must be
790 * disabled before reading the MFP GPIP, because the Sound
791 * Done Signal and the Monochrome Detect are XORed together!
793 * Even on a TT, we should look if there is a DMA sound. It was
794 * announced that the Eagle is TT compatible, but only the PCM is
797 if (ATARIHW_PRESENT(PCM_8BIT
)) {
798 tt_dmasnd
.ctrl
= DMASND_CTRL_OFF
;
799 udelay(20); /* wait a while for things to settle down */
801 mono_moni
= (st_mfp
.par_dt_reg
& 0x80) == 0;
804 tt_encode_var(&atafb_predefined
[0], &par
);
809 #endif /* ATAFB_TT */
811 /* ------------------- Falcon specific functions ---------------------- */
815 static int mon_type
; /* Falcon connected monitor */
816 static int f030_bus_width
; /* Falcon ram bus width (for vid_control) */
822 static struct pixel_clock
{
823 unsigned long f
; /* f/[Hz] */
824 unsigned long t
; /* t/[ps] (=1/f) */
825 int right
, hsync
, left
; /* standard timing in clock cycles, not pixel */
826 /* hsync initialized in falcon_detect() */
827 int sync_mask
; /* or-mask for hw.falcon.sync to set this clock */
828 int control_mask
; /* ditto, for hw.falcon.vid_control */
830 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
832 32000000, 31250, 18, 0, 42, 0x0, 0
834 0, 0, 18, 0, 42, 0x1, 0
837 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
838 static int vdl_prescale
[4][3] = {
839 { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
842 /* Default hsync timing [mon_type] in picoseconds */
843 static long h_syncs
[4] = { 3000000, 4875000, 4000000, 4875000 };
845 static inline int hxx_prescale(struct falcon_hw
*hw
)
847 return hw
->ste_mode
? 16
848 : vdl_prescale
[mon_type
][hw
->vid_mode
>> 2 & 0x3];
851 static int falcon_encode_fix(struct fb_fix_screeninfo
*fix
,
852 struct atafb_par
*par
)
854 strcpy(fix
->id
, "Atari Builtin");
855 fix
->smem_start
= phys_screen_base
;
856 fix
->smem_len
= screen_len
;
857 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
859 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
863 if (par
->hw
.falcon
.mono
) {
864 fix
->type
= FB_TYPE_PACKED_PIXELS
;
866 /* no smooth scrolling with longword aligned video mem */
868 } else if (par
->hw
.falcon
.f_shift
& 0x100) {
869 fix
->type
= FB_TYPE_PACKED_PIXELS
;
871 /* Is this ok or should it be DIRECTCOLOR? */
872 fix
->visual
= FB_VISUAL_TRUECOLOR
;
875 fix
->line_length
= par
->next_line
;
876 fix
->accel
= FB_ACCEL_ATARIBLITT
;
880 static int falcon_decode_var(struct fb_var_screeninfo
*var
,
881 struct atafb_par
*par
)
883 int bpp
= var
->bits_per_pixel
;
884 int xres
= var
->xres
;
885 int yres
= var
->yres
;
886 int xres_virtual
= var
->xres_virtual
;
887 int yres_virtual
= var
->yres_virtual
;
888 int left_margin
, right_margin
, hsync_len
;
889 int upper_margin
, lower_margin
, vsync_len
;
891 int interlace
= 0, doubleline
= 0;
892 struct pixel_clock
*pclock
;
893 int plen
; /* width of pixel in clock cycles */
898 int hdb_off
, hde_off
, base_off
;
899 int gstart
, gend1
, gend2
, align
;
902 Get the video params out of 'var'. If a value doesn't fit, round
903 it up, if it's too big, return EINVAL.
904 Round up in the following order: bits_per_pixel, xres, yres,
905 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
906 horizontal timing, vertical timing.
908 There is a maximum of screen resolution determined by pixelclock
909 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
910 In interlace mode this is " * " *vfmin <= pixelclock.
911 Additional constraints: hfreq.
912 Frequency range for multisync monitors is given via command line.
913 For TV and SM124 both frequencies are fixed.
915 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
916 Y % 16 == 0 to fit 8x16 font
919 Currently interlace and doubleline mode in var are ignored.
920 On SM124 and TV only the standard resolutions can be used.
923 /* Reject uninitialized mode */
924 if (!xres
|| !yres
|| !bpp
)
927 if (mon_type
== F_MON_SM
&& bpp
!= 1)
932 par
->hw
.falcon
.f_shift
= 0x400;
933 par
->hw
.falcon
.st_shift
= 0x200;
934 } else if (bpp
<= 2) {
936 par
->hw
.falcon
.f_shift
= 0x000;
937 par
->hw
.falcon
.st_shift
= 0x100;
938 } else if (bpp
<= 4) {
940 par
->hw
.falcon
.f_shift
= 0x000;
941 par
->hw
.falcon
.st_shift
= 0x000;
942 } else if (bpp
<= 8) {
944 par
->hw
.falcon
.f_shift
= 0x010;
945 } else if (bpp
<= 16) {
946 bpp
= 16; /* packed pixel mode */
947 par
->hw
.falcon
.f_shift
= 0x100; /* hicolor, no overlay */
950 par
->hw
.falcon
.bpp
= bpp
;
952 if (mon_type
== F_MON_SM
|| DontCalcRes
) {
953 /* Skip all calculations. VGA/TV/SC1224 only supported. */
954 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
956 if (bpp
> myvar
->bits_per_pixel
||
957 var
->xres
> myvar
->xres
||
958 var
->yres
> myvar
->yres
)
960 fbhw
->get_par(par
); /* Current par will be new par */
961 goto set_screen_base
; /* Don't forget this */
964 /* Only some fixed resolutions < 640x400 */
967 else if (xres
<= 640 && bpp
!= 16)
971 else if (yres
<= 240)
973 else if (yres
<= 400)
976 /* 2 planes must use STE compatibility mode */
977 par
->hw
.falcon
.ste_mode
= bpp
== 2;
978 par
->hw
.falcon
.mono
= bpp
== 1;
980 /* Total and visible scanline length must be a multiple of one longword,
981 * this and the console fontwidth yields the alignment for xres and
983 * TODO: this way "odd" fontheights are not supported
985 * Special case in STE mode: blank and graphic positions don't align,
986 * avoid trash at right margin
988 if (par
->hw
.falcon
.ste_mode
)
989 xres
= (xres
+ 63) & ~63;
991 xres
= (xres
+ 31) & ~31;
993 xres
= (xres
+ 15) & ~15;
995 yres
= (yres
+ 15) & ~15;
997 yres
= (yres
+ 7) & ~7;
999 if (xres_virtual
< xres
)
1000 xres_virtual
= xres
;
1002 xres_virtual
= (xres_virtual
+ 31) & ~31;
1004 xres_virtual
= (xres_virtual
+ 15) & ~15;
1006 if (yres_virtual
<= 0)
1008 else if (yres_virtual
< yres
)
1009 yres_virtual
= yres
;
1011 par
->hw
.falcon
.line_width
= bpp
* xres
/ 16;
1012 par
->hw
.falcon
.line_offset
= bpp
* (xres_virtual
- xres
) / 16;
1014 /* single or double pixel width */
1015 xstretch
= (xres
< 640) ? 2 : 1;
1017 #if 0 /* SM124 supports only 640x400, this is rejected above */
1018 if (mon_type
== F_MON_SM
) {
1019 if (xres
!= 640 && yres
!= 400)
1023 /* SM124-mode is special */
1024 par
->hw
.falcon
.ste_mode
= 1;
1025 par
->hw
.falcon
.f_shift
= 0x000;
1026 par
->hw
.falcon
.st_shift
= 0x200;
1027 left_margin
= hsync_len
= 128 / plen
;
1029 /* TODO set all margins */
1032 if (mon_type
== F_MON_SC
|| mon_type
== F_MON_TV
) {
1033 plen
= 2 * xstretch
;
1034 if (var
->pixclock
> f32
.t
* plen
)
1039 if (var
->pixclock
== 0) {
1040 /* set some minimal margins which center the screen */
1043 hsync_len
= pclock
->hsync
/ plen
;
1046 vsync_len
= interlace
? 3 : 4;
1048 left_margin
= var
->left_margin
;
1049 right_margin
= var
->right_margin
;
1050 hsync_len
= var
->hsync_len
;
1051 upper_margin
= var
->upper_margin
;
1052 lower_margin
= var
->lower_margin
;
1053 vsync_len
= var
->vsync_len
;
1054 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1055 upper_margin
= (upper_margin
+ 1) / 2;
1056 lower_margin
= (lower_margin
+ 1) / 2;
1057 vsync_len
= (vsync_len
+ 1) / 2;
1058 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1064 } else { /* F_MON_VGA */
1066 xstretch
= 2; /* Double pixel width only for hicolor */
1067 /* Default values are used for vert./hor. timing if no pixelclock given. */
1068 if (var
->pixclock
== 0) {
1069 /* Choose master pixelclock depending on hor. timing */
1070 plen
= 1 * xstretch
;
1071 if ((plen
* xres
+ f25
.right
+ f25
.hsync
+ f25
.left
) *
1072 fb_info
.monspecs
.hfmin
< f25
.f
)
1074 else if ((plen
* xres
+ f32
.right
+ f32
.hsync
+
1075 f32
.left
) * fb_info
.monspecs
.hfmin
< f32
.f
)
1077 else if ((plen
* xres
+ fext
.right
+ fext
.hsync
+
1078 fext
.left
) * fb_info
.monspecs
.hfmin
< fext
.f
&&
1084 left_margin
= pclock
->left
/ plen
;
1085 right_margin
= pclock
->right
/ plen
;
1086 hsync_len
= pclock
->hsync
/ plen
;
1091 /* Choose largest pixelclock <= wanted clock */
1093 unsigned long pcl
= ULONG_MAX
;
1095 for (i
= 1; i
<= 4; i
*= 2) {
1096 if (f25
.t
* i
>= var
->pixclock
&&
1101 if (f32
.t
* i
>= var
->pixclock
&&
1106 if (fext
.t
&& fext
.t
* i
>= var
->pixclock
&&
1114 plen
= pcl
/ pclock
->t
;
1116 left_margin
= var
->left_margin
;
1117 right_margin
= var
->right_margin
;
1118 hsync_len
= var
->hsync_len
;
1119 upper_margin
= var
->upper_margin
;
1120 lower_margin
= var
->lower_margin
;
1121 vsync_len
= var
->vsync_len
;
1122 /* Internal unit is [single lines per (half-)frame] */
1123 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1124 /* # lines in half frame */
1125 /* External unit is [lines per full frame] */
1126 upper_margin
= (upper_margin
+ 1) / 2;
1127 lower_margin
= (lower_margin
+ 1) / 2;
1128 vsync_len
= (vsync_len
+ 1) / 2;
1129 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1130 /* External unit is [double lines per frame] */
1136 if (pclock
== &fext
)
1137 longoffset
= 1; /* VIDEL doesn't synchronize on short offset */
1139 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1140 /* this is definitely wrong if bus clock != 32MHz */
1141 if (pclock
->f
/ plen
/ 8 * bpp
> 32000000L)
1147 /* include sync lengths in right/lower margin for all calculations */
1148 right_margin
+= hsync_len
;
1149 lower_margin
+= vsync_len
;
1151 /* ! In all calculations of margins we use # of lines in half frame
1152 * (which is a full frame in non-interlace mode), so we can switch
1153 * between interlace and non-interlace without messing around
1157 /* Set base_offset 128 and video bus width */
1158 par
->hw
.falcon
.vid_control
= mon_type
| f030_bus_width
;
1160 par
->hw
.falcon
.vid_control
|= VCO_SHORTOFFS
; /* base_offset 64 */
1161 if (var
->sync
& FB_SYNC_HOR_HIGH_ACT
)
1162 par
->hw
.falcon
.vid_control
|= VCO_HSYPOS
;
1163 if (var
->sync
& FB_SYNC_VERT_HIGH_ACT
)
1164 par
->hw
.falcon
.vid_control
|= VCO_VSYPOS
;
1166 par
->hw
.falcon
.vid_control
|= pclock
->control_mask
;
1167 /* External or internal clock */
1168 par
->hw
.falcon
.sync
= pclock
->sync_mask
| 0x2;
1169 /* Pixellength and prescale */
1170 par
->hw
.falcon
.vid_mode
= (2 / plen
) << 2;
1172 par
->hw
.falcon
.vid_mode
|= VMO_DOUBLE
;
1174 par
->hw
.falcon
.vid_mode
|= VMO_INTER
;
1176 /*********************
1177 * Horizontal timing: unit = [master clock cycles]
1178 * unit of hxx-registers: [master clock cycles * prescale]
1179 * Hxx-registers are 9 bit wide
1181 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1183 * graphic output = hdb & 0x200 ?
1184 * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1185 * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1186 * (this must be a multiple of plen*128/bpp, on VGA pixels
1187 * to the right may be cut off with a bigger right margin)
1189 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1190 * (hdb - hht - 2) * prescale + hdboff :
1191 * hdb * prescale + hdboff
1193 * end of graphics relative to start of 1st halfline =
1194 * (hde + hht + 2) * prescale + hdeoff
1195 *********************/
1196 /* Calculate VIDEL registers */
1198 prescale
= hxx_prescale(&par
->hw
.falcon
);
1199 base_off
= par
->hw
.falcon
.vid_control
& VCO_SHORTOFFS
? 64 : 128;
1201 /* Offsets depend on video mode */
1202 /* Offsets are in clock cycles, divide by prescale to
1203 * calculate hd[be]-registers
1205 if (par
->hw
.falcon
.f_shift
& 0x100) {
1208 hdb_off
= (base_off
+ 16 * plen
) + prescale
;
1211 hde_off
= ((128 / bpp
+ 2) * plen
);
1212 if (par
->hw
.falcon
.ste_mode
)
1213 hdb_off
= (64 + base_off
+ (128 / bpp
+ 2) * plen
) + prescale
;
1215 hdb_off
= (base_off
+ (128 / bpp
+ 18) * plen
) + prescale
;
1218 gstart
= (prescale
/ 2 + plen
* left_margin
) / prescale
;
1219 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1220 gend1
= gstart
+ roundup(xres
, align
) * plen
/ prescale
;
1221 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1222 gend2
= gstart
+ xres
* plen
/ prescale
;
1223 par
->HHT
= plen
* (left_margin
+ xres
+ right_margin
) /
1225 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1227 par
->HDB
= gstart
- hdb_off
/ prescale
;
1230 par
->HDB
+= par
->HHT
+ 2 + 0x200;
1231 par
->HDE
= gend1
- par
->HHT
- 2 - hde_off
/ prescale
;
1232 par
->HBB
= gend2
- par
->HHT
- 2;
1234 /* One more Videl constraint: data fetch of two lines must not overlap */
1235 if ((par
->HDB
& 0x200) && (par
->HDB
& ~0x200) - par
->HDE
<= 5) {
1236 /* if this happens increase margins, decrease hfreq. */
1239 if (hde_off
% prescale
)
1240 par
->HBB
++; /* compensate for non matching hde and hbb */
1241 par
->HSS
= par
->HHT
+ 2 - plen
* hsync_len
/ prescale
;
1242 if (par
->HSS
< par
->HBB
)
1243 par
->HSS
= par
->HBB
;
1246 /* check hor. frequency */
1247 hfreq
= pclock
->f
/ ((par
->HHT
+ 2) * prescale
* 2);
1248 if (hfreq
> fb_info
.monspecs
.hfmax
&& mon_type
!= F_MON_VGA
) {
1249 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1250 /* Too high -> enlarge margin */
1255 if (hfreq
> fb_info
.monspecs
.hfmax
|| hfreq
< fb_info
.monspecs
.hfmin
)
1259 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1260 * of the first displayed line!
1261 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1262 * non-interlace, odd in interlace mode for synchronisation.
1263 * Vxx-registers are 11 bit wide
1265 par
->VBE
= (upper_margin
* 2 + 1); /* must begin on odd halfline */
1266 par
->VDB
= par
->VBE
;
1271 par
->VDE
<<= 1; /* VDE now half lines per (half-)frame */
1272 par
->VDE
+= par
->VDB
;
1273 par
->VBB
= par
->VDE
;
1274 par
->VFT
= par
->VBB
+ (lower_margin
* 2 - 1) - 1;
1275 par
->VSS
= par
->VFT
+ 1 - (vsync_len
* 2 - 1);
1276 /* vbb,vss,vft must be even in interlace mode */
1283 /* V-frequency check, hope I didn't create any loop here. */
1284 /* Interlace and doubleline are mutually exclusive. */
1285 vfreq
= (hfreq
* 2) / (par
->VFT
+ 1);
1286 if (vfreq
> fb_info
.monspecs
.vfmax
&& !doubleline
&& !interlace
) {
1287 /* Too high -> try again with doubleline */
1290 } else if (vfreq
< fb_info
.monspecs
.vfmin
&& !interlace
&& !doubleline
) {
1291 /* Too low -> try again with interlace */
1294 } else if (vfreq
< fb_info
.monspecs
.vfmin
&& doubleline
) {
1295 /* Doubleline too low -> clear doubleline and enlarge margins */
1299 (hfreq
* 2) / (par
->VFT
+ 1 + 4 * lines
- 2 * yres
) >
1300 fb_info
.monspecs
.vfmax
;
1303 upper_margin
+= lines
;
1304 lower_margin
+= lines
;
1306 } else if (vfreq
> fb_info
.monspecs
.vfmax
&& doubleline
) {
1307 /* Doubleline too high -> enlarge margins */
1310 (hfreq
* 2) / (par
->VFT
+ 1 + 4 * lines
) >
1311 fb_info
.monspecs
.vfmax
;
1314 upper_margin
+= lines
;
1315 lower_margin
+= lines
;
1317 } else if (vfreq
> fb_info
.monspecs
.vfmax
&& interlace
) {
1318 /* Interlace, 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
.vfmin
||
1329 vfreq
> fb_info
.monspecs
.vfmax
)
1333 linelen
= xres_virtual
* bpp
/ 8;
1334 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
1336 if (yres
* linelen
> screen_len
&& screen_len
)
1338 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
1340 par
->yres_virtual
= yres_virtual
;
1341 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
1342 par
->hw
.falcon
.xoffset
= 0;
1344 par
->next_line
= linelen
;
1349 static int falcon_encode_var(struct fb_var_screeninfo
*var
,
1350 struct atafb_par
*par
)
1352 /* !!! only for VGA !!! */
1355 int hdb_off
, hde_off
, base_off
;
1356 struct falcon_hw
*hw
= &par
->hw
.falcon
;
1358 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
1359 /* possible frequencies: 25.175 or 32MHz */
1360 var
->pixclock
= hw
->sync
& 0x1 ? fext
.t
:
1361 hw
->vid_control
& VCO_CLOCK25
? f25
.t
: f32
.t
;
1367 if (hw
->vid_control
& VCO_HSYPOS
)
1368 var
->sync
|= FB_SYNC_HOR_HIGH_ACT
;
1369 if (hw
->vid_control
& VCO_VSYPOS
)
1370 var
->sync
|= FB_SYNC_VERT_HIGH_ACT
;
1372 var
->vmode
= FB_VMODE_NONINTERLACED
;
1373 if (hw
->vid_mode
& VMO_INTER
)
1374 var
->vmode
|= FB_VMODE_INTERLACED
;
1375 if (hw
->vid_mode
& VMO_DOUBLE
)
1376 var
->vmode
|= FB_VMODE_DOUBLE
;
1378 /* visible y resolution:
1379 * Graphics display starts at line VDB and ends at line
1380 * VDE. If interlace mode off unit of VC-registers is
1381 * half lines, else lines.
1383 var
->yres
= hw
->vde
- hw
->vdb
;
1384 if (!(var
->vmode
& FB_VMODE_INTERLACED
))
1386 if (var
->vmode
& FB_VMODE_DOUBLE
)
1390 * to get bpp, we must examine f_shift and st_shift.
1391 * f_shift is valid if any of bits no. 10, 8 or 4
1392 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1393 * if bit 10 set then bit 8 and bit 4 don't care...
1394 * If all these bits are 0 get display depth from st_shift
1395 * (as for ST and STE)
1397 if (hw
->f_shift
& 0x400) /* 2 colors */
1398 var
->bits_per_pixel
= 1;
1399 else if (hw
->f_shift
& 0x100) /* hicolor */
1400 var
->bits_per_pixel
= 16;
1401 else if (hw
->f_shift
& 0x010) /* 8 bitplanes */
1402 var
->bits_per_pixel
= 8;
1403 else if (hw
->st_shift
== 0)
1404 var
->bits_per_pixel
= 4;
1405 else if (hw
->st_shift
== 0x100)
1406 var
->bits_per_pixel
= 2;
1407 else /* if (hw->st_shift == 0x200) */
1408 var
->bits_per_pixel
= 1;
1410 var
->xres
= hw
->line_width
* 16 / var
->bits_per_pixel
;
1411 var
->xres_virtual
= var
->xres
+ hw
->line_offset
* 16 / var
->bits_per_pixel
;
1413 var
->xres_virtual
+= 16;
1415 if (var
->bits_per_pixel
== 16) {
1416 var
->red
.offset
= 11;
1417 var
->red
.length
= 5;
1418 var
->red
.msb_right
= 0;
1419 var
->green
.offset
= 5;
1420 var
->green
.length
= 6;
1421 var
->green
.msb_right
= 0;
1422 var
->blue
.offset
= 0;
1423 var
->blue
.length
= 5;
1424 var
->blue
.msb_right
= 0;
1426 var
->red
.offset
= 0;
1427 var
->red
.length
= hw
->ste_mode
? 4 : 6;
1428 if (var
->red
.length
> var
->bits_per_pixel
)
1429 var
->red
.length
= var
->bits_per_pixel
;
1430 var
->red
.msb_right
= 0;
1432 var
->blue
= var
->green
= var
->red
;
1434 var
->transp
.offset
= 0;
1435 var
->transp
.length
= 0;
1436 var
->transp
.msb_right
= 0;
1438 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
1440 if (par
->yres_virtual
)
1441 var
->yres_virtual
= par
->yres_virtual
;
1443 /* yres_virtual == 0 means use maximum */
1444 var
->yres_virtual
= screen_len
/ linelen
;
1447 var
->yres_virtual
= 2 * var
->yres
;
1449 var
->yres_virtual
= var
->yres
+ hwscroll
* 16;
1451 var
->xoffset
= 0; /* TODO change this */
1454 prescale
= hxx_prescale(hw
);
1455 plen
= 4 >> (hw
->vid_mode
>> 2 & 0x3);
1456 base_off
= hw
->vid_control
& VCO_SHORTOFFS
? 64 : 128;
1457 if (hw
->f_shift
& 0x100) {
1459 hdb_off
= (base_off
+ 16 * plen
) + prescale
;
1461 hde_off
= ((128 / var
->bits_per_pixel
+ 2) * plen
);
1463 hdb_off
= (64 + base_off
+ (128 / var
->bits_per_pixel
+ 2) * plen
)
1466 hdb_off
= (base_off
+ (128 / var
->bits_per_pixel
+ 18) * plen
)
1470 /* Right margin includes hsync */
1471 var
->left_margin
= hdb_off
+ prescale
* ((hw
->hdb
& 0x1ff) -
1472 (hw
->hdb
& 0x200 ? 2 + hw
->hht
: 0));
1473 if (hw
->ste_mode
|| mon_type
!= F_MON_VGA
)
1474 var
->right_margin
= prescale
* (hw
->hht
+ 2 - hw
->hde
) - hde_off
;
1476 /* can't use this in ste_mode, because hbb is +1 off */
1477 var
->right_margin
= prescale
* (hw
->hht
+ 2 - hw
->hbb
);
1478 var
->hsync_len
= prescale
* (hw
->hht
+ 2 - hw
->hss
);
1480 /* Lower margin includes vsync */
1481 var
->upper_margin
= hw
->vdb
/ 2; /* round down to full lines */
1482 var
->lower_margin
= (hw
->vft
+ 1 - hw
->vde
+ 1) / 2; /* round up */
1483 var
->vsync_len
= (hw
->vft
+ 1 - hw
->vss
+ 1) / 2; /* round up */
1484 if (var
->vmode
& FB_VMODE_INTERLACED
) {
1485 var
->upper_margin
*= 2;
1486 var
->lower_margin
*= 2;
1487 var
->vsync_len
*= 2;
1488 } else if (var
->vmode
& FB_VMODE_DOUBLE
) {
1489 var
->upper_margin
= (var
->upper_margin
+ 1) / 2;
1490 var
->lower_margin
= (var
->lower_margin
+ 1) / 2;
1491 var
->vsync_len
= (var
->vsync_len
+ 1) / 2;
1494 var
->pixclock
*= plen
;
1495 var
->left_margin
/= plen
;
1496 var
->right_margin
/= plen
;
1497 var
->hsync_len
/= plen
;
1499 var
->right_margin
-= var
->hsync_len
;
1500 var
->lower_margin
-= var
->vsync_len
;
1503 var
->yoffset
= (par
->screen_base
- screen_base
) / linelen
;
1506 var
->nonstd
= 0; /* what is this for? */
1511 static int f_change_mode
;
1512 static struct falcon_hw f_new_mode
;
1513 static int f_pan_display
;
1515 static void falcon_get_par(struct atafb_par
*par
)
1518 struct falcon_hw
*hw
= &par
->hw
.falcon
;
1520 hw
->line_width
= shifter_f030
.scn_width
;
1521 hw
->line_offset
= shifter_f030
.off_next
;
1522 hw
->st_shift
= videl
.st_shift
& 0x300;
1523 hw
->f_shift
= videl
.f_shift
;
1524 hw
->vid_control
= videl
.control
;
1525 hw
->vid_mode
= videl
.mode
;
1526 hw
->sync
= shifter_st
.syncmode
& 0x1;
1527 hw
->xoffset
= videl
.xoffset
& 0xf;
1528 hw
->hht
= videl
.hht
;
1529 hw
->hbb
= videl
.hbb
;
1530 hw
->hbe
= videl
.hbe
;
1531 hw
->hdb
= videl
.hdb
;
1532 hw
->hde
= videl
.hde
;
1533 hw
->hss
= videl
.hss
;
1534 hw
->vft
= videl
.vft
;
1535 hw
->vbb
= videl
.vbb
;
1536 hw
->vbe
= videl
.vbe
;
1537 hw
->vdb
= videl
.vdb
;
1538 hw
->vde
= videl
.vde
;
1539 hw
->vss
= videl
.vss
;
1541 addr
= (shifter_st
.bas_hi
& 0xff) << 16 |
1542 (shifter_st
.bas_md
& 0xff) << 8 |
1543 (shifter_st
.bas_lo
& 0xff);
1544 par
->screen_base
= atari_stram_to_virt(addr
);
1546 /* derived parameters */
1547 hw
->ste_mode
= (hw
->f_shift
& 0x510) == 0 && hw
->st_shift
== 0x100;
1548 hw
->mono
= (hw
->f_shift
& 0x400) ||
1549 ((hw
->f_shift
& 0x510) == 0 && hw
->st_shift
== 0x200);
1552 static void falcon_set_par(struct atafb_par
*par
)
1556 /* only set screen_base if really necessary */
1557 if (current_par
.screen_base
!= par
->screen_base
)
1558 fbhw
->set_screen_base(par
->screen_base
);
1560 /* Don't touch any other registers if we keep the default resolution */
1564 /* Tell vbl-handler to change video mode.
1565 * We change modes only on next VBL, to avoid desynchronisation
1566 * (a shift to the right and wrap around by a random number of pixels
1567 * in all monochrome modes).
1568 * This seems to work on my Falcon.
1570 f_new_mode
= par
->hw
.falcon
;
1574 static irqreturn_t
falcon_vbl_switcher(int irq
, void *dummy
)
1576 struct falcon_hw
*hw
= &f_new_mode
;
1578 if (f_change_mode
) {
1581 if (hw
->sync
& 0x1) {
1582 /* Enable external pixelclock. This code only for ScreenWonder */
1583 *(volatile unsigned short *)0xffff9202 = 0xffbf;
1585 /* Turn off external clocks. Read sets all output bits to 1. */
1586 *(volatile unsigned short *)0xffff9202;
1588 shifter_st
.syncmode
= hw
->sync
;
1590 videl
.hht
= hw
->hht
;
1591 videl
.hbb
= hw
->hbb
;
1592 videl
.hbe
= hw
->hbe
;
1593 videl
.hdb
= hw
->hdb
;
1594 videl
.hde
= hw
->hde
;
1595 videl
.hss
= hw
->hss
;
1596 videl
.vft
= hw
->vft
;
1597 videl
.vbb
= hw
->vbb
;
1598 videl
.vbe
= hw
->vbe
;
1599 videl
.vdb
= hw
->vdb
;
1600 videl
.vde
= hw
->vde
;
1601 videl
.vss
= hw
->vss
;
1603 videl
.f_shift
= 0; /* write enables Falcon palette, 0: 4 planes */
1605 videl
.st_shift
= hw
->st_shift
; /* write enables STE palette */
1608 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1609 * Writing 0 to f_shift enables 4 plane Falcon mode but
1610 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1611 * with Falcon palette.
1614 /* now back to Falcon palette mode */
1615 videl
.f_shift
= hw
->f_shift
;
1617 /* writing to st_shift changed scn_width and vid_mode */
1618 videl
.xoffset
= hw
->xoffset
;
1619 shifter_f030
.scn_width
= hw
->line_width
;
1620 shifter_f030
.off_next
= hw
->line_offset
;
1621 videl
.control
= hw
->vid_control
;
1622 videl
.mode
= hw
->vid_mode
;
1624 if (f_pan_display
) {
1626 videl
.xoffset
= current_par
.hw
.falcon
.xoffset
;
1627 shifter_f030
.off_next
= current_par
.hw
.falcon
.line_offset
;
1632 static int falcon_pan_display(struct fb_var_screeninfo
*var
,
1633 struct fb_info
*info
)
1635 struct atafb_par
*par
= info
->par
;
1638 int bpp
= info
->var
.bits_per_pixel
;
1641 var
->xoffset
= round_up(var
->xoffset
, 32);
1643 par
->hw
.falcon
.xoffset
= var
->xoffset
& 15;
1645 par
->hw
.falcon
.xoffset
= 0;
1646 var
->xoffset
= round_up(var
->xoffset
, 2);
1648 par
->hw
.falcon
.line_offset
= bpp
*
1649 (info
->var
.xres_virtual
- info
->var
.xres
) / 16;
1650 if (par
->hw
.falcon
.xoffset
)
1651 par
->hw
.falcon
.line_offset
-= bpp
;
1652 xoffset
= var
->xoffset
- par
->hw
.falcon
.xoffset
;
1654 par
->screen_base
= screen_base
+
1655 (var
->yoffset
* info
->var
.xres_virtual
+ xoffset
) * bpp
/ 8;
1656 if (fbhw
->set_screen_base
)
1657 fbhw
->set_screen_base(par
->screen_base
);
1659 return -EINVAL
; /* shouldn't happen */
1664 static int falcon_setcolreg(unsigned int regno
, unsigned int red
,
1665 unsigned int green
, unsigned int blue
,
1666 unsigned int transp
, struct fb_info
*info
)
1670 f030_col
[regno
] = (((red
& 0xfc00) << 16) |
1671 ((green
& 0xfc00) << 8) |
1672 ((blue
& 0xfc00) >> 8));
1674 shifter_tt
.color_reg
[regno
] =
1675 ((((red
& 0xe000) >> 13) | ((red
& 0x1000) >> 12)) << 8) |
1676 ((((green
& 0xe000) >> 13) | ((green
& 0x1000) >> 12)) << 4) |
1677 ((blue
& 0xe000) >> 13) | ((blue
& 0x1000) >> 12);
1678 ((u32
*)info
->pseudo_palette
)[regno
] = ((red
& 0xf800) |
1679 ((green
& 0xfc00) >> 5) |
1680 ((blue
& 0xf800) >> 11));
1685 static int falcon_blank(int blank_mode
)
1687 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1688 * so VIDEL doesn't hog the bus while saving.
1689 * (this may affect usleep()).
1691 int vdb
, vss
, hbe
, hss
;
1693 if (mon_type
== F_MON_SM
) /* this doesn't work on SM124 */
1696 vdb
= current_par
.VDB
;
1697 vss
= current_par
.VSS
;
1698 hbe
= current_par
.HBE
;
1699 hss
= current_par
.HSS
;
1701 if (blank_mode
>= 1) {
1702 /* disable graphics output (this speeds up the CPU) ... */
1703 vdb
= current_par
.VFT
+ 1;
1704 /* ... and blank all lines */
1705 hbe
= current_par
.HHT
+ 2;
1707 /* use VESA suspend modes on VGA monitors */
1708 if (mon_type
== F_MON_VGA
) {
1709 if (blank_mode
== 2 || blank_mode
== 4)
1710 vss
= current_par
.VFT
+ 1;
1711 if (blank_mode
== 3 || blank_mode
== 4)
1712 hss
= current_par
.HHT
+ 2;
1723 static int falcon_detect(void)
1725 struct atafb_par par
;
1728 /* Determine connected monitor and set monitor parameters */
1729 fhw
= *(unsigned char *)0xffff8006;
1730 mon_type
= fhw
>> 6 & 0x3;
1731 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1732 f030_bus_width
= fhw
<< 6 & 0x80;
1735 fb_info
.monspecs
.vfmin
= 70;
1736 fb_info
.monspecs
.vfmax
= 72;
1737 fb_info
.monspecs
.hfmin
= 35713;
1738 fb_info
.monspecs
.hfmax
= 35715;
1743 fb_info
.monspecs
.vfmin
= 49; /* not 50, since TOS defaults to 49.9x Hz */
1744 fb_info
.monspecs
.vfmax
= 60;
1745 fb_info
.monspecs
.hfmin
= 15620;
1746 fb_info
.monspecs
.hfmax
= 15755;
1749 /* initialize hsync-len */
1750 f25
.hsync
= h_syncs
[mon_type
] / f25
.t
;
1751 f32
.hsync
= h_syncs
[mon_type
] / f32
.t
;
1753 fext
.hsync
= h_syncs
[mon_type
] / fext
.t
;
1755 falcon_get_par(&par
);
1756 falcon_encode_var(&atafb_predefined
[0], &par
);
1758 /* Detected mode is always the "autodetect" slot */
1762 #endif /* ATAFB_FALCON */
1764 /* ------------------- ST(E) specific functions ---------------------- */
1768 static int stste_encode_fix(struct fb_fix_screeninfo
*fix
,
1769 struct atafb_par
*par
)
1773 strcpy(fix
->id
, "Atari Builtin");
1774 fix
->smem_start
= phys_screen_base
;
1775 fix
->smem_len
= screen_len
;
1776 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
1778 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
1779 mode
= par
->hw
.st
.mode
& 3;
1780 if (mode
== ST_HIGH
) {
1781 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1783 fix
->visual
= FB_VISUAL_MONO10
;
1785 if (ATARIHW_PRESENT(EXTD_SHIFTER
)) {
1793 fix
->line_length
= par
->next_line
;
1794 fix
->accel
= FB_ACCEL_ATARIBLITT
;
1798 static int stste_decode_var(struct fb_var_screeninfo
*var
,
1799 struct atafb_par
*par
)
1801 int xres
= var
->xres
;
1802 int yres
= var
->yres
;
1803 int bpp
= var
->bits_per_pixel
;
1805 int yres_virtual
= var
->yres_virtual
;
1808 if (bpp
> 1 || xres
> sttt_xres
|| yres
> st_yres
)
1810 par
->hw
.st
.mode
= ST_HIGH
;
1815 if (bpp
> 4 || xres
> sttt_xres
|| yres
> st_yres
)
1818 if (xres
> sttt_xres
/ 2 || yres
> st_yres
/ 2)
1820 par
->hw
.st
.mode
= ST_LOW
;
1821 xres
= sttt_xres
/ 2;
1824 } else if (bpp
> 1) {
1825 if (xres
> sttt_xres
|| yres
> st_yres
/ 2)
1827 par
->hw
.st
.mode
= ST_MID
;
1834 if (yres_virtual
<= 0)
1836 else if (yres_virtual
< yres
)
1837 yres_virtual
= yres
;
1838 if (var
->sync
& FB_SYNC_EXT
)
1839 par
->hw
.st
.sync
= (par
->hw
.st
.sync
& ~1) | 1;
1841 par
->hw
.st
.sync
= (par
->hw
.st
.sync
& ~1);
1842 linelen
= xres
* bpp
/ 8;
1843 if (yres_virtual
* linelen
> screen_len
&& screen_len
)
1845 if (yres
* linelen
> screen_len
&& screen_len
)
1847 if (var
->yoffset
+ yres
> yres_virtual
&& yres_virtual
)
1849 par
->yres_virtual
= yres_virtual
;
1850 par
->screen_base
= screen_base
+ var
->yoffset
* linelen
;
1851 par
->next_line
= linelen
;
1855 static int stste_encode_var(struct fb_var_screeninfo
*var
,
1856 struct atafb_par
*par
)
1859 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
1860 var
->red
.offset
= 0;
1861 var
->red
.length
= ATARIHW_PRESENT(EXTD_SHIFTER
) ? 4 : 3;
1862 var
->red
.msb_right
= 0;
1865 var
->pixclock
= 31041;
1866 var
->left_margin
= 120; /* these are incorrect */
1867 var
->right_margin
= 100;
1868 var
->upper_margin
= 8;
1869 var
->lower_margin
= 16;
1870 var
->hsync_len
= 140;
1871 var
->vsync_len
= 30;
1876 if (!(par
->hw
.st
.sync
& 1))
1879 var
->sync
= FB_SYNC_EXT
;
1881 switch (par
->hw
.st
.mode
& 3) {
1883 var
->xres
= sttt_xres
/ 2;
1884 var
->yres
= st_yres
/ 2;
1885 var
->bits_per_pixel
= 4;
1888 var
->xres
= sttt_xres
;
1889 var
->yres
= st_yres
/ 2;
1890 var
->bits_per_pixel
= 2;
1893 var
->xres
= sttt_xres
;
1894 var
->yres
= st_yres
;
1895 var
->bits_per_pixel
= 1;
1898 var
->blue
= var
->green
= var
->red
;
1899 var
->transp
.offset
= 0;
1900 var
->transp
.length
= 0;
1901 var
->transp
.msb_right
= 0;
1902 var
->xres_virtual
= sttt_xres_virtual
;
1903 linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
1904 ovsc_addlen
= linelen
* (sttt_yres_virtual
- st_yres
);
1907 var
->yres_virtual
= var
->yres
;
1908 else if (screen_len
) {
1909 if (par
->yres_virtual
)
1910 var
->yres_virtual
= par
->yres_virtual
;
1912 /* yres_virtual == 0 means use maximum */
1913 var
->yres_virtual
= screen_len
/ linelen
;
1916 var
->yres_virtual
= 2 * var
->yres
;
1918 var
->yres_virtual
= var
->yres
+ hwscroll
* 16;
1922 var
->yoffset
= (par
->screen_base
- screen_base
) / linelen
;
1927 var
->vmode
= FB_VMODE_NONINTERLACED
;
1931 static void stste_get_par(struct atafb_par
*par
)
1934 par
->hw
.st
.mode
= shifter_tt
.st_shiftmode
;
1935 par
->hw
.st
.sync
= shifter_st
.syncmode
;
1936 addr
= ((shifter_st
.bas_hi
& 0xff) << 16) |
1937 ((shifter_st
.bas_md
& 0xff) << 8);
1938 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
1939 addr
|= (shifter_st
.bas_lo
& 0xff);
1940 par
->screen_base
= atari_stram_to_virt(addr
);
1943 static void stste_set_par(struct atafb_par
*par
)
1945 shifter_tt
.st_shiftmode
= par
->hw
.st
.mode
;
1946 shifter_st
.syncmode
= par
->hw
.st
.sync
;
1947 /* only set screen_base if really necessary */
1948 if (current_par
.screen_base
!= par
->screen_base
)
1949 fbhw
->set_screen_base(par
->screen_base
);
1952 static int stste_setcolreg(unsigned int regno
, unsigned int red
,
1953 unsigned int green
, unsigned int blue
,
1954 unsigned int transp
, struct fb_info
*info
)
1961 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
1962 shifter_tt
.color_reg
[regno
] =
1963 ((((red
& 0xe) >> 1) | ((red
& 1) << 3)) << 8) |
1964 ((((green
& 0xe) >> 1) | ((green
& 1) << 3)) << 4) |
1965 ((blue
& 0xe) >> 1) | ((blue
& 1) << 3);
1967 shifter_tt
.color_reg
[regno
] =
1968 ((red
& 0xe) << 7) |
1969 ((green
& 0xe) << 3) |
1970 ((blue
& 0xe) >> 1);
1974 static int stste_detect(void)
1976 struct atafb_par par
;
1978 /* Determine the connected monitor: The DMA sound must be
1979 * disabled before reading the MFP GPIP, because the Sound
1980 * Done Signal and the Monochrome Detect are XORed together!
1982 if (ATARIHW_PRESENT(PCM_8BIT
)) {
1983 tt_dmasnd
.ctrl
= DMASND_CTRL_OFF
;
1984 udelay(20); /* wait a while for things to settle down */
1986 mono_moni
= (st_mfp
.par_dt_reg
& 0x80) == 0;
1988 stste_get_par(&par
);
1989 stste_encode_var(&atafb_predefined
[0], &par
);
1991 if (!ATARIHW_PRESENT(EXTD_SHIFTER
))
1996 static void stste_set_screen_base(void *s_base
)
1999 addr
= atari_stram_to_phys(s_base
);
2000 /* Setup Screen Memory */
2001 shifter_st
.bas_hi
= (unsigned char)((addr
& 0xff0000) >> 16);
2002 shifter_st
.bas_md
= (unsigned char)((addr
& 0x00ff00) >> 8);
2003 if (ATARIHW_PRESENT(EXTD_SHIFTER
))
2004 shifter_st
.bas_lo
= (unsigned char)(addr
& 0x0000ff);
2007 #endif /* ATAFB_STE */
2009 /* Switching the screen size should be done during vsync, otherwise
2010 * the margins may get messed up. This is a well known problem of
2011 * the ST's video system.
2013 * Unfortunately there is hardly any way to find the vsync, as the
2014 * vertical blank interrupt is no longer in time on machines with
2015 * overscan type modifications.
2017 * We can, however, use Timer B to safely detect the black shoulder,
2018 * but then we've got to guess an appropriate delay to find the vsync.
2019 * This might not work on every machine.
2021 * martin_rogge @ ki.maus.de, 8th Aug 1995
2024 #define LINE_DELAY (mono_moni ? 30 : 70)
2025 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2027 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2028 static void st_ovsc_switch(void)
2030 unsigned long flags
;
2031 register unsigned char old
, new;
2033 if (!(atari_switches
& ATARI_SWITCH_OVSC_MASK
))
2035 local_irq_save(flags
);
2037 st_mfp
.tim_ct_b
= 0x10;
2038 st_mfp
.active_edge
|= 8;
2039 st_mfp
.tim_ct_b
= 0;
2040 st_mfp
.tim_dt_b
= 0xf0;
2041 st_mfp
.tim_ct_b
= 8;
2042 while (st_mfp
.tim_dt_b
> 1) /* TOS does it this way, don't ask why */
2044 new = st_mfp
.tim_dt_b
;
2048 new = st_mfp
.tim_dt_b
;
2049 } while (old
!= new);
2050 st_mfp
.tim_ct_b
= 0x10;
2053 if (atari_switches
& ATARI_SWITCH_OVSC_IKBD
)
2054 acia
.key_ctrl
= ACIA_DIV64
| ACIA_D8N1S
| ACIA_RHTID
| ACIA_RIE
;
2055 if (atari_switches
& ATARI_SWITCH_OVSC_MIDI
)
2056 acia
.mid_ctrl
= ACIA_DIV16
| ACIA_D8N1S
| ACIA_RHTID
;
2057 if (atari_switches
& (ATARI_SWITCH_OVSC_SND6
|ATARI_SWITCH_OVSC_SND7
)) {
2058 sound_ym
.rd_data_reg_sel
= 14;
2059 sound_ym
.wd_data
= sound_ym
.rd_data_reg_sel
|
2060 ((atari_switches
& ATARI_SWITCH_OVSC_SND6
) ? 0x40:0) |
2061 ((atari_switches
& ATARI_SWITCH_OVSC_SND7
) ? 0x80:0);
2063 local_irq_restore(flags
);
2066 /* ------------------- External Video ---------------------- */
2070 static int ext_encode_fix(struct fb_fix_screeninfo
*fix
, struct atafb_par
*par
)
2072 strcpy(fix
->id
, "Unknown Extern");
2073 fix
->smem_start
= external_addr
;
2074 fix
->smem_len
= PAGE_ALIGN(external_len
);
2075 if (external_depth
== 1) {
2076 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2077 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2078 * for "normal" and "inverted", rsp., in the monochrome case */
2080 (external_pmode
== FB_TYPE_INTERLEAVED_PLANES
||
2081 external_pmode
== FB_TYPE_PACKED_PIXELS
) ?
2082 FB_VISUAL_MONO10
: FB_VISUAL_MONO01
;
2084 /* Use STATIC if we don't know how to access color registers */
2085 int visual
= external_vgaiobase
?
2086 FB_VISUAL_PSEUDOCOLOR
:
2087 FB_VISUAL_STATIC_PSEUDOCOLOR
;
2088 switch (external_pmode
) {
2089 case -1: /* truecolor */
2090 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2091 fix
->visual
= FB_VISUAL_TRUECOLOR
;
2093 case FB_TYPE_PACKED_PIXELS
:
2094 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2095 fix
->visual
= visual
;
2097 case FB_TYPE_PLANES
:
2098 fix
->type
= FB_TYPE_PLANES
;
2099 fix
->visual
= visual
;
2101 case FB_TYPE_INTERLEAVED_PLANES
:
2102 fix
->type
= FB_TYPE_INTERLEAVED_PLANES
;
2104 fix
->visual
= visual
;
2111 fix
->line_length
= par
->next_line
;
2115 static int ext_decode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
2117 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
2119 if (var
->bits_per_pixel
> myvar
->bits_per_pixel
||
2120 var
->xres
> myvar
->xres
||
2121 var
->xres_virtual
> myvar
->xres_virtual
||
2122 var
->yres
> myvar
->yres
||
2127 par
->next_line
= external_xres_virtual
* external_depth
/ 8;
2131 static int ext_encode_var(struct fb_var_screeninfo
*var
, struct atafb_par
*par
)
2133 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
2134 var
->red
.offset
= 0;
2135 var
->red
.length
= (external_pmode
== -1) ? external_depth
/ 3 :
2136 (external_vgaiobase
? external_bitspercol
: 0);
2137 var
->red
.msb_right
= 0;
2140 var
->pixclock
= 31041;
2141 var
->left_margin
= 120; /* these are surely incorrect */
2142 var
->right_margin
= 100;
2143 var
->upper_margin
= 8;
2144 var
->lower_margin
= 16;
2145 var
->hsync_len
= 140;
2146 var
->vsync_len
= 30;
2153 var
->xres
= external_xres
;
2154 var
->yres
= external_yres
;
2155 var
->xres_virtual
= external_xres_virtual
;
2156 var
->bits_per_pixel
= external_depth
;
2158 var
->blue
= var
->green
= var
->red
;
2159 var
->transp
.offset
= 0;
2160 var
->transp
.length
= 0;
2161 var
->transp
.msb_right
= 0;
2162 var
->yres_virtual
= var
->yres
;
2167 var
->vmode
= FB_VMODE_NONINTERLACED
;
2171 static void ext_get_par(struct atafb_par
*par
)
2173 par
->screen_base
= external_screen_base
;
2176 static void ext_set_par(struct atafb_par
*par
)
2180 #define OUTB(port,val) \
2181 *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2183 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2186 unsigned char tmp = INB(0x3da); \
2190 static int ext_setcolreg(unsigned int regno
, unsigned int red
,
2191 unsigned int green
, unsigned int blue
,
2192 unsigned int transp
, struct fb_info
*info
)
2194 unsigned char colmask
= (1 << external_bitspercol
) - 1;
2196 if (!external_vgaiobase
)
2206 switch (external_card_type
) {
2210 OUTB(0x3c9, red
& colmask
);
2212 OUTB(0x3c9, green
& colmask
);
2214 OUTB(0x3c9, blue
& colmask
);
2219 OUTB((MV300_reg
[regno
] << 2) + 1, red
);
2220 OUTB((MV300_reg
[regno
] << 2) + 1, green
);
2221 OUTB((MV300_reg
[regno
] << 2) + 1, blue
);
2229 static int ext_detect(void)
2231 struct fb_var_screeninfo
*myvar
= &atafb_predefined
[0];
2232 struct atafb_par dummy_par
;
2234 myvar
->xres
= external_xres
;
2235 myvar
->xres_virtual
= external_xres_virtual
;
2236 myvar
->yres
= external_yres
;
2237 myvar
->bits_per_pixel
= external_depth
;
2238 ext_encode_var(myvar
, &dummy_par
);
2242 #endif /* ATAFB_EXT */
2244 /* ------ This is the same for most hardware types -------- */
2246 static void set_screen_base(void *s_base
)
2250 addr
= atari_stram_to_phys(s_base
);
2251 /* Setup Screen Memory */
2252 shifter_st
.bas_hi
= (unsigned char)((addr
& 0xff0000) >> 16);
2253 shifter_st
.bas_md
= (unsigned char)((addr
& 0x00ff00) >> 8);
2254 shifter_st
.bas_lo
= (unsigned char)(addr
& 0x0000ff);
2257 static int pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2259 struct atafb_par
*par
= info
->par
;
2261 if (!fbhw
->set_screen_base
||
2262 (!ATARIHW_PRESENT(EXTD_SHIFTER
) && var
->xoffset
))
2264 var
->xoffset
= round_up(var
->xoffset
, 16);
2265 par
->screen_base
= screen_base
+
2266 (var
->yoffset
* info
->var
.xres_virtual
+ var
->xoffset
)
2267 * info
->var
.bits_per_pixel
/ 8;
2268 fbhw
->set_screen_base(par
->screen_base
);
2272 /* ------------ Interfaces to hardware functions ------------ */
2275 static struct fb_hwswitch tt_switch
= {
2276 .detect
= tt_detect
,
2277 .encode_fix
= tt_encode_fix
,
2278 .decode_var
= tt_decode_var
,
2279 .encode_var
= tt_encode_var
,
2280 .get_par
= tt_get_par
,
2281 .set_par
= tt_set_par
,
2282 .set_screen_base
= set_screen_base
,
2283 .pan_display
= pan_display
,
2288 static struct fb_hwswitch falcon_switch
= {
2289 .detect
= falcon_detect
,
2290 .encode_fix
= falcon_encode_fix
,
2291 .decode_var
= falcon_decode_var
,
2292 .encode_var
= falcon_encode_var
,
2293 .get_par
= falcon_get_par
,
2294 .set_par
= falcon_set_par
,
2295 .set_screen_base
= set_screen_base
,
2296 .blank
= falcon_blank
,
2297 .pan_display
= falcon_pan_display
,
2302 static struct fb_hwswitch st_switch
= {
2303 .detect
= stste_detect
,
2304 .encode_fix
= stste_encode_fix
,
2305 .decode_var
= stste_decode_var
,
2306 .encode_var
= stste_encode_var
,
2307 .get_par
= stste_get_par
,
2308 .set_par
= stste_set_par
,
2309 .set_screen_base
= stste_set_screen_base
,
2310 .pan_display
= pan_display
2315 static struct fb_hwswitch ext_switch
= {
2316 .detect
= ext_detect
,
2317 .encode_fix
= ext_encode_fix
,
2318 .decode_var
= ext_decode_var
,
2319 .encode_var
= ext_encode_var
,
2320 .get_par
= ext_get_par
,
2321 .set_par
= ext_set_par
,
2325 static void ata_get_par(struct atafb_par
*par
)
2327 if (current_par_valid
)
2333 static void ata_set_par(struct atafb_par
*par
)
2337 current_par_valid
= 1;
2341 /* =========================================================== */
2342 /* ============== Hardware Independent Functions ============= */
2343 /* =========================================================== */
2345 /* used for hardware scrolling */
2347 static int do_fb_set_var(struct fb_var_screeninfo
*var
, int isactive
)
2350 struct atafb_par par
;
2352 err
= fbhw
->decode_var(var
, &par
);
2355 activate
= var
->activate
;
2356 if (((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) && isactive
)
2358 fbhw
->encode_var(var
, &par
);
2359 var
->activate
= activate
;
2363 /* fbhw->encode_fix() must be called with fb_info->mm_lock held
2364 * if it is called after the register_framebuffer() - not a case here
2366 static int atafb_get_fix(struct fb_fix_screeninfo
*fix
, struct fb_info
*info
)
2368 struct atafb_par par
;
2370 // Get fix directly (case con == -1 before)??
2371 err
= fbhw
->decode_var(&info
->var
, &par
);
2374 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
2375 err
= fbhw
->encode_fix(fix
, &par
);
2379 static int atafb_get_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2381 struct atafb_par par
;
2384 fbhw
->encode_var(var
, &par
);
2389 // No longer called by fbcon!
2390 // Still called by set_var internally
2392 static void atafb_set_disp(struct fb_info
*info
)
2394 atafb_get_var(&info
->var
, info
);
2395 atafb_get_fix(&info
->fix
, info
);
2397 /* Note: smem_start derives from phys_screen_base, not screen_base! */
2398 info
->screen_base
= (external_addr
? external_screen_base
:
2399 atari_stram_to_virt(info
->fix
.smem_start
));
2403 atafb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2405 if (!fbhw
->pan_display
)
2408 return fbhw
->pan_display(var
, info
);
2412 * generic drawing routines; imageblit needs updating for image depth > 1
2415 static void atafb_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
2417 struct atafb_par
*par
= info
->par
;
2421 if (!rect
->width
|| !rect
->height
)
2425 if (info
->var
.bits_per_pixel
== 16) {
2426 cfb_fillrect(info
, rect
);
2432 * We could use hardware clipping but on many cards you get around
2433 * hardware clipping by writing to framebuffer directly.
2435 x2
= rect
->dx
+ rect
->width
;
2436 y2
= rect
->dy
+ rect
->height
;
2437 x2
= x2
< info
->var
.xres_virtual
? x2
: info
->var
.xres_virtual
;
2438 y2
= y2
< info
->var
.yres_virtual
? y2
: info
->var
.yres_virtual
;
2439 width
= x2
- rect
->dx
;
2440 height
= y2
- rect
->dy
;
2442 if (info
->var
.bits_per_pixel
== 1)
2443 atafb_mfb_fillrect(info
, par
->next_line
, rect
->color
,
2444 rect
->dy
, rect
->dx
, height
, width
);
2445 else if (info
->var
.bits_per_pixel
== 2)
2446 atafb_iplan2p2_fillrect(info
, par
->next_line
, rect
->color
,
2447 rect
->dy
, rect
->dx
, height
, width
);
2448 else if (info
->var
.bits_per_pixel
== 4)
2449 atafb_iplan2p4_fillrect(info
, par
->next_line
, rect
->color
,
2450 rect
->dy
, rect
->dx
, height
, width
);
2452 atafb_iplan2p8_fillrect(info
, par
->next_line
, rect
->color
,
2453 rect
->dy
, rect
->dx
, height
, width
);
2458 static void atafb_copyarea(struct fb_info
*info
, const struct fb_copyarea
*area
)
2460 struct atafb_par
*par
= info
->par
;
2462 u32 dx
, dy
, sx
, sy
, width
, height
;
2466 if (info
->var
.bits_per_pixel
== 16) {
2467 cfb_copyarea(info
, area
);
2472 /* clip the destination */
2473 x2
= area
->dx
+ area
->width
;
2474 y2
= area
->dy
+ area
->height
;
2475 dx
= area
->dx
> 0 ? area
->dx
: 0;
2476 dy
= area
->dy
> 0 ? area
->dy
: 0;
2477 x2
= x2
< info
->var
.xres_virtual
? x2
: info
->var
.xres_virtual
;
2478 y2
= y2
< info
->var
.yres_virtual
? y2
: info
->var
.yres_virtual
;
2482 if (area
->sx
+ dx
< area
->dx
|| area
->sy
+ dy
< area
->dy
)
2486 sx
= area
->sx
+ (dx
- area
->dx
);
2487 sy
= area
->sy
+ (dy
- area
->dy
);
2489 /* the source must be completely inside the virtual screen */
2490 if (sx
+ width
> info
->var
.xres_virtual
||
2491 sy
+ height
> info
->var
.yres_virtual
)
2494 if (dy
> sy
|| (dy
== sy
&& dx
> sx
)) {
2500 if (info
->var
.bits_per_pixel
== 1)
2501 atafb_mfb_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2502 else if (info
->var
.bits_per_pixel
== 2)
2503 atafb_iplan2p2_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2504 else if (info
->var
.bits_per_pixel
== 4)
2505 atafb_iplan2p4_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2507 atafb_iplan2p8_copyarea(info
, par
->next_line
, sy
, sx
, dy
, dx
, height
, width
);
2512 static void atafb_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
2514 struct atafb_par
*par
= info
->par
;
2517 u32 dx
, dy
, width
, height
, pitch
;
2520 if (info
->var
.bits_per_pixel
== 16) {
2521 cfb_imageblit(info
, image
);
2527 * We could use hardware clipping but on many cards you get around
2528 * hardware clipping by writing to framebuffer directly like we are
2531 x2
= image
->dx
+ image
->width
;
2532 y2
= image
->dy
+ image
->height
;
2535 x2
= x2
< info
->var
.xres_virtual
? x2
: info
->var
.xres_virtual
;
2536 y2
= y2
< info
->var
.yres_virtual
? y2
: info
->var
.yres_virtual
;
2540 if (image
->depth
== 1) {
2541 // used for font data
2543 pitch
= (image
->width
+ 7) / 8;
2546 if (info
->var
.bits_per_pixel
== 1)
2547 atafb_mfb_linefill(info
, par
->next_line
,
2549 image
->bg_color
, image
->fg_color
);
2550 else if (info
->var
.bits_per_pixel
== 2)
2551 atafb_iplan2p2_linefill(info
, par
->next_line
,
2553 image
->bg_color
, image
->fg_color
);
2554 else if (info
->var
.bits_per_pixel
== 4)
2555 atafb_iplan2p4_linefill(info
, par
->next_line
,
2557 image
->bg_color
, image
->fg_color
);
2559 atafb_iplan2p8_linefill(info
, par
->next_line
,
2561 image
->bg_color
, image
->fg_color
);
2566 c2p_iplan2(info
->screen_base
, image
->data
, dx
, dy
, width
,
2567 height
, par
->next_line
, image
->width
,
2568 info
->var
.bits_per_pixel
);
2573 atafb_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
2576 #ifdef FBCMD_GET_CURRENTPAR
2577 case FBCMD_GET_CURRENTPAR
:
2578 if (copy_to_user((void *)arg
, ¤t_par
,
2579 sizeof(struct atafb_par
)))
2583 #ifdef FBCMD_SET_CURRENTPAR
2584 case FBCMD_SET_CURRENTPAR
:
2585 if (copy_from_user(¤t_par
, (void *)arg
,
2586 sizeof(struct atafb_par
)))
2588 ata_set_par(¤t_par
);
2595 /* (un)blank/poweroff
2602 static int atafb_blank(int blank
, struct fb_info
*info
)
2604 unsigned short black
[16];
2605 struct fb_cmap cmap
;
2606 if (fbhw
->blank
&& !fbhw
->blank(blank
))
2609 memset(black
, 0, 16 * sizeof(unsigned short));
2616 fb_set_cmap(&cmap
, info
);
2620 do_install_cmap(info
);
2626 * New fbcon interface ...
2629 /* check var by decoding var into hw par, rounding if necessary,
2630 * then encoding hw par back into new, validated var */
2631 static int atafb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
2634 struct atafb_par par
;
2636 /* Validate wanted screen parameters */
2637 // if ((err = ata_decode_var(var, &par)))
2638 err
= fbhw
->decode_var(var
, &par
);
2642 /* Encode (possibly rounded) screen parameters */
2643 fbhw
->encode_var(var
, &par
);
2647 /* actually set hw par by decoding var, then setting hardware from
2648 * hw par just decoded */
2649 static int atafb_set_par(struct fb_info
*info
)
2651 struct atafb_par
*par
= info
->par
;
2653 /* Decode wanted screen parameters */
2654 fbhw
->decode_var(&info
->var
, par
);
2655 mutex_lock(&info
->mm_lock
);
2656 fbhw
->encode_fix(&info
->fix
, par
);
2657 mutex_unlock(&info
->mm_lock
);
2659 /* Set new videomode */
2666 static struct fb_ops atafb_ops
= {
2667 .owner
= THIS_MODULE
,
2668 __FB_DEFAULT_IOMEM_OPS_RDWR
,
2669 .fb_check_var
= atafb_check_var
,
2670 .fb_set_par
= atafb_set_par
,
2671 .fb_blank
= atafb_blank
,
2672 .fb_pan_display
= atafb_pan_display
,
2673 .fb_fillrect
= atafb_fillrect
,
2674 .fb_copyarea
= atafb_copyarea
,
2675 .fb_imageblit
= atafb_imageblit
,
2676 .fb_ioctl
= atafb_ioctl
,
2677 __FB_DEFAULT_IOMEM_OPS_MMAP
,
2680 static void check_default_par(int detected_mode
)
2682 char default_name
[10];
2684 struct fb_var_screeninfo var
;
2685 unsigned long min_mem
;
2687 /* First try the user supplied mode */
2689 var
= atafb_predefined
[default_par
- 1];
2690 var
.activate
= FB_ACTIVATE_TEST
;
2691 if (do_fb_set_var(&var
, 1))
2692 default_par
= 0; /* failed */
2694 /* Next is the autodetected one */
2696 var
= atafb_predefined
[detected_mode
- 1]; /* autodetect */
2697 var
.activate
= FB_ACTIVATE_TEST
;
2698 if (!do_fb_set_var(&var
, 1))
2699 default_par
= detected_mode
;
2701 /* If that also failed, try some default modes... */
2703 /* try default1, default2... */
2704 for (i
= 1; i
< 10; i
++) {
2705 sprintf(default_name
,"default%d", i
);
2706 default_par
= get_video_mode(default_name
);
2708 panic("can't set default video mode");
2709 var
= atafb_predefined
[default_par
- 1];
2710 var
.activate
= FB_ACTIVATE_TEST
;
2711 if (!do_fb_set_var(&var
,1))
2715 min_mem
= var
.xres_virtual
* var
.yres_virtual
* var
.bits_per_pixel
/ 8;
2716 if (default_mem_req
< min_mem
)
2717 default_mem_req
= min_mem
;
2721 static void __init
atafb_setup_ext(char *spec
)
2723 int xres
, xres_virtual
, yres
, depth
, planes
;
2724 unsigned long addr
, len
;
2727 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2729 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2730 * [;<xres-virtual>]]]]]
2733 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2735 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2737 p
= strsep(&spec
, ";");
2740 xres_virtual
= xres
= simple_strtoul(p
, NULL
, 10);
2744 p
= strsep(&spec
, ";");
2747 yres
= simple_strtoul(p
, NULL
, 10);
2751 p
= strsep(&spec
, ";");
2754 depth
= simple_strtoul(p
, NULL
, 10);
2755 if (depth
!= 1 && depth
!= 2 && depth
!= 4 && depth
!= 8 &&
2756 depth
!= 16 && depth
!= 24)
2759 p
= strsep(&spec
, ";");
2763 planes
= FB_TYPE_INTERLEAVED_PLANES
;
2765 planes
= FB_TYPE_PACKED_PIXELS
;
2767 planes
= FB_TYPE_PLANES
;
2769 planes
= -1; /* true color */
2773 p
= strsep(&spec
, ";");
2776 addr
= simple_strtoul(p
, NULL
, 0);
2778 p
= strsep(&spec
, ";");
2780 len
= xres
* yres
* depth
/ 8;
2782 len
= simple_strtoul(p
, NULL
, 0);
2784 p
= strsep(&spec
, ";");
2786 external_vgaiobase
= simple_strtoul(p
, NULL
, 0);
2788 p
= strsep(&spec
, ";");
2790 external_bitspercol
= simple_strtoul(p
, NULL
, 0);
2791 if (external_bitspercol
> 8)
2792 external_bitspercol
= 8;
2793 else if (external_bitspercol
< 1)
2794 external_bitspercol
= 1;
2797 p
= strsep(&spec
, ";");
2799 if (!strcmp(p
, "vga"))
2800 external_card_type
= IS_VGA
;
2801 if (!strcmp(p
, "mv300"))
2802 external_card_type
= IS_MV300
;
2805 p
= strsep(&spec
, ";");
2807 xres_virtual
= simple_strtoul(p
, NULL
, 10);
2808 if (xres_virtual
< xres
)
2809 xres_virtual
= xres
;
2810 if (xres_virtual
* yres
* depth
/ 8 > len
)
2811 len
= xres_virtual
* yres
* depth
/ 8;
2814 external_xres
= xres
;
2815 external_xres_virtual
= xres_virtual
;
2816 external_yres
= yres
;
2817 external_depth
= depth
;
2818 external_pmode
= planes
;
2819 external_addr
= addr
;
2822 if (external_card_type
== IS_MV300
) {
2823 switch (external_depth
) {
2825 MV300_reg
= MV300_reg_1bit
;
2828 MV300_reg
= MV300_reg_4bit
;
2831 MV300_reg
= MV300_reg_8bit
;
2836 #endif /* ATAFB_EXT */
2838 static void __init
atafb_setup_int(char *spec
)
2840 /* Format to config extended internal video hardware like OverScan:
2841 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2843 * <xres>: x-resolution
2844 * <yres>: y-resolution
2845 * The following are only needed if you have an overscan which
2846 * needs a black border:
2847 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2848 * <yres_max>: max. number of lines your OverScan hardware would allow
2849 * <offset>: Offset from physical beginning to visible beginning
2850 * of screen in bytes
2855 if (!(p
= strsep(&spec
, ";")) || !*p
)
2857 xres
= simple_strtoul(p
, NULL
, 10);
2858 if (!(p
= strsep(&spec
, ";")) || !*p
)
2861 tt_yres
= st_yres
= simple_strtoul(p
, NULL
, 10);
2862 if ((p
= strsep(&spec
, ";")) && *p
)
2863 sttt_xres_virtual
= simple_strtoul(p
, NULL
, 10);
2864 if ((p
= strsep(&spec
, ";")) && *p
)
2865 sttt_yres_virtual
= simple_strtoul(p
, NULL
, 0);
2866 if ((p
= strsep(&spec
, ";")) && *p
)
2867 ovsc_offset
= simple_strtoul(p
, NULL
, 0);
2869 if (ovsc_offset
|| (sttt_yres_virtual
!= st_yres
))
2874 static void __init
atafb_setup_mcap(char *spec
)
2877 int vmin
, vmax
, hmin
, hmax
;
2879 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2880 * <V*> vertical freq. in Hz
2881 * <H*> horizontal freq. in kHz
2883 if (!(p
= strsep(&spec
, ";")) || !*p
)
2885 vmin
= simple_strtoul(p
, NULL
, 10);
2888 if (!(p
= strsep(&spec
, ";")) || !*p
)
2890 vmax
= simple_strtoul(p
, NULL
, 10);
2891 if (vmax
<= 0 || vmax
<= vmin
)
2893 if (!(p
= strsep(&spec
, ";")) || !*p
)
2895 hmin
= 1000 * simple_strtoul(p
, NULL
, 10);
2898 if (!(p
= strsep(&spec
, "")) || !*p
)
2900 hmax
= 1000 * simple_strtoul(p
, NULL
, 10);
2901 if (hmax
<= 0 || hmax
<= hmin
)
2904 fb_info
.monspecs
.vfmin
= vmin
;
2905 fb_info
.monspecs
.vfmax
= vmax
;
2906 fb_info
.monspecs
.hfmin
= hmin
;
2907 fb_info
.monspecs
.hfmax
= hmax
;
2909 #endif /* ATAFB_FALCON */
2911 static void __init
atafb_setup_user(char *spec
)
2913 /* Format of user defined video mode is: <xres>;<yres>;<depth>
2916 int xres
, yres
, depth
, temp
;
2918 p
= strsep(&spec
, ";");
2921 xres
= simple_strtoul(p
, NULL
, 10);
2922 p
= strsep(&spec
, ";");
2925 yres
= simple_strtoul(p
, NULL
, 10);
2926 p
= strsep(&spec
, "");
2929 depth
= simple_strtoul(p
, NULL
, 10);
2930 temp
= get_video_mode("user0");
2933 atafb_predefined
[default_par
- 1].xres
= xres
;
2934 atafb_predefined
[default_par
- 1].yres
= yres
;
2935 atafb_predefined
[default_par
- 1].bits_per_pixel
= depth
;
2939 static int __init
atafb_setup(char *options
)
2944 if (!options
|| !*options
)
2947 while ((this_opt
= strsep(&options
, ",")) != NULL
) {
2950 if ((temp
= get_video_mode(this_opt
))) {
2952 mode_option
= this_opt
;
2953 } else if (!strcmp(this_opt
, "inverse"))
2955 else if (!strncmp(this_opt
, "hwscroll_", 9)) {
2956 hwscroll
= simple_strtoul(this_opt
+ 9, NULL
, 10);
2963 else if (!strcmp(this_opt
, "mv300")) {
2964 external_bitspercol
= 8;
2965 external_card_type
= IS_MV300
;
2966 } else if (!strncmp(this_opt
, "external:", 9))
2967 atafb_setup_ext(this_opt
+ 9);
2969 else if (!strncmp(this_opt
, "internal:", 9))
2970 atafb_setup_int(this_opt
+ 9);
2972 else if (!strncmp(this_opt
, "eclock:", 7)) {
2973 fext
.f
= simple_strtoul(this_opt
+ 7, NULL
, 10);
2974 /* external pixelclock in kHz --> ps */
2975 fext
.t
= 1000000000 / fext
.f
;
2977 } else if (!strncmp(this_opt
, "monitorcap:", 11))
2978 atafb_setup_mcap(this_opt
+ 11);
2980 else if (!strcmp(this_opt
, "keep"))
2982 else if (!strncmp(this_opt
, "R", 1))
2983 atafb_setup_user(this_opt
+ 1);
2988 static int __init
atafb_probe(struct platform_device
*pdev
)
2990 int pad
, detected_mode
, error
;
2991 unsigned int defmode
= 0;
2992 unsigned long mem_req
;
2993 char *option
= NULL
;
2995 if (fb_get_options("atafb", &option
))
2997 atafb_setup(option
);
2998 dev_dbg(&pdev
->dev
, "%s: start\n", __func__
);
3002 if (external_addr
) {
3003 dev_dbg(&pdev
->dev
, "initializing external hw\n");
3005 atafb_ops
.fb_setcolreg
= &ext_setcolreg
;
3006 defmode
= DEFMODE_EXT
;
3011 if (ATARIHW_PRESENT(TT_SHIFTER
)) {
3012 dev_dbg(&pdev
->dev
, "initializing TT hw\n");
3014 atafb_ops
.fb_setcolreg
= &tt_setcolreg
;
3015 defmode
= DEFMODE_TT
;
3020 if (ATARIHW_PRESENT(VIDEL_SHIFTER
)) {
3021 dev_dbg(&pdev
->dev
, "initializing Falcon hw\n");
3022 fbhw
= &falcon_switch
;
3023 atafb_ops
.fb_setcolreg
= &falcon_setcolreg
;
3024 error
= request_irq(IRQ_AUTO_4
, falcon_vbl_switcher
, 0,
3025 "framebuffer:modeswitch",
3026 falcon_vbl_switcher
);
3029 defmode
= DEFMODE_F30
;
3034 if (ATARIHW_PRESENT(STND_SHIFTER
) ||
3035 ATARIHW_PRESENT(EXTD_SHIFTER
)) {
3036 dev_dbg(&pdev
->dev
, "initializing ST/E hw\n");
3038 atafb_ops
.fb_setcolreg
= &stste_setcolreg
;
3039 defmode
= DEFMODE_STE
;
3043 atafb_ops
.fb_setcolreg
= &stste_setcolreg
;
3044 dev_warn(&pdev
->dev
,
3045 "Cannot determine video hardware; defaulting to ST(e)\n");
3046 #else /* ATAFB_STE */
3047 /* no default driver included */
3048 /* Nobody will ever see this message :-) */
3049 panic("Cannot initialize video hardware");
3053 /* Multisync monitor capabilities */
3054 /* Atari-TOS defaults if no boot option present */
3055 if (fb_info
.monspecs
.hfmin
== 0) {
3056 fb_info
.monspecs
.hfmin
= 31000;
3057 fb_info
.monspecs
.hfmax
= 32000;
3058 fb_info
.monspecs
.vfmin
= 58;
3059 fb_info
.monspecs
.vfmax
= 62;
3062 detected_mode
= fbhw
->detect();
3063 check_default_par(detected_mode
);
3065 if (!external_addr
) {
3066 #endif /* ATAFB_EXT */
3067 mem_req
= default_mem_req
+ ovsc_offset
+ ovsc_addlen
;
3068 mem_req
= PAGE_ALIGN(mem_req
) + PAGE_SIZE
;
3069 screen_base
= atari_stram_alloc(mem_req
, "atafb");
3071 panic("Cannot allocate screen memory");
3072 memset(screen_base
, 0, mem_req
);
3073 pad
= -(unsigned long)screen_base
& (PAGE_SIZE
- 1);
3075 phys_screen_base
= atari_stram_to_phys(screen_base
+ ovsc_offset
);
3076 screen_len
= (mem_req
- pad
- ovsc_offset
) & PAGE_MASK
;
3078 if (CPU_IS_040_OR_060
) {
3079 /* On a '040+, the cache mode of video RAM must be set to
3080 * write-through also for internal video hardware! */
3081 cache_push(atari_stram_to_phys(screen_base
), screen_len
);
3082 kernel_set_cachemode(screen_base
, screen_len
,
3083 IOMAP_WRITETHROUGH
);
3085 dev_info(&pdev
->dev
, "phys_screen_base %lx screen_len %d\n",
3086 phys_screen_base
, screen_len
);
3089 /* Map the video memory (physical address given) to somewhere
3090 * in the kernel address space.
3092 external_screen_base
= ioremap_wt(external_addr
, external_len
);
3093 if (external_vgaiobase
)
3094 external_vgaiobase
=
3095 (unsigned long)ioremap(external_vgaiobase
, 0x10000);
3096 screen_base
= external_screen_base
;
3097 phys_screen_base
= external_addr
;
3098 screen_len
= external_len
& PAGE_MASK
;
3099 memset (screen_base
, 0, external_len
);
3101 #endif /* ATAFB_EXT */
3103 // strcpy(fb_info.mode->name, "Atari Builtin ");
3104 fb_info
.fbops
= &atafb_ops
;
3105 // try to set default (detected; requested) var
3106 do_fb_set_var(&atafb_predefined
[default_par
- 1], 1);
3107 // reads hw state into current par, which may not be sane yet
3108 ata_get_par(¤t_par
);
3109 fb_info
.par
= ¤t_par
;
3110 // tries to read from HW which may not be initialized yet
3111 // so set sane var first, then call atafb_set_par
3112 atafb_get_var(&fb_info
.var
, &fb_info
);
3115 fb_info
.pseudo_palette
= current_par
.hw
.falcon
.pseudo_palette
;
3118 if (!fb_find_mode(&fb_info
.var
, &fb_info
, mode_option
, atafb_modedb
,
3119 NUM_TOTAL_MODES
, &atafb_modedb
[defmode
],
3120 fb_info
.var
.bits_per_pixel
)) {
3124 fb_videomode_to_modelist(atafb_modedb
, NUM_TOTAL_MODES
,
3127 atafb_set_disp(&fb_info
);
3129 fb_alloc_cmap(&(fb_info
.cmap
), 1 << fb_info
.var
.bits_per_pixel
, 0);
3132 dev_info(&pdev
->dev
, "Determined %dx%d, depth %d\n", fb_info
.var
.xres
,
3133 fb_info
.var
.yres
, fb_info
.var
.bits_per_pixel
);
3134 if ((fb_info
.var
.xres
!= fb_info
.var
.xres_virtual
) ||
3135 (fb_info
.var
.yres
!= fb_info
.var
.yres_virtual
))
3136 dev_info(&pdev
->dev
, " virtual %dx%d\n",
3137 fb_info
.var
.xres_virtual
, fb_info
.var
.yres_virtual
);
3139 if (register_framebuffer(&fb_info
) < 0) {
3141 if (external_addr
) {
3142 iounmap(external_screen_base
);
3145 if (external_vgaiobase
) {
3146 iounmap((void*)external_vgaiobase
);
3147 external_vgaiobase
= 0;
3153 fb_info(&fb_info
, "frame buffer device, using %dK of video memory\n",
3156 /* TODO: This driver cannot be unloaded yet */
3160 static void atafb_shutdown(struct platform_device
*pdev
)
3162 /* Unblank before kexec */
3167 static struct platform_driver atafb_driver
= {
3168 .shutdown
= atafb_shutdown
,
3174 static int __init
atafb_init(void)
3176 struct platform_device
*pdev
;
3181 pdev
= platform_device_register_simple("atafb", -1, NULL
, 0);
3183 return PTR_ERR(pdev
);
3185 return platform_driver_probe(&atafb_driver
, atafb_probe
);
3188 device_initcall(atafb_init
);