1 /*
2 * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
3 *
4 * Copyright (C) 1994 Martin Schaller & Roman Hodek
5 *
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
8 * for more details.
9 *
10 * History:
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
31 * supported.
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
38 *
39 * To do:
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.
42 *
43 */
44
45 #define ATAFB_TT
46 #define ATAFB_STE
47 #define ATAFB_EXT
48 #define ATAFB_FALCON
49
50 #include <linux/kernel.h>
51 #include <linux/errno.h>
52 #include <linux/string.h>
53 #include <linux/mm.h>
54 #include <linux/delay.h>
55 #include <linux/init.h>
56 #include <linux/interrupt.h>
57 #include <linux/platform_device.h>
58
59 #include <asm/setup.h>
60 #include <linux/uaccess.h>
61 #include <asm/irq.h>
62 #include <asm/io.h>
63
64 #include <asm/atarihw.h>
65 #include <asm/atariints.h>
66 #include <asm/atari_stram.h>
67
68 #include <linux/fb.h>
69 #include <asm/atarikb.h>
70
71 #include "c2p.h"
72 #include "atafb.h"
73
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
78
79 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
80
81
82 static int default_par; /* default resolution (0=none) */
83
84 static unsigned long default_mem_req;
85
86 static int hwscroll = -1;
87
88 static int use_hwscroll = 1;
89
90 static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
91 static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
92 static int ovsc_offset, ovsc_addlen;
93
94 /*
95 * Hardware parameters for current mode
96 */
97
98 static struct atafb_par {
99 void *screen_base;
100 int yres_virtual;
101 u_long next_line;
102 #if defined ATAFB_TT || defined ATAFB_STE
103 union {
104 struct {
105 int mode;
106 int sync;
107 } tt, st;
108 #endif
109 #ifdef ATAFB_FALCON
110 struct falcon_hw {
111 /* Here are fields for storing a video mode, as direct
112 * parameters for the hardware.
113 */
114 short sync;
115 short line_width;
116 short line_offset;
117 short st_shift;
118 short f_shift;
119 short vid_control;
120 short vid_mode;
121 short xoffset;
122 short hht, hbb, hbe, hdb, hde, hss;
123 short vft, vbb, vbe, vdb, vde, vss;
124 /* auxiliary information */
125 short mono;
126 short ste_mode;
127 short bpp;
128 u32 pseudo_palette[16];
129 } falcon;
130 #endif
131 /* Nothing needed for external mode */
132 } hw;
133 } current_par;
134
135 /* Don't calculate an own resolution, and thus don't change the one found when
136 * booting (currently used for the Falcon to keep settings for internal video
137 * hardware extensions (e.g. ScreenBlaster) */
138 static int DontCalcRes = 0;
139
140 #ifdef ATAFB_FALCON
141 #define HHT hw.falcon.hht
142 #define HBB hw.falcon.hbb
143 #define HBE hw.falcon.hbe
144 #define HDB hw.falcon.hdb
145 #define HDE hw.falcon.hde
146 #define HSS hw.falcon.hss
147 #define VFT hw.falcon.vft
148 #define VBB hw.falcon.vbb
149 #define VBE hw.falcon.vbe
150 #define VDB hw.falcon.vdb
151 #define VDE hw.falcon.vde
152 #define VSS hw.falcon.vss
153 #define VCO_CLOCK25 0x04
154 #define VCO_CSYPOS 0x10
155 #define VCO_VSYPOS 0x20
156 #define VCO_HSYPOS 0x40
157 #define VCO_SHORTOFFS 0x100
158 #define VMO_DOUBLE 0x01
159 #define VMO_INTER 0x02
160 #define VMO_PREMASK 0x0c
161 #endif
162
163 static struct fb_info fb_info = {
164 .fix = {
165 .id = "Atari ",
166 .visual = FB_VISUAL_PSEUDOCOLOR,
167 .accel = FB_ACCEL_NONE,
168 }
169 };
170
171 static void *screen_base; /* base address of screen */
172 static unsigned long phys_screen_base; /* (only for Overscan) */
173
174 static int screen_len;
175
176 static int current_par_valid;
177
178 static int mono_moni;
179
180
181 #ifdef ATAFB_EXT
182
183 /* external video handling */
184 static unsigned int external_xres;
185 static unsigned int external_xres_virtual;
186 static unsigned int external_yres;
187
188 /*
189 * not needed - atafb will never support panning/hardwarescroll with external
190 * static unsigned int external_yres_virtual;
191 */
192 static unsigned int external_depth;
193 static int external_pmode;
194 static void *external_screen_base;
195 static unsigned long external_addr;
196 static unsigned long external_len;
197 static unsigned long external_vgaiobase;
198 static unsigned int external_bitspercol = 6;
199
200 /*
201 * JOE <joe@amber.dinoco.de>:
202 * added card type for external driver, is only needed for
203 * colormap handling.
204 */
205 enum cardtype { IS_VGA, IS_MV300 };
206 static enum cardtype external_card_type = IS_VGA;
207
208 /*
209 * The MV300 mixes the color registers. So we need an array of munged
210 * indices in order to access the correct reg.
211 */
212 static int MV300_reg_1bit[2] = {
213 0, 1
214 };
215 static int MV300_reg_4bit[16] = {
216 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
217 };
218 static int MV300_reg_8bit[256] = {
219 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
220 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
221 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
222 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
223 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
224 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
225 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
226 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
227 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
228 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
229 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
230 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
231 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
232 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
233 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
234 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
235 };
236
237 static int *MV300_reg = MV300_reg_8bit;
238 #endif /* ATAFB_EXT */
239
240
241 static int inverse;
242
243 extern int fontheight_8x8;
244 extern int fontwidth_8x8;
245 extern unsigned char fontdata_8x8[];
246
247 extern int fontheight_8x16;
248 extern int fontwidth_8x16;
249 extern unsigned char fontdata_8x16[];
250
251 /*
252 * struct fb_ops {
253 * * open/release and usage marking
254 * struct module *owner;
255 * int (*fb_open)(struct fb_info *info, int user);
256 * int (*fb_release)(struct fb_info *info, int user);
257 *
258 * * For framebuffers with strange non linear layouts or that do not
259 * * work with normal memory mapped access
260 * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
261 * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
262 *
263 * * checks var and eventually tweaks it to something supported,
264 * * DOES NOT MODIFY PAR *
265 * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
266 *
267 * * set the video mode according to info->var *
268 * int (*fb_set_par)(struct fb_info *info);
269 *
270 * * set color register *
271 * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
272 * unsigned int blue, unsigned int transp, struct fb_info *info);
273 *
274 * * set color registers in batch *
275 * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
276 *
277 * * blank display *
278 * int (*fb_blank)(int blank, struct fb_info *info);
279 *
280 * * pan display *
281 * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
282 *
283 * *** The meat of the drawing engine ***
284 * * Draws a rectangle *
285 * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
286 * * Copy data from area to another *
287 * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
288 * * Draws a image to the display *
289 * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
290 *
291 * * Draws cursor *
292 * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
293 *
294 * * wait for blit idle, optional *
295 * int (*fb_sync)(struct fb_info *info);
296 *
297 * * perform fb specific ioctl (optional) *
298 * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
299 * unsigned long arg);
300 *
301 * * Handle 32bit compat ioctl (optional) *
302 * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
303 * unsigned long arg);
304 *
305 * * perform fb specific mmap *
306 * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
307 * } ;
308 */
309
310
311 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
312 * TT, or Falcon.
313 *
314 * int (*detect)(void)
315 * This function should detect the current video mode settings and
316 * store them in atafb_predefined[0] for later reference by the
317 * user. Return the index+1 of an equivalent predefined mode or 0
318 * if there is no such.
319 *
320 * int (*encode_fix)(struct fb_fix_screeninfo *fix,
321 * struct atafb_par *par)
322 * This function should fill in the 'fix' structure based on the
323 * values in the 'par' structure.
324 * !!! Obsolete, perhaps !!!
325 *
326 * int (*decode_var)(struct fb_var_screeninfo *var,
327 * struct atafb_par *par)
328 * Get the video params out of 'var'. If a value doesn't fit, round
329 * it up, if it's too big, return EINVAL.
330 * Round up in the following order: bits_per_pixel, xres, yres,
331 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
332 * horizontal timing, vertical timing.
333 *
334 * int (*encode_var)(struct fb_var_screeninfo *var,
335 * struct atafb_par *par);
336 * Fill the 'var' structure based on the values in 'par' and maybe
337 * other values read out of the hardware.
338 *
339 * void (*get_par)(struct atafb_par *par)
340 * Fill the hardware's 'par' structure.
341 * !!! Used only by detect() !!!
342 *
343 * void (*set_par)(struct atafb_par *par)
344 * Set the hardware according to 'par'.
345 *
346 * void (*set_screen_base)(void *s_base)
347 * Set the base address of the displayed frame buffer. Only called
348 * if yres_virtual > yres or xres_virtual > xres.
349 *
350 * int (*blank)(int blank_mode)
351 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
352 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
353 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
354 * doesn't support it. Implements VESA suspend and powerdown modes on
355 * hardware that supports disabling hsync/vsync:
356 * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
357 */
358
359 static struct fb_hwswitch {
360 int (*detect)(void);
361 int (*encode_fix)(struct fb_fix_screeninfo *fix,
362 struct atafb_par *par);
363 int (*decode_var)(struct fb_var_screeninfo *var,
364 struct atafb_par *par);
365 int (*encode_var)(struct fb_var_screeninfo *var,
366 struct atafb_par *par);
367 void (*get_par)(struct atafb_par *par);
368 void (*set_par)(struct atafb_par *par);
369 void (*set_screen_base)(void *s_base);
370 int (*blank)(int blank_mode);
371 int (*pan_display)(struct fb_var_screeninfo *var,
372 struct fb_info *info);
373 } *fbhw;
374
375 static char *autodetect_names[] = { "autodetect", NULL };
376 static char *stlow_names[] = { "stlow", NULL };
377 static char *stmid_names[] = { "stmid", "default5", NULL };
378 static char *sthigh_names[] = { "sthigh", "default4", NULL };
379 static char *ttlow_names[] = { "ttlow", NULL };
380 static char *ttmid_names[] = { "ttmid", "default1", NULL };
381 static char *tthigh_names[] = { "tthigh", "default2", NULL };
382 static char *vga2_names[] = { "vga2", NULL };
383 static char *vga4_names[] = { "vga4", NULL };
384 static char *vga16_names[] = { "vga16", "default3", NULL };
385 static char *vga256_names[] = { "vga256", NULL };
386 static char *falh2_names[] = { "falh2", NULL };
387 static char *falh16_names[] = { "falh16", NULL };
388
389 static char **fb_var_names[] = {
390 autodetect_names,
391 stlow_names,
392 stmid_names,
393 sthigh_names,
394 ttlow_names,
395 ttmid_names,
396 tthigh_names,
397 vga2_names,
398 vga4_names,
399 vga16_names,
400 vga256_names,
401 falh2_names,
402 falh16_names,
403 NULL
404 };
405
406 static struct fb_var_screeninfo atafb_predefined[] = {
407 /*
408 * yres_virtual == 0 means use hw-scrolling if possible, else yres
409 */
410 { /* autodetect */
411 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
412 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
413 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
414 { /* st low */
415 320, 200, 320, 0, 0, 0, 4, 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 },
418 { /* st mid */
419 640, 200, 640, 0, 0, 0, 2, 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 },
422 { /* st high */
423 640, 400, 640, 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 },
426 { /* tt low */
427 320, 480, 320, 0, 0, 0, 8, 0,
428 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
429 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
430 { /* tt mid */
431 640, 480, 640, 0, 0, 0, 4, 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 },
434 { /* tt high */
435 1280, 960, 1280, 0, 0, 0, 1, 0,
436 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
437 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
438 { /* vga2 */
439 640, 480, 640, 0, 0, 0, 1, 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 },
442 { /* vga4 */
443 640, 480, 640, 0, 0, 0, 2, 0,
444 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
445 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
446 { /* vga16 */
447 640, 480, 640, 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 },
450 { /* vga256 */
451 640, 480, 640, 0, 0, 0, 8, 0,
452 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
453 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
454 { /* falh2 */
455 896, 608, 896, 0, 0, 0, 1, 0,
456 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
457 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
458 { /* falh16 */
459 896, 608, 896, 0, 0, 0, 4, 0,
460 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
461 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
462 };
463
464 static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
465
466 static struct fb_videomode atafb_modedb[] __initdata = {
467 /*
468 * Atari Video Modes
469 *
470 * If you change these, make sure to update DEFMODE_* as well!
471 */
472
473 /*
474 * ST/TT Video Modes
475 */
476
477 {
478 /* 320x200, 15 kHz, 60 Hz (ST low) */
479 "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
480 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
481 }, {
482 /* 640x200, 15 kHz, 60 Hz (ST medium) */
483 "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
484 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
485 }, {
486 /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
487 "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
488 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
489 }, {
490 /* 320x480, 15 kHz, 60 Hz (TT low) */
491 "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
492 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
493 }, {
494 /* 640x480, 29 kHz, 57 Hz (TT medium) */
495 "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
496 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
497 }, {
498 /* 1280x960, 29 kHz, 60 Hz (TT high) */
499 "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
500 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
501 },
502
503 /*
504 * VGA Video Modes
505 */
506
507 {
508 /* 640x480, 31 kHz, 60 Hz (VGA) */
509 "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
510 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
511 }, {
512 /* 640x400, 31 kHz, 70 Hz (VGA) */
513 "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
514 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
515 },
516
517 /*
518 * Falcon HiRes Video Modes
519 */
520
521 {
522 /* 896x608, 31 kHz, 60 Hz (Falcon High) */
523 "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
524 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
525 },
526 };
527
528 #define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb)
529
530 static char *mode_option __initdata = NULL;
531
532 /* default modes */
533
534 #define DEFMODE_TT 5 /* "tt-high" for TT */
535 #define DEFMODE_F30 7 /* "vga70" for Falcon */
536 #define DEFMODE_STE 2 /* "st-high" for ST/E */
537 #define DEFMODE_EXT 6 /* "vga" for external */
538
539
get_video_mode(char * vname)540 static int get_video_mode(char *vname)
541 {
542 char ***name_list;
543 char **name;
544 int i;
545
546 name_list = fb_var_names;
547 for (i = 0; i < num_atafb_predefined; i++) {
548 name = *name_list++;
549 if (!name || !*name)
550 break;
551 while (*name) {
552 if (!strcmp(vname, *name))
553 return i + 1;
554 name++;
555 }
556 }
557 return 0;
558 }
559
560
561
562 /* ------------------- TT specific functions ---------------------- */
563
564 #ifdef ATAFB_TT
565
tt_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)566 static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
567 {
568 int mode;
569
570 strcpy(fix->id, "Atari Builtin");
571 fix->smem_start = phys_screen_base;
572 fix->smem_len = screen_len;
573 fix->type = FB_TYPE_INTERLEAVED_PLANES;
574 fix->type_aux = 2;
575 fix->visual = FB_VISUAL_PSEUDOCOLOR;
576 mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
577 if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
578 fix->type = FB_TYPE_PACKED_PIXELS;
579 fix->type_aux = 0;
580 if (mode == TT_SHIFTER_TTHIGH)
581 fix->visual = FB_VISUAL_MONO01;
582 }
583 fix->xpanstep = 0;
584 fix->ypanstep = 1;
585 fix->ywrapstep = 0;
586 fix->line_length = par->next_line;
587 fix->accel = FB_ACCEL_ATARIBLITT;
588 return 0;
589 }
590
tt_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)591 static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
592 {
593 int xres = var->xres;
594 int yres = var->yres;
595 int bpp = var->bits_per_pixel;
596 int linelen;
597 int yres_virtual = var->yres_virtual;
598
599 if (mono_moni) {
600 if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
601 return -EINVAL;
602 par->hw.tt.mode = TT_SHIFTER_TTHIGH;
603 xres = sttt_xres * 2;
604 yres = tt_yres * 2;
605 bpp = 1;
606 } else {
607 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
608 return -EINVAL;
609 if (bpp > 4) {
610 if (xres > sttt_xres / 2 || yres > tt_yres)
611 return -EINVAL;
612 par->hw.tt.mode = TT_SHIFTER_TTLOW;
613 xres = sttt_xres / 2;
614 yres = tt_yres;
615 bpp = 8;
616 } else if (bpp > 2) {
617 if (xres > sttt_xres || yres > tt_yres)
618 return -EINVAL;
619 if (xres > sttt_xres / 2 || yres > st_yres / 2) {
620 par->hw.tt.mode = TT_SHIFTER_TTMID;
621 xres = sttt_xres;
622 yres = tt_yres;
623 bpp = 4;
624 } else {
625 par->hw.tt.mode = TT_SHIFTER_STLOW;
626 xres = sttt_xres / 2;
627 yres = st_yres / 2;
628 bpp = 4;
629 }
630 } else if (bpp > 1) {
631 if (xres > sttt_xres || yres > st_yres / 2)
632 return -EINVAL;
633 par->hw.tt.mode = TT_SHIFTER_STMID;
634 xres = sttt_xres;
635 yres = st_yres / 2;
636 bpp = 2;
637 } else if (var->xres > sttt_xres || var->yres > st_yres) {
638 return -EINVAL;
639 } else {
640 par->hw.tt.mode = TT_SHIFTER_STHIGH;
641 xres = sttt_xres;
642 yres = st_yres;
643 bpp = 1;
644 }
645 }
646 if (yres_virtual <= 0)
647 yres_virtual = 0;
648 else if (yres_virtual < yres)
649 yres_virtual = yres;
650 if (var->sync & FB_SYNC_EXT)
651 par->hw.tt.sync = 0;
652 else
653 par->hw.tt.sync = 1;
654 linelen = xres * bpp / 8;
655 if (yres_virtual * linelen > screen_len && screen_len)
656 return -EINVAL;
657 if (yres * linelen > screen_len && screen_len)
658 return -EINVAL;
659 if (var->yoffset + yres > yres_virtual && yres_virtual)
660 return -EINVAL;
661 par->yres_virtual = yres_virtual;
662 par->screen_base = screen_base + var->yoffset * linelen;
663 par->next_line = linelen;
664 return 0;
665 }
666
tt_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)667 static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
668 {
669 int linelen;
670 memset(var, 0, sizeof(struct fb_var_screeninfo));
671 var->red.offset = 0;
672 var->red.length = 4;
673 var->red.msb_right = 0;
674 var->grayscale = 0;
675
676 var->pixclock = 31041;
677 var->left_margin = 120; /* these may be incorrect */
678 var->right_margin = 100;
679 var->upper_margin = 8;
680 var->lower_margin = 16;
681 var->hsync_len = 140;
682 var->vsync_len = 30;
683
684 var->height = -1;
685 var->width = -1;
686
687 if (par->hw.tt.sync & 1)
688 var->sync = 0;
689 else
690 var->sync = FB_SYNC_EXT;
691
692 switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
693 case TT_SHIFTER_STLOW:
694 var->xres = sttt_xres / 2;
695 var->xres_virtual = sttt_xres_virtual / 2;
696 var->yres = st_yres / 2;
697 var->bits_per_pixel = 4;
698 break;
699 case TT_SHIFTER_STMID:
700 var->xres = sttt_xres;
701 var->xres_virtual = sttt_xres_virtual;
702 var->yres = st_yres / 2;
703 var->bits_per_pixel = 2;
704 break;
705 case TT_SHIFTER_STHIGH:
706 var->xres = sttt_xres;
707 var->xres_virtual = sttt_xres_virtual;
708 var->yres = st_yres;
709 var->bits_per_pixel = 1;
710 break;
711 case TT_SHIFTER_TTLOW:
712 var->xres = sttt_xres / 2;
713 var->xres_virtual = sttt_xres_virtual / 2;
714 var->yres = tt_yres;
715 var->bits_per_pixel = 8;
716 break;
717 case TT_SHIFTER_TTMID:
718 var->xres = sttt_xres;
719 var->xres_virtual = sttt_xres_virtual;
720 var->yres = tt_yres;
721 var->bits_per_pixel = 4;
722 break;
723 case TT_SHIFTER_TTHIGH:
724 var->red.length = 0;
725 var->xres = sttt_xres * 2;
726 var->xres_virtual = sttt_xres_virtual * 2;
727 var->yres = tt_yres * 2;
728 var->bits_per_pixel = 1;
729 break;
730 }
731 var->blue = var->green = var->red;
732 var->transp.offset = 0;
733 var->transp.length = 0;
734 var->transp.msb_right = 0;
735 linelen = var->xres_virtual * var->bits_per_pixel / 8;
736 if (!use_hwscroll)
737 var->yres_virtual = var->yres;
738 else if (screen_len) {
739 if (par->yres_virtual)
740 var->yres_virtual = par->yres_virtual;
741 else
742 /* yres_virtual == 0 means use maximum */
743 var->yres_virtual = screen_len / linelen;
744 } else {
745 if (hwscroll < 0)
746 var->yres_virtual = 2 * var->yres;
747 else
748 var->yres_virtual = var->yres + hwscroll * 16;
749 }
750 var->xoffset = 0;
751 if (screen_base)
752 var->yoffset = (par->screen_base - screen_base) / linelen;
753 else
754 var->yoffset = 0;
755 var->nonstd = 0;
756 var->activate = 0;
757 var->vmode = FB_VMODE_NONINTERLACED;
758 return 0;
759 }
760
tt_get_par(struct atafb_par * par)761 static void tt_get_par(struct atafb_par *par)
762 {
763 unsigned long addr;
764 par->hw.tt.mode = shifter_tt.tt_shiftmode;
765 par->hw.tt.sync = shifter_st.syncmode;
766 addr = ((shifter_st.bas_hi & 0xff) << 16) |
767 ((shifter_st.bas_md & 0xff) << 8) |
768 ((shifter_st.bas_lo & 0xff));
769 par->screen_base = atari_stram_to_virt(addr);
770 }
771
tt_set_par(struct atafb_par * par)772 static void tt_set_par(struct atafb_par *par)
773 {
774 shifter_tt.tt_shiftmode = par->hw.tt.mode;
775 shifter_st.syncmode = par->hw.tt.sync;
776 /* only set screen_base if really necessary */
777 if (current_par.screen_base != par->screen_base)
778 fbhw->set_screen_base(par->screen_base);
779 }
780
tt_setcolreg(unsigned int regno,unsigned int red,unsigned int green,unsigned int blue,unsigned int transp,struct fb_info * info)781 static int tt_setcolreg(unsigned int regno, unsigned int red,
782 unsigned int green, unsigned int blue,
783 unsigned int transp, struct fb_info *info)
784 {
785 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
786 regno += 254;
787 if (regno > 255)
788 return 1;
789 tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
790 (blue >> 12));
791 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
792 TT_SHIFTER_STHIGH && regno == 254)
793 tt_palette[0] = 0;
794 return 0;
795 }
796
tt_detect(void)797 static int tt_detect(void)
798 {
799 struct atafb_par par;
800
801 /* Determine the connected monitor: The DMA sound must be
802 * disabled before reading the MFP GPIP, because the Sound
803 * Done Signal and the Monochrome Detect are XORed together!
804 *
805 * Even on a TT, we should look if there is a DMA sound. It was
806 * announced that the Eagle is TT compatible, but only the PCM is
807 * missing...
808 */
809 if (ATARIHW_PRESENT(PCM_8BIT)) {
810 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
811 udelay(20); /* wait a while for things to settle down */
812 }
813 mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
814
815 tt_get_par(&par);
816 tt_encode_var(&atafb_predefined[0], &par);
817
818 return 1;
819 }
820
821 #endif /* ATAFB_TT */
822
823 /* ------------------- Falcon specific functions ---------------------- */
824
825 #ifdef ATAFB_FALCON
826
827 static int mon_type; /* Falcon connected monitor */
828 static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
829 #define F_MON_SM 0
830 #define F_MON_SC 1
831 #define F_MON_VGA 2
832 #define F_MON_TV 3
833
834 static struct pixel_clock {
835 unsigned long f; /* f/[Hz] */
836 unsigned long t; /* t/[ps] (=1/f) */
837 int right, hsync, left; /* standard timing in clock cycles, not pixel */
838 /* hsync initialized in falcon_detect() */
839 int sync_mask; /* or-mask for hw.falcon.sync to set this clock */
840 int control_mask; /* ditto, for hw.falcon.vid_control */
841 } f25 = {
842 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
843 }, f32 = {
844 32000000, 31250, 18, 0, 42, 0x0, 0
845 }, fext = {
846 0, 0, 18, 0, 42, 0x1, 0
847 };
848
849 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
850 static int vdl_prescale[4][3] = {
851 { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
852 };
853
854 /* Default hsync timing [mon_type] in picoseconds */
855 static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
856
hxx_prescale(struct falcon_hw * hw)857 static inline int hxx_prescale(struct falcon_hw *hw)
858 {
859 return hw->ste_mode ? 16
860 : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
861 }
862
falcon_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)863 static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
864 struct atafb_par *par)
865 {
866 strcpy(fix->id, "Atari Builtin");
867 fix->smem_start = phys_screen_base;
868 fix->smem_len = screen_len;
869 fix->type = FB_TYPE_INTERLEAVED_PLANES;
870 fix->type_aux = 2;
871 fix->visual = FB_VISUAL_PSEUDOCOLOR;
872 fix->xpanstep = 1;
873 fix->ypanstep = 1;
874 fix->ywrapstep = 0;
875 if (par->hw.falcon.mono) {
876 fix->type = FB_TYPE_PACKED_PIXELS;
877 fix->type_aux = 0;
878 /* no smooth scrolling with longword aligned video mem */
879 fix->xpanstep = 32;
880 } else if (par->hw.falcon.f_shift & 0x100) {
881 fix->type = FB_TYPE_PACKED_PIXELS;
882 fix->type_aux = 0;
883 /* Is this ok or should it be DIRECTCOLOR? */
884 fix->visual = FB_VISUAL_TRUECOLOR;
885 fix->xpanstep = 2;
886 }
887 fix->line_length = par->next_line;
888 fix->accel = FB_ACCEL_ATARIBLITT;
889 return 0;
890 }
891
falcon_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)892 static int falcon_decode_var(struct fb_var_screeninfo *var,
893 struct atafb_par *par)
894 {
895 int bpp = var->bits_per_pixel;
896 int xres = var->xres;
897 int yres = var->yres;
898 int xres_virtual = var->xres_virtual;
899 int yres_virtual = var->yres_virtual;
900 int left_margin, right_margin, hsync_len;
901 int upper_margin, lower_margin, vsync_len;
902 int linelen;
903 int interlace = 0, doubleline = 0;
904 struct pixel_clock *pclock;
905 int plen; /* width of pixel in clock cycles */
906 int xstretch;
907 int prescale;
908 int longoffset = 0;
909 int hfreq, vfreq;
910 int hdb_off, hde_off, base_off;
911 int gstart, gend1, gend2, align;
912
913 /*
914 Get the video params out of 'var'. If a value doesn't fit, round
915 it up, if it's too big, return EINVAL.
916 Round up in the following order: bits_per_pixel, xres, yres,
917 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
918 horizontal timing, vertical timing.
919
920 There is a maximum of screen resolution determined by pixelclock
921 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
922 In interlace mode this is " * " *vfmin <= pixelclock.
923 Additional constraints: hfreq.
924 Frequency range for multisync monitors is given via command line.
925 For TV and SM124 both frequencies are fixed.
926
927 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
928 Y % 16 == 0 to fit 8x16 font
929 Y % 8 == 0 if Y<400
930
931 Currently interlace and doubleline mode in var are ignored.
932 On SM124 and TV only the standard resolutions can be used.
933 */
934
935 /* Reject uninitialized mode */
936 if (!xres || !yres || !bpp)
937 return -EINVAL;
938
939 if (mon_type == F_MON_SM && bpp != 1)
940 return -EINVAL;
941
942 if (bpp <= 1) {
943 bpp = 1;
944 par->hw.falcon.f_shift = 0x400;
945 par->hw.falcon.st_shift = 0x200;
946 } else if (bpp <= 2) {
947 bpp = 2;
948 par->hw.falcon.f_shift = 0x000;
949 par->hw.falcon.st_shift = 0x100;
950 } else if (bpp <= 4) {
951 bpp = 4;
952 par->hw.falcon.f_shift = 0x000;
953 par->hw.falcon.st_shift = 0x000;
954 } else if (bpp <= 8) {
955 bpp = 8;
956 par->hw.falcon.f_shift = 0x010;
957 } else if (bpp <= 16) {
958 bpp = 16; /* packed pixel mode */
959 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
960 } else
961 return -EINVAL;
962 par->hw.falcon.bpp = bpp;
963
964 if (mon_type == F_MON_SM || DontCalcRes) {
965 /* Skip all calculations. VGA/TV/SC1224 only supported. */
966 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
967
968 if (bpp > myvar->bits_per_pixel ||
969 var->xres > myvar->xres ||
970 var->yres > myvar->yres)
971 return -EINVAL;
972 fbhw->get_par(par); /* Current par will be new par */
973 goto set_screen_base; /* Don't forget this */
974 }
975
976 /* Only some fixed resolutions < 640x400 */
977 if (xres <= 320)
978 xres = 320;
979 else if (xres <= 640 && bpp != 16)
980 xres = 640;
981 if (yres <= 200)
982 yres = 200;
983 else if (yres <= 240)
984 yres = 240;
985 else if (yres <= 400)
986 yres = 400;
987
988 /* 2 planes must use STE compatibility mode */
989 par->hw.falcon.ste_mode = bpp == 2;
990 par->hw.falcon.mono = bpp == 1;
991
992 /* Total and visible scanline length must be a multiple of one longword,
993 * this and the console fontwidth yields the alignment for xres and
994 * xres_virtual.
995 * TODO: this way "odd" fontheights are not supported
996 *
997 * Special case in STE mode: blank and graphic positions don't align,
998 * avoid trash at right margin
999 */
1000 if (par->hw.falcon.ste_mode)
1001 xres = (xres + 63) & ~63;
1002 else if (bpp == 1)
1003 xres = (xres + 31) & ~31;
1004 else
1005 xres = (xres + 15) & ~15;
1006 if (yres >= 400)
1007 yres = (yres + 15) & ~15;
1008 else
1009 yres = (yres + 7) & ~7;
1010
1011 if (xres_virtual < xres)
1012 xres_virtual = xres;
1013 else if (bpp == 1)
1014 xres_virtual = (xres_virtual + 31) & ~31;
1015 else
1016 xres_virtual = (xres_virtual + 15) & ~15;
1017
1018 if (yres_virtual <= 0)
1019 yres_virtual = 0;
1020 else if (yres_virtual < yres)
1021 yres_virtual = yres;
1022
1023 /* backward bug-compatibility */
1024 if (var->pixclock > 1)
1025 var->pixclock -= 1;
1026
1027 par->hw.falcon.line_width = bpp * xres / 16;
1028 par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
1029
1030 /* single or double pixel width */
1031 xstretch = (xres < 640) ? 2 : 1;
1032
1033 #if 0 /* SM124 supports only 640x400, this is rejected above */
1034 if (mon_type == F_MON_SM) {
1035 if (xres != 640 && yres != 400)
1036 return -EINVAL;
1037 plen = 1;
1038 pclock = &f32;
1039 /* SM124-mode is special */
1040 par->hw.falcon.ste_mode = 1;
1041 par->hw.falcon.f_shift = 0x000;
1042 par->hw.falcon.st_shift = 0x200;
1043 left_margin = hsync_len = 128 / plen;
1044 right_margin = 0;
1045 /* TODO set all margins */
1046 } else
1047 #endif
1048 if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
1049 plen = 2 * xstretch;
1050 if (var->pixclock > f32.t * plen)
1051 return -EINVAL;
1052 pclock = &f32;
1053 if (yres > 240)
1054 interlace = 1;
1055 if (var->pixclock == 0) {
1056 /* set some minimal margins which center the screen */
1057 left_margin = 32;
1058 right_margin = 18;
1059 hsync_len = pclock->hsync / plen;
1060 upper_margin = 31;
1061 lower_margin = 14;
1062 vsync_len = interlace ? 3 : 4;
1063 } else {
1064 left_margin = var->left_margin;
1065 right_margin = var->right_margin;
1066 hsync_len = var->hsync_len;
1067 upper_margin = var->upper_margin;
1068 lower_margin = var->lower_margin;
1069 vsync_len = var->vsync_len;
1070 if (var->vmode & FB_VMODE_INTERLACED) {
1071 upper_margin = (upper_margin + 1) / 2;
1072 lower_margin = (lower_margin + 1) / 2;
1073 vsync_len = (vsync_len + 1) / 2;
1074 } else if (var->vmode & FB_VMODE_DOUBLE) {
1075 upper_margin *= 2;
1076 lower_margin *= 2;
1077 vsync_len *= 2;
1078 }
1079 }
1080 } else { /* F_MON_VGA */
1081 if (bpp == 16)
1082 xstretch = 2; /* Double pixel width only for hicolor */
1083 /* Default values are used for vert./hor. timing if no pixelclock given. */
1084 if (var->pixclock == 0) {
1085 int linesize;
1086
1087 /* Choose master pixelclock depending on hor. timing */
1088 plen = 1 * xstretch;
1089 if ((plen * xres + f25.right + f25.hsync + f25.left) *
1090 fb_info.monspecs.hfmin < f25.f)
1091 pclock = &f25;
1092 else if ((plen * xres + f32.right + f32.hsync +
1093 f32.left) * fb_info.monspecs.hfmin < f32.f)
1094 pclock = &f32;
1095 else if ((plen * xres + fext.right + fext.hsync +
1096 fext.left) * fb_info.monspecs.hfmin < fext.f &&
1097 fext.f)
1098 pclock = &fext;
1099 else
1100 return -EINVAL;
1101
1102 left_margin = pclock->left / plen;
1103 right_margin = pclock->right / plen;
1104 hsync_len = pclock->hsync / plen;
1105 linesize = left_margin + xres + right_margin + hsync_len;
1106 upper_margin = 31;
1107 lower_margin = 11;
1108 vsync_len = 3;
1109 } else {
1110 /* Choose largest pixelclock <= wanted clock */
1111 int i;
1112 unsigned long pcl = ULONG_MAX;
1113 pclock = 0;
1114 for (i = 1; i <= 4; i *= 2) {
1115 if (f25.t * i >= var->pixclock &&
1116 f25.t * i < pcl) {
1117 pcl = f25.t * i;
1118 pclock = &f25;
1119 }
1120 if (f32.t * i >= var->pixclock &&
1121 f32.t * i < pcl) {
1122 pcl = f32.t * i;
1123 pclock = &f32;
1124 }
1125 if (fext.t && fext.t * i >= var->pixclock &&
1126 fext.t * i < pcl) {
1127 pcl = fext.t * i;
1128 pclock = &fext;
1129 }
1130 }
1131 if (!pclock)
1132 return -EINVAL;
1133 plen = pcl / pclock->t;
1134
1135 left_margin = var->left_margin;
1136 right_margin = var->right_margin;
1137 hsync_len = var->hsync_len;
1138 upper_margin = var->upper_margin;
1139 lower_margin = var->lower_margin;
1140 vsync_len = var->vsync_len;
1141 /* Internal unit is [single lines per (half-)frame] */
1142 if (var->vmode & FB_VMODE_INTERLACED) {
1143 /* # lines in half frame */
1144 /* External unit is [lines per full frame] */
1145 upper_margin = (upper_margin + 1) / 2;
1146 lower_margin = (lower_margin + 1) / 2;
1147 vsync_len = (vsync_len + 1) / 2;
1148 } else if (var->vmode & FB_VMODE_DOUBLE) {
1149 /* External unit is [double lines per frame] */
1150 upper_margin *= 2;
1151 lower_margin *= 2;
1152 vsync_len *= 2;
1153 }
1154 }
1155 if (pclock == &fext)
1156 longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1157 }
1158 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1159 /* this is definitely wrong if bus clock != 32MHz */
1160 if (pclock->f / plen / 8 * bpp > 32000000L)
1161 return -EINVAL;
1162
1163 if (vsync_len < 1)
1164 vsync_len = 1;
1165
1166 /* include sync lengths in right/lower margin for all calculations */
1167 right_margin += hsync_len;
1168 lower_margin += vsync_len;
1169
1170 /* ! In all calculations of margins we use # of lines in half frame
1171 * (which is a full frame in non-interlace mode), so we can switch
1172 * between interlace and non-interlace without messing around
1173 * with these.
1174 */
1175 again:
1176 /* Set base_offset 128 and video bus width */
1177 par->hw.falcon.vid_control = mon_type | f030_bus_width;
1178 if (!longoffset)
1179 par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */
1180 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1181 par->hw.falcon.vid_control |= VCO_HSYPOS;
1182 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1183 par->hw.falcon.vid_control |= VCO_VSYPOS;
1184 /* Pixelclock */
1185 par->hw.falcon.vid_control |= pclock->control_mask;
1186 /* External or internal clock */
1187 par->hw.falcon.sync = pclock->sync_mask | 0x2;
1188 /* Pixellength and prescale */
1189 par->hw.falcon.vid_mode = (2 / plen) << 2;
1190 if (doubleline)
1191 par->hw.falcon.vid_mode |= VMO_DOUBLE;
1192 if (interlace)
1193 par->hw.falcon.vid_mode |= VMO_INTER;
1194
1195 /*********************
1196 * Horizontal timing: unit = [master clock cycles]
1197 * unit of hxx-registers: [master clock cycles * prescale]
1198 * Hxx-registers are 9 bit wide
1199 *
1200 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
1201 *
1202 * graphic output = hdb & 0x200 ?
1203 * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
1204 * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1205 * (this must be a multiple of plen*128/bpp, on VGA pixels
1206 * to the right may be cut off with a bigger right margin)
1207 *
1208 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1209 * (hdb - hht - 2) * prescale + hdboff :
1210 * hdb * prescale + hdboff
1211 *
1212 * end of graphics relative to start of 1st halfline =
1213 * (hde + hht + 2) * prescale + hdeoff
1214 *********************/
1215 /* Calculate VIDEL registers */
1216 {
1217 prescale = hxx_prescale(&par->hw.falcon);
1218 base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1219
1220 /* Offsets depend on video mode */
1221 /* Offsets are in clock cycles, divide by prescale to
1222 * calculate hd[be]-registers
1223 */
1224 if (par->hw.falcon.f_shift & 0x100) {
1225 align = 1;
1226 hde_off = 0;
1227 hdb_off = (base_off + 16 * plen) + prescale;
1228 } else {
1229 align = 128 / bpp;
1230 hde_off = ((128 / bpp + 2) * plen);
1231 if (par->hw.falcon.ste_mode)
1232 hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1233 else
1234 hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1235 }
1236
1237 gstart = (prescale / 2 + plen * left_margin) / prescale;
1238 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1239 gend1 = gstart + roundup(xres, align) * plen / prescale;
1240 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1241 gend2 = gstart + xres * plen / prescale;
1242 par->HHT = plen * (left_margin + xres + right_margin) /
1243 (2 * prescale) - 2;
1244 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1245
1246 par->HDB = gstart - hdb_off / prescale;
1247 par->HBE = gstart;
1248 if (par->HDB < 0)
1249 par->HDB += par->HHT + 2 + 0x200;
1250 par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
1251 par->HBB = gend2 - par->HHT - 2;
1252 #if 0
1253 /* One more Videl constraint: data fetch of two lines must not overlap */
1254 if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1255 /* if this happens increase margins, decrease hfreq. */
1256 }
1257 #endif
1258 if (hde_off % prescale)
1259 par->HBB++; /* compensate for non matching hde and hbb */
1260 par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1261 if (par->HSS < par->HBB)
1262 par->HSS = par->HBB;
1263 }
1264
1265 /* check hor. frequency */
1266 hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
1267 if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
1268 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1269 /* Too high -> enlarge margin */
1270 left_margin += 1;
1271 right_margin += 1;
1272 goto again;
1273 }
1274 if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1275 return -EINVAL;
1276
1277 /* Vxx-registers */
1278 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1279 * of the first displayed line!
1280 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1281 * non-interlace, odd in interlace mode for synchronisation.
1282 * Vxx-registers are 11 bit wide
1283 */
1284 par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1285 par->VDB = par->VBE;
1286 par->VDE = yres;
1287 if (!interlace)
1288 par->VDE <<= 1;
1289 if (doubleline)
1290 par->VDE <<= 1; /* VDE now half lines per (half-)frame */
1291 par->VDE += par->VDB;
1292 par->VBB = par->VDE;
1293 par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1294 par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
1295 /* vbb,vss,vft must be even in interlace mode */
1296 if (interlace) {
1297 par->VBB++;
1298 par->VSS++;
1299 par->VFT++;
1300 }
1301
1302 /* V-frequency check, hope I didn't create any loop here. */
1303 /* Interlace and doubleline are mutually exclusive. */
1304 vfreq = (hfreq * 2) / (par->VFT + 1);
1305 if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1306 /* Too high -> try again with doubleline */
1307 doubleline = 1;
1308 goto again;
1309 } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1310 /* Too low -> try again with interlace */
1311 interlace = 1;
1312 goto again;
1313 } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1314 /* Doubleline too low -> clear doubleline and enlarge margins */
1315 int lines;
1316 doubleline = 0;
1317 for (lines = 0;
1318 (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
1319 fb_info.monspecs.vfmax;
1320 lines++)
1321 ;
1322 upper_margin += lines;
1323 lower_margin += lines;
1324 goto again;
1325 } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1326 /* Doubleline too high -> enlarge margins */
1327 int lines;
1328 for (lines = 0;
1329 (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1330 fb_info.monspecs.vfmax;
1331 lines += 2)
1332 ;
1333 upper_margin += lines;
1334 lower_margin += lines;
1335 goto again;
1336 } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1337 /* Interlace, too high -> enlarge margins */
1338 int lines;
1339 for (lines = 0;
1340 (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
1341 fb_info.monspecs.vfmax;
1342 lines++)
1343 ;
1344 upper_margin += lines;
1345 lower_margin += lines;
1346 goto again;
1347 } else if (vfreq < fb_info.monspecs.vfmin ||
1348 vfreq > fb_info.monspecs.vfmax)
1349 return -EINVAL;
1350
1351 set_screen_base:
1352 linelen = xres_virtual * bpp / 8;
1353 if (yres_virtual * linelen > screen_len && screen_len)
1354 return -EINVAL;
1355 if (yres * linelen > screen_len && screen_len)
1356 return -EINVAL;
1357 if (var->yoffset + yres > yres_virtual && yres_virtual)
1358 return -EINVAL;
1359 par->yres_virtual = yres_virtual;
1360 par->screen_base = screen_base + var->yoffset * linelen;
1361 par->hw.falcon.xoffset = 0;
1362
1363 par->next_line = linelen;
1364
1365 return 0;
1366 }
1367
falcon_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)1368 static int falcon_encode_var(struct fb_var_screeninfo *var,
1369 struct atafb_par *par)
1370 {
1371 /* !!! only for VGA !!! */
1372 int linelen;
1373 int prescale, plen;
1374 int hdb_off, hde_off, base_off;
1375 struct falcon_hw *hw = &par->hw.falcon;
1376
1377 memset(var, 0, sizeof(struct fb_var_screeninfo));
1378 /* possible frequencies: 25.175 or 32MHz */
1379 var->pixclock = hw->sync & 0x1 ? fext.t :
1380 hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1381
1382 var->height = -1;
1383 var->width = -1;
1384
1385 var->sync = 0;
1386 if (hw->vid_control & VCO_HSYPOS)
1387 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1388 if (hw->vid_control & VCO_VSYPOS)
1389 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1390
1391 var->vmode = FB_VMODE_NONINTERLACED;
1392 if (hw->vid_mode & VMO_INTER)
1393 var->vmode |= FB_VMODE_INTERLACED;
1394 if (hw->vid_mode & VMO_DOUBLE)
1395 var->vmode |= FB_VMODE_DOUBLE;
1396
1397 /* visible y resolution:
1398 * Graphics display starts at line VDB and ends at line
1399 * VDE. If interlace mode off unit of VC-registers is
1400 * half lines, else lines.
1401 */
1402 var->yres = hw->vde - hw->vdb;
1403 if (!(var->vmode & FB_VMODE_INTERLACED))
1404 var->yres >>= 1;
1405 if (var->vmode & FB_VMODE_DOUBLE)
1406 var->yres >>= 1;
1407
1408 /*
1409 * to get bpp, we must examine f_shift and st_shift.
1410 * f_shift is valid if any of bits no. 10, 8 or 4
1411 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1412 * if bit 10 set then bit 8 and bit 4 don't care...
1413 * If all these bits are 0 get display depth from st_shift
1414 * (as for ST and STE)
1415 */
1416 if (hw->f_shift & 0x400) /* 2 colors */
1417 var->bits_per_pixel = 1;
1418 else if (hw->f_shift & 0x100) /* hicolor */
1419 var->bits_per_pixel = 16;
1420 else if (hw->f_shift & 0x010) /* 8 bitplanes */
1421 var->bits_per_pixel = 8;
1422 else if (hw->st_shift == 0)
1423 var->bits_per_pixel = 4;
1424 else if (hw->st_shift == 0x100)
1425 var->bits_per_pixel = 2;
1426 else /* if (hw->st_shift == 0x200) */
1427 var->bits_per_pixel = 1;
1428
1429 var->xres = hw->line_width * 16 / var->bits_per_pixel;
1430 var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1431 if (hw->xoffset)
1432 var->xres_virtual += 16;
1433
1434 if (var->bits_per_pixel == 16) {
1435 var->red.offset = 11;
1436 var->red.length = 5;
1437 var->red.msb_right = 0;
1438 var->green.offset = 5;
1439 var->green.length = 6;
1440 var->green.msb_right = 0;
1441 var->blue.offset = 0;
1442 var->blue.length = 5;
1443 var->blue.msb_right = 0;
1444 } else {
1445 var->red.offset = 0;
1446 var->red.length = hw->ste_mode ? 4 : 6;
1447 if (var->red.length > var->bits_per_pixel)
1448 var->red.length = var->bits_per_pixel;
1449 var->red.msb_right = 0;
1450 var->grayscale = 0;
1451 var->blue = var->green = var->red;
1452 }
1453 var->transp.offset = 0;
1454 var->transp.length = 0;
1455 var->transp.msb_right = 0;
1456
1457 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1458 if (screen_len) {
1459 if (par->yres_virtual)
1460 var->yres_virtual = par->yres_virtual;
1461 else
1462 /* yres_virtual == 0 means use maximum */
1463 var->yres_virtual = screen_len / linelen;
1464 } else {
1465 if (hwscroll < 0)
1466 var->yres_virtual = 2 * var->yres;
1467 else
1468 var->yres_virtual = var->yres + hwscroll * 16;
1469 }
1470 var->xoffset = 0; /* TODO change this */
1471
1472 /* hdX-offsets */
1473 prescale = hxx_prescale(hw);
1474 plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1475 base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1476 if (hw->f_shift & 0x100) {
1477 hde_off = 0;
1478 hdb_off = (base_off + 16 * plen) + prescale;
1479 } else {
1480 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1481 if (hw->ste_mode)
1482 hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1483 + prescale;
1484 else
1485 hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1486 + prescale;
1487 }
1488
1489 /* Right margin includes hsync */
1490 var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1491 (hw->hdb & 0x200 ? 2 + hw->hht : 0));
1492 if (hw->ste_mode || mon_type != F_MON_VGA)
1493 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1494 else
1495 /* can't use this in ste_mode, because hbb is +1 off */
1496 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1497 var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1498
1499 /* Lower margin includes vsync */
1500 var->upper_margin = hw->vdb / 2; /* round down to full lines */
1501 var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2; /* round up */
1502 var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2; /* round up */
1503 if (var->vmode & FB_VMODE_INTERLACED) {
1504 var->upper_margin *= 2;
1505 var->lower_margin *= 2;
1506 var->vsync_len *= 2;
1507 } else if (var->vmode & FB_VMODE_DOUBLE) {
1508 var->upper_margin = (var->upper_margin + 1) / 2;
1509 var->lower_margin = (var->lower_margin + 1) / 2;
1510 var->vsync_len = (var->vsync_len + 1) / 2;
1511 }
1512
1513 var->pixclock *= plen;
1514 var->left_margin /= plen;
1515 var->right_margin /= plen;
1516 var->hsync_len /= plen;
1517
1518 var->right_margin -= var->hsync_len;
1519 var->lower_margin -= var->vsync_len;
1520
1521 if (screen_base)
1522 var->yoffset = (par->screen_base - screen_base) / linelen;
1523 else
1524 var->yoffset = 0;
1525 var->nonstd = 0; /* what is this for? */
1526 var->activate = 0;
1527 return 0;
1528 }
1529
1530 static int f_change_mode;
1531 static struct falcon_hw f_new_mode;
1532 static int f_pan_display;
1533
falcon_get_par(struct atafb_par * par)1534 static void falcon_get_par(struct atafb_par *par)
1535 {
1536 unsigned long addr;
1537 struct falcon_hw *hw = &par->hw.falcon;
1538
1539 hw->line_width = shifter_f030.scn_width;
1540 hw->line_offset = shifter_f030.off_next;
1541 hw->st_shift = videl.st_shift & 0x300;
1542 hw->f_shift = videl.f_shift;
1543 hw->vid_control = videl.control;
1544 hw->vid_mode = videl.mode;
1545 hw->sync = shifter_st.syncmode & 0x1;
1546 hw->xoffset = videl.xoffset & 0xf;
1547 hw->hht = videl.hht;
1548 hw->hbb = videl.hbb;
1549 hw->hbe = videl.hbe;
1550 hw->hdb = videl.hdb;
1551 hw->hde = videl.hde;
1552 hw->hss = videl.hss;
1553 hw->vft = videl.vft;
1554 hw->vbb = videl.vbb;
1555 hw->vbe = videl.vbe;
1556 hw->vdb = videl.vdb;
1557 hw->vde = videl.vde;
1558 hw->vss = videl.vss;
1559
1560 addr = (shifter_st.bas_hi & 0xff) << 16 |
1561 (shifter_st.bas_md & 0xff) << 8 |
1562 (shifter_st.bas_lo & 0xff);
1563 par->screen_base = atari_stram_to_virt(addr);
1564
1565 /* derived parameters */
1566 hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
1567 hw->mono = (hw->f_shift & 0x400) ||
1568 ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
1569 }
1570
falcon_set_par(struct atafb_par * par)1571 static void falcon_set_par(struct atafb_par *par)
1572 {
1573 f_change_mode = 0;
1574
1575 /* only set screen_base if really necessary */
1576 if (current_par.screen_base != par->screen_base)
1577 fbhw->set_screen_base(par->screen_base);
1578
1579 /* Don't touch any other registers if we keep the default resolution */
1580 if (DontCalcRes)
1581 return;
1582
1583 /* Tell vbl-handler to change video mode.
1584 * We change modes only on next VBL, to avoid desynchronisation
1585 * (a shift to the right and wrap around by a random number of pixels
1586 * in all monochrome modes).
1587 * This seems to work on my Falcon.
1588 */
1589 f_new_mode = par->hw.falcon;
1590 f_change_mode = 1;
1591 }
1592
falcon_vbl_switcher(int irq,void * dummy)1593 static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
1594 {
1595 struct falcon_hw *hw = &f_new_mode;
1596
1597 if (f_change_mode) {
1598 f_change_mode = 0;
1599
1600 if (hw->sync & 0x1) {
1601 /* Enable external pixelclock. This code only for ScreenWonder */
1602 *(volatile unsigned short *)0xffff9202 = 0xffbf;
1603 } else {
1604 /* Turn off external clocks. Read sets all output bits to 1. */
1605 *(volatile unsigned short *)0xffff9202;
1606 }
1607 shifter_st.syncmode = hw->sync;
1608
1609 videl.hht = hw->hht;
1610 videl.hbb = hw->hbb;
1611 videl.hbe = hw->hbe;
1612 videl.hdb = hw->hdb;
1613 videl.hde = hw->hde;
1614 videl.hss = hw->hss;
1615 videl.vft = hw->vft;
1616 videl.vbb = hw->vbb;
1617 videl.vbe = hw->vbe;
1618 videl.vdb = hw->vdb;
1619 videl.vde = hw->vde;
1620 videl.vss = hw->vss;
1621
1622 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1623 if (hw->ste_mode) {
1624 videl.st_shift = hw->st_shift; /* write enables STE palette */
1625 } else {
1626 /* IMPORTANT:
1627 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
1628 * Writing 0 to f_shift enables 4 plane Falcon mode but
1629 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
1630 * with Falcon palette.
1631 */
1632 videl.st_shift = 0;
1633 /* now back to Falcon palette mode */
1634 videl.f_shift = hw->f_shift;
1635 }
1636 /* writing to st_shift changed scn_width and vid_mode */
1637 videl.xoffset = hw->xoffset;
1638 shifter_f030.scn_width = hw->line_width;
1639 shifter_f030.off_next = hw->line_offset;
1640 videl.control = hw->vid_control;
1641 videl.mode = hw->vid_mode;
1642 }
1643 if (f_pan_display) {
1644 f_pan_display = 0;
1645 videl.xoffset = current_par.hw.falcon.xoffset;
1646 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1647 }
1648 return IRQ_HANDLED;
1649 }
1650
falcon_pan_display(struct fb_var_screeninfo * var,struct fb_info * info)1651 static int falcon_pan_display(struct fb_var_screeninfo *var,
1652 struct fb_info *info)
1653 {
1654 struct atafb_par *par = (struct atafb_par *)info->par;
1655
1656 int xoffset;
1657 int bpp = info->var.bits_per_pixel;
1658
1659 if (bpp == 1)
1660 var->xoffset = up(var->xoffset, 32);
1661 if (bpp != 16)
1662 par->hw.falcon.xoffset = var->xoffset & 15;
1663 else {
1664 par->hw.falcon.xoffset = 0;
1665 var->xoffset = up(var->xoffset, 2);
1666 }
1667 par->hw.falcon.line_offset = bpp *
1668 (info->var.xres_virtual - info->var.xres) / 16;
1669 if (par->hw.falcon.xoffset)
1670 par->hw.falcon.line_offset -= bpp;
1671 xoffset = var->xoffset - par->hw.falcon.xoffset;
1672
1673 par->screen_base = screen_base +
1674 (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
1675 if (fbhw->set_screen_base)
1676 fbhw->set_screen_base(par->screen_base);
1677 else
1678 return -EINVAL; /* shouldn't happen */
1679 f_pan_display = 1;
1680 return 0;
1681 }
1682
falcon_setcolreg(unsigned int regno,unsigned int red,unsigned int green,unsigned int blue,unsigned int transp,struct fb_info * info)1683 static int falcon_setcolreg(unsigned int regno, unsigned int red,
1684 unsigned int green, unsigned int blue,
1685 unsigned int transp, struct fb_info *info)
1686 {
1687 if (regno > 255)
1688 return 1;
1689 f030_col[regno] = (((red & 0xfc00) << 16) |
1690 ((green & 0xfc00) << 8) |
1691 ((blue & 0xfc00) >> 8));
1692 if (regno < 16) {
1693 shifter_tt.color_reg[regno] =
1694 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1695 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1696 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1697 ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
1698 ((green & 0xfc00) >> 5) |
1699 ((blue & 0xf800) >> 11));
1700 }
1701 return 0;
1702 }
1703
falcon_blank(int blank_mode)1704 static int falcon_blank(int blank_mode)
1705 {
1706 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1707 * so VIDEL doesn't hog the bus while saving.
1708 * (this may affect usleep()).
1709 */
1710 int vdb, vss, hbe, hss;
1711
1712 if (mon_type == F_MON_SM) /* this doesn't work on SM124 */
1713 return 1;
1714
1715 vdb = current_par.VDB;
1716 vss = current_par.VSS;
1717 hbe = current_par.HBE;
1718 hss = current_par.HSS;
1719
1720 if (blank_mode >= 1) {
1721 /* disable graphics output (this speeds up the CPU) ... */
1722 vdb = current_par.VFT + 1;
1723 /* ... and blank all lines */
1724 hbe = current_par.HHT + 2;
1725 }
1726 /* use VESA suspend modes on VGA monitors */
1727 if (mon_type == F_MON_VGA) {
1728 if (blank_mode == 2 || blank_mode == 4)
1729 vss = current_par.VFT + 1;
1730 if (blank_mode == 3 || blank_mode == 4)
1731 hss = current_par.HHT + 2;
1732 }
1733
1734 videl.vdb = vdb;
1735 videl.vss = vss;
1736 videl.hbe = hbe;
1737 videl.hss = hss;
1738
1739 return 0;
1740 }
1741
falcon_detect(void)1742 static int falcon_detect(void)
1743 {
1744 struct atafb_par par;
1745 unsigned char fhw;
1746
1747 /* Determine connected monitor and set monitor parameters */
1748 fhw = *(unsigned char *)0xffff8006;
1749 mon_type = fhw >> 6 & 0x3;
1750 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1751 f030_bus_width = fhw << 6 & 0x80;
1752 switch (mon_type) {
1753 case F_MON_SM:
1754 fb_info.monspecs.vfmin = 70;
1755 fb_info.monspecs.vfmax = 72;
1756 fb_info.monspecs.hfmin = 35713;
1757 fb_info.monspecs.hfmax = 35715;
1758 break;
1759 case F_MON_SC:
1760 case F_MON_TV:
1761 /* PAL...NTSC */
1762 fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
1763 fb_info.monspecs.vfmax = 60;
1764 fb_info.monspecs.hfmin = 15620;
1765 fb_info.monspecs.hfmax = 15755;
1766 break;
1767 }
1768 /* initialize hsync-len */
1769 f25.hsync = h_syncs[mon_type] / f25.t;
1770 f32.hsync = h_syncs[mon_type] / f32.t;
1771 if (fext.t)
1772 fext.hsync = h_syncs[mon_type] / fext.t;
1773
1774 falcon_get_par(&par);
1775 falcon_encode_var(&atafb_predefined[0], &par);
1776
1777 /* Detected mode is always the "autodetect" slot */
1778 return 1;
1779 }
1780
1781 #endif /* ATAFB_FALCON */
1782
1783 /* ------------------- ST(E) specific functions ---------------------- */
1784
1785 #ifdef ATAFB_STE
1786
stste_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)1787 static int stste_encode_fix(struct fb_fix_screeninfo *fix,
1788 struct atafb_par *par)
1789 {
1790 int mode;
1791
1792 strcpy(fix->id, "Atari Builtin");
1793 fix->smem_start = phys_screen_base;
1794 fix->smem_len = screen_len;
1795 fix->type = FB_TYPE_INTERLEAVED_PLANES;
1796 fix->type_aux = 2;
1797 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1798 mode = par->hw.st.mode & 3;
1799 if (mode == ST_HIGH) {
1800 fix->type = FB_TYPE_PACKED_PIXELS;
1801 fix->type_aux = 0;
1802 fix->visual = FB_VISUAL_MONO10;
1803 }
1804 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1805 fix->xpanstep = 16;
1806 fix->ypanstep = 1;
1807 } else {
1808 fix->xpanstep = 0;
1809 fix->ypanstep = 0;
1810 }
1811 fix->ywrapstep = 0;
1812 fix->line_length = par->next_line;
1813 fix->accel = FB_ACCEL_ATARIBLITT;
1814 return 0;
1815 }
1816
stste_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)1817 static int stste_decode_var(struct fb_var_screeninfo *var,
1818 struct atafb_par *par)
1819 {
1820 int xres = var->xres;
1821 int yres = var->yres;
1822 int bpp = var->bits_per_pixel;
1823 int linelen;
1824 int yres_virtual = var->yres_virtual;
1825
1826 if (mono_moni) {
1827 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1828 return -EINVAL;
1829 par->hw.st.mode = ST_HIGH;
1830 xres = sttt_xres;
1831 yres = st_yres;
1832 bpp = 1;
1833 } else {
1834 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1835 return -EINVAL;
1836 if (bpp > 2) {
1837 if (xres > sttt_xres / 2 || yres > st_yres / 2)
1838 return -EINVAL;
1839 par->hw.st.mode = ST_LOW;
1840 xres = sttt_xres / 2;
1841 yres = st_yres / 2;
1842 bpp = 4;
1843 } else if (bpp > 1) {
1844 if (xres > sttt_xres || yres > st_yres / 2)
1845 return -EINVAL;
1846 par->hw.st.mode = ST_MID;
1847 xres = sttt_xres;
1848 yres = st_yres / 2;
1849 bpp = 2;
1850 } else
1851 return -EINVAL;
1852 }
1853 if (yres_virtual <= 0)
1854 yres_virtual = 0;
1855 else if (yres_virtual < yres)
1856 yres_virtual = yres;
1857 if (var->sync & FB_SYNC_EXT)
1858 par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
1859 else
1860 par->hw.st.sync = (par->hw.st.sync & ~1);
1861 linelen = xres * bpp / 8;
1862 if (yres_virtual * linelen > screen_len && screen_len)
1863 return -EINVAL;
1864 if (yres * linelen > screen_len && screen_len)
1865 return -EINVAL;
1866 if (var->yoffset + yres > yres_virtual && yres_virtual)
1867 return -EINVAL;
1868 par->yres_virtual = yres_virtual;
1869 par->screen_base = screen_base + var->yoffset * linelen;
1870 par->next_line = linelen;
1871 return 0;
1872 }
1873
stste_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)1874 static int stste_encode_var(struct fb_var_screeninfo *var,
1875 struct atafb_par *par)
1876 {
1877 int linelen;
1878 memset(var, 0, sizeof(struct fb_var_screeninfo));
1879 var->red.offset = 0;
1880 var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1881 var->red.msb_right = 0;
1882 var->grayscale = 0;
1883
1884 var->pixclock = 31041;
1885 var->left_margin = 120; /* these are incorrect */
1886 var->right_margin = 100;
1887 var->upper_margin = 8;
1888 var->lower_margin = 16;
1889 var->hsync_len = 140;
1890 var->vsync_len = 30;
1891
1892 var->height = -1;
1893 var->width = -1;
1894
1895 if (!(par->hw.st.sync & 1))
1896 var->sync = 0;
1897 else
1898 var->sync = FB_SYNC_EXT;
1899
1900 switch (par->hw.st.mode & 3) {
1901 case ST_LOW:
1902 var->xres = sttt_xres / 2;
1903 var->yres = st_yres / 2;
1904 var->bits_per_pixel = 4;
1905 break;
1906 case ST_MID:
1907 var->xres = sttt_xres;
1908 var->yres = st_yres / 2;
1909 var->bits_per_pixel = 2;
1910 break;
1911 case ST_HIGH:
1912 var->xres = sttt_xres;
1913 var->yres = st_yres;
1914 var->bits_per_pixel = 1;
1915 break;
1916 }
1917 var->blue = var->green = var->red;
1918 var->transp.offset = 0;
1919 var->transp.length = 0;
1920 var->transp.msb_right = 0;
1921 var->xres_virtual = sttt_xres_virtual;
1922 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1923 ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
1924
1925 if (!use_hwscroll)
1926 var->yres_virtual = var->yres;
1927 else if (screen_len) {
1928 if (par->yres_virtual)
1929 var->yres_virtual = par->yres_virtual;
1930 else
1931 /* yres_virtual == 0 means use maximum */
1932 var->yres_virtual = screen_len / linelen;
1933 } else {
1934 if (hwscroll < 0)
1935 var->yres_virtual = 2 * var->yres;
1936 else
1937 var->yres_virtual = var->yres + hwscroll * 16;
1938 }
1939 var->xoffset = 0;
1940 if (screen_base)
1941 var->yoffset = (par->screen_base - screen_base) / linelen;
1942 else
1943 var->yoffset = 0;
1944 var->nonstd = 0;
1945 var->activate = 0;
1946 var->vmode = FB_VMODE_NONINTERLACED;
1947 return 0;
1948 }
1949
stste_get_par(struct atafb_par * par)1950 static void stste_get_par(struct atafb_par *par)
1951 {
1952 unsigned long addr;
1953 par->hw.st.mode = shifter_tt.st_shiftmode;
1954 par->hw.st.sync = shifter_st.syncmode;
1955 addr = ((shifter_st.bas_hi & 0xff) << 16) |
1956 ((shifter_st.bas_md & 0xff) << 8);
1957 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1958 addr |= (shifter_st.bas_lo & 0xff);
1959 par->screen_base = atari_stram_to_virt(addr);
1960 }
1961
stste_set_par(struct atafb_par * par)1962 static void stste_set_par(struct atafb_par *par)
1963 {
1964 shifter_tt.st_shiftmode = par->hw.st.mode;
1965 shifter_st.syncmode = par->hw.st.sync;
1966 /* only set screen_base if really necessary */
1967 if (current_par.screen_base != par->screen_base)
1968 fbhw->set_screen_base(par->screen_base);
1969 }
1970
stste_setcolreg(unsigned int regno,unsigned int red,unsigned int green,unsigned int blue,unsigned int transp,struct fb_info * info)1971 static int stste_setcolreg(unsigned int regno, unsigned int red,
1972 unsigned int green, unsigned int blue,
1973 unsigned int transp, struct fb_info *info)
1974 {
1975 if (regno > 15)
1976 return 1;
1977 red >>= 12;
1978 blue >>= 12;
1979 green >>= 12;
1980 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1981 shifter_tt.color_reg[regno] =
1982 (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1983 (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1984 ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1985 else
1986 shifter_tt.color_reg[regno] =
1987 ((red & 0xe) << 7) |
1988 ((green & 0xe) << 3) |
1989 ((blue & 0xe) >> 1);
1990 return 0;
1991 }
1992
stste_detect(void)1993 static int stste_detect(void)
1994 {
1995 struct atafb_par par;
1996
1997 /* Determine the connected monitor: The DMA sound must be
1998 * disabled before reading the MFP GPIP, because the Sound
1999 * Done Signal and the Monochrome Detect are XORed together!
2000 */
2001 if (ATARIHW_PRESENT(PCM_8BIT)) {
2002 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2003 udelay(20); /* wait a while for things to settle down */
2004 }
2005 mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
2006
2007 stste_get_par(&par);
2008 stste_encode_var(&atafb_predefined[0], &par);
2009
2010 if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2011 use_hwscroll = 0;
2012 return 1;
2013 }
2014
stste_set_screen_base(void * s_base)2015 static void stste_set_screen_base(void *s_base)
2016 {
2017 unsigned long addr;
2018 addr = atari_stram_to_phys(s_base);
2019 /* Setup Screen Memory */
2020 shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2021 shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2022 if (ATARIHW_PRESENT(EXTD_SHIFTER))
2023 shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
2024 }
2025
2026 #endif /* ATAFB_STE */
2027
2028 /* Switching the screen size should be done during vsync, otherwise
2029 * the margins may get messed up. This is a well known problem of
2030 * the ST's video system.
2031 *
2032 * Unfortunately there is hardly any way to find the vsync, as the
2033 * vertical blank interrupt is no longer in time on machines with
2034 * overscan type modifications.
2035 *
2036 * We can, however, use Timer B to safely detect the black shoulder,
2037 * but then we've got to guess an appropriate delay to find the vsync.
2038 * This might not work on every machine.
2039 *
2040 * martin_rogge @ ki.maus.de, 8th Aug 1995
2041 */
2042
2043 #define LINE_DELAY (mono_moni ? 30 : 70)
2044 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2045
2046 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
st_ovsc_switch(void)2047 static void st_ovsc_switch(void)
2048 {
2049 unsigned long flags;
2050 register unsigned char old, new;
2051
2052 if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2053 return;
2054 local_irq_save(flags);
2055
2056 st_mfp.tim_ct_b = 0x10;
2057 st_mfp.active_edge |= 8;
2058 st_mfp.tim_ct_b = 0;
2059 st_mfp.tim_dt_b = 0xf0;
2060 st_mfp.tim_ct_b = 8;
2061 while (st_mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2062 ;
2063 new = st_mfp.tim_dt_b;
2064 do {
2065 udelay(LINE_DELAY);
2066 old = new;
2067 new = st_mfp.tim_dt_b;
2068 } while (old != new);
2069 st_mfp.tim_ct_b = 0x10;
2070 udelay(SYNC_DELAY);
2071
2072 if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2073 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2074 if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2075 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2076 if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2077 sound_ym.rd_data_reg_sel = 14;
2078 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2079 ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2080 ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2081 }
2082 local_irq_restore(flags);
2083 }
2084
2085 /* ------------------- External Video ---------------------- */
2086
2087 #ifdef ATAFB_EXT
2088
ext_encode_fix(struct fb_fix_screeninfo * fix,struct atafb_par * par)2089 static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
2090 {
2091 strcpy(fix->id, "Unknown Extern");
2092 fix->smem_start = external_addr;
2093 fix->smem_len = PAGE_ALIGN(external_len);
2094 if (external_depth == 1) {
2095 fix->type = FB_TYPE_PACKED_PIXELS;
2096 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2097 * for "normal" and "inverted", rsp., in the monochrome case */
2098 fix->visual =
2099 (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2100 external_pmode == FB_TYPE_PACKED_PIXELS) ?
2101 FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
2102 } else {
2103 /* Use STATIC if we don't know how to access color registers */
2104 int visual = external_vgaiobase ?
2105 FB_VISUAL_PSEUDOCOLOR :
2106 FB_VISUAL_STATIC_PSEUDOCOLOR;
2107 switch (external_pmode) {
2108 case -1: /* truecolor */
2109 fix->type = FB_TYPE_PACKED_PIXELS;
2110 fix->visual = FB_VISUAL_TRUECOLOR;
2111 break;
2112 case FB_TYPE_PACKED_PIXELS:
2113 fix->type = FB_TYPE_PACKED_PIXELS;
2114 fix->visual = visual;
2115 break;
2116 case FB_TYPE_PLANES:
2117 fix->type = FB_TYPE_PLANES;
2118 fix->visual = visual;
2119 break;
2120 case FB_TYPE_INTERLEAVED_PLANES:
2121 fix->type = FB_TYPE_INTERLEAVED_PLANES;
2122 fix->type_aux = 2;
2123 fix->visual = visual;
2124 break;
2125 }
2126 }
2127 fix->xpanstep = 0;
2128 fix->ypanstep = 0;
2129 fix->ywrapstep = 0;
2130 fix->line_length = par->next_line;
2131 return 0;
2132 }
2133
ext_decode_var(struct fb_var_screeninfo * var,struct atafb_par * par)2134 static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2135 {
2136 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2137
2138 if (var->bits_per_pixel > myvar->bits_per_pixel ||
2139 var->xres > myvar->xres ||
2140 var->xres_virtual > myvar->xres_virtual ||
2141 var->yres > myvar->yres ||
2142 var->xoffset > 0 ||
2143 var->yoffset > 0)
2144 return -EINVAL;
2145
2146 par->next_line = external_xres_virtual * external_depth / 8;
2147 return 0;
2148 }
2149
ext_encode_var(struct fb_var_screeninfo * var,struct atafb_par * par)2150 static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
2151 {
2152 memset(var, 0, sizeof(struct fb_var_screeninfo));
2153 var->red.offset = 0;
2154 var->red.length = (external_pmode == -1) ? external_depth / 3 :
2155 (external_vgaiobase ? external_bitspercol : 0);
2156 var->red.msb_right = 0;
2157 var->grayscale = 0;
2158
2159 var->pixclock = 31041;
2160 var->left_margin = 120; /* these are surely incorrect */
2161 var->right_margin = 100;
2162 var->upper_margin = 8;
2163 var->lower_margin = 16;
2164 var->hsync_len = 140;
2165 var->vsync_len = 30;
2166
2167 var->height = -1;
2168 var->width = -1;
2169
2170 var->sync = 0;
2171
2172 var->xres = external_xres;
2173 var->yres = external_yres;
2174 var->xres_virtual = external_xres_virtual;
2175 var->bits_per_pixel = external_depth;
2176
2177 var->blue = var->green = var->red;
2178 var->transp.offset = 0;
2179 var->transp.length = 0;
2180 var->transp.msb_right = 0;
2181 var->yres_virtual = var->yres;
2182 var->xoffset = 0;
2183 var->yoffset = 0;
2184 var->nonstd = 0;
2185 var->activate = 0;
2186 var->vmode = FB_VMODE_NONINTERLACED;
2187 return 0;
2188 }
2189
ext_get_par(struct atafb_par * par)2190 static void ext_get_par(struct atafb_par *par)
2191 {
2192 par->screen_base = external_screen_base;
2193 }
2194
ext_set_par(struct atafb_par * par)2195 static void ext_set_par(struct atafb_par *par)
2196 {
2197 }
2198
2199 #define OUTB(port,val) \
2200 *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
2201 #define INB(port) \
2202 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2203 #define DACDelay \
2204 do { \
2205 unsigned char tmp = INB(0x3da); \
2206 tmp = INB(0x3da); \
2207 } while (0)
2208
ext_setcolreg(unsigned int regno,unsigned int red,unsigned int green,unsigned int blue,unsigned int transp,struct fb_info * info)2209 static int ext_setcolreg(unsigned int regno, unsigned int red,
2210 unsigned int green, unsigned int blue,
2211 unsigned int transp, struct fb_info *info)
2212 {
2213 unsigned char colmask = (1 << external_bitspercol) - 1;
2214
2215 if (!external_vgaiobase)
2216 return 1;
2217
2218 if (regno > 255)
2219 return 1;
2220
2221 switch (external_card_type) {
2222 case IS_VGA:
2223 OUTB(0x3c8, regno);
2224 DACDelay;
2225 OUTB(0x3c9, red & colmask);
2226 DACDelay;
2227 OUTB(0x3c9, green & colmask);
2228 DACDelay;
2229 OUTB(0x3c9, blue & colmask);
2230 DACDelay;
2231 return 0;
2232
2233 case IS_MV300:
2234 OUTB((MV300_reg[regno] << 2) + 1, red);
2235 OUTB((MV300_reg[regno] << 2) + 1, green);
2236 OUTB((MV300_reg[regno] << 2) + 1, blue);
2237 return 0;
2238
2239 default:
2240 return 1;
2241 }
2242 }
2243
ext_detect(void)2244 static int ext_detect(void)
2245 {
2246 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2247 struct atafb_par dummy_par;
2248
2249 myvar->xres = external_xres;
2250 myvar->xres_virtual = external_xres_virtual;
2251 myvar->yres = external_yres;
2252 myvar->bits_per_pixel = external_depth;
2253 ext_encode_var(myvar, &dummy_par);
2254 return 1;
2255 }
2256
2257 #endif /* ATAFB_EXT */
2258
2259 /* ------ This is the same for most hardware types -------- */
2260
set_screen_base(void * s_base)2261 static void set_screen_base(void *s_base)
2262 {
2263 unsigned long addr;
2264
2265 addr = atari_stram_to_phys(s_base);
2266 /* Setup Screen Memory */
2267 shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
2268 shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
2269 shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
2270 }
2271
pan_display(struct fb_var_screeninfo * var,struct fb_info * info)2272 static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2273 {
2274 struct atafb_par *par = (struct atafb_par *)info->par;
2275
2276 if (!fbhw->set_screen_base ||
2277 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2278 return -EINVAL;
2279 var->xoffset = up(var->xoffset, 16);
2280 par->screen_base = screen_base +
2281 (var->yoffset * info->var.xres_virtual + var->xoffset)
2282 * info->var.bits_per_pixel / 8;
2283 fbhw->set_screen_base(par->screen_base);
2284 return 0;
2285 }
2286
2287 /* ------------ Interfaces to hardware functions ------------ */
2288
2289 #ifdef ATAFB_TT
2290 static struct fb_hwswitch tt_switch = {
2291 .detect = tt_detect,
2292 .encode_fix = tt_encode_fix,
2293 .decode_var = tt_decode_var,
2294 .encode_var = tt_encode_var,
2295 .get_par = tt_get_par,
2296 .set_par = tt_set_par,
2297 .set_screen_base = set_screen_base,
2298 .pan_display = pan_display,
2299 };
2300 #endif
2301
2302 #ifdef ATAFB_FALCON
2303 static struct fb_hwswitch falcon_switch = {
2304 .detect = falcon_detect,
2305 .encode_fix = falcon_encode_fix,
2306 .decode_var = falcon_decode_var,
2307 .encode_var = falcon_encode_var,
2308 .get_par = falcon_get_par,
2309 .set_par = falcon_set_par,
2310 .set_screen_base = set_screen_base,
2311 .blank = falcon_blank,
2312 .pan_display = falcon_pan_display,
2313 };
2314 #endif
2315
2316 #ifdef ATAFB_STE
2317 static struct fb_hwswitch st_switch = {
2318 .detect = stste_detect,
2319 .encode_fix = stste_encode_fix,
2320 .decode_var = stste_decode_var,
2321 .encode_var = stste_encode_var,
2322 .get_par = stste_get_par,
2323 .set_par = stste_set_par,
2324 .set_screen_base = stste_set_screen_base,
2325 .pan_display = pan_display
2326 };
2327 #endif
2328
2329 #ifdef ATAFB_EXT
2330 static struct fb_hwswitch ext_switch = {
2331 .detect = ext_detect,
2332 .encode_fix = ext_encode_fix,
2333 .decode_var = ext_decode_var,
2334 .encode_var = ext_encode_var,
2335 .get_par = ext_get_par,
2336 .set_par = ext_set_par,
2337 };
2338 #endif
2339
ata_get_par(struct atafb_par * par)2340 static void ata_get_par(struct atafb_par *par)
2341 {
2342 if (current_par_valid)
2343 *par = current_par;
2344 else
2345 fbhw->get_par(par);
2346 }
2347
ata_set_par(struct atafb_par * par)2348 static void ata_set_par(struct atafb_par *par)
2349 {
2350 fbhw->set_par(par);
2351 current_par = *par;
2352 current_par_valid = 1;
2353 }
2354
2355
2356 /* =========================================================== */
2357 /* ============== Hardware Independent Functions ============= */
2358 /* =========================================================== */
2359
2360 /* used for hardware scrolling */
2361
do_fb_set_var(struct fb_var_screeninfo * var,int isactive)2362 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2363 {
2364 int err, activate;
2365 struct atafb_par par;
2366
2367 err = fbhw->decode_var(var, &par);
2368 if (err)
2369 return err;
2370 activate = var->activate;
2371 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2372 ata_set_par(&par);
2373 fbhw->encode_var(var, &par);
2374 var->activate = activate;
2375 return 0;
2376 }
2377
2378 /* fbhw->encode_fix() must be called with fb_info->mm_lock held
2379 * if it is called after the register_framebuffer() - not a case here
2380 */
atafb_get_fix(struct fb_fix_screeninfo * fix,struct fb_info * info)2381 static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2382 {
2383 struct atafb_par par;
2384 int err;
2385 // Get fix directly (case con == -1 before)??
2386 err = fbhw->decode_var(&info->var, &par);
2387 if (err)
2388 return err;
2389 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2390 err = fbhw->encode_fix(fix, &par);
2391 return err;
2392 }
2393
atafb_get_var(struct fb_var_screeninfo * var,struct fb_info * info)2394 static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
2395 {
2396 struct atafb_par par;
2397
2398 ata_get_par(&par);
2399 fbhw->encode_var(var, &par);
2400
2401 return 0;
2402 }
2403
2404 // No longer called by fbcon!
2405 // Still called by set_var internally
2406
atafb_set_disp(struct fb_info * info)2407 static void atafb_set_disp(struct fb_info *info)
2408 {
2409 atafb_get_var(&info->var, info);
2410 atafb_get_fix(&info->fix, info);
2411
2412 /* Note: smem_start derives from phys_screen_base, not screen_base! */
2413 info->screen_base = (external_addr ? external_screen_base :
2414 atari_stram_to_virt(info->fix.smem_start));
2415 }
2416
atafb_setcolreg(u_int regno,u_int red,u_int green,u_int blue,u_int transp,struct fb_info * info)2417 static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2418 u_int transp, struct fb_info *info)
2419 {
2420 red >>= 8;
2421 green >>= 8;
2422 blue >>= 8;
2423
2424 return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
2425 }
2426
2427 static int
atafb_pan_display(struct fb_var_screeninfo * var,struct fb_info * info)2428 atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
2429 {
2430 int xoffset = var->xoffset;
2431 int yoffset = var->yoffset;
2432 int err;
2433
2434 if (var->vmode & FB_VMODE_YWRAP) {
2435 if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
2436 return -EINVAL;
2437 } else {
2438 if (xoffset + info->var.xres > info->var.xres_virtual ||
2439 yoffset + info->var.yres > info->var.yres_virtual)
2440 return -EINVAL;
2441 }
2442
2443 if (fbhw->pan_display) {
2444 err = fbhw->pan_display(var, info);
2445 if (err)
2446 return err;
2447 } else
2448 return -EINVAL;
2449
2450 info->var.xoffset = xoffset;
2451 info->var.yoffset = yoffset;
2452
2453 if (var->vmode & FB_VMODE_YWRAP)
2454 info->var.vmode |= FB_VMODE_YWRAP;
2455 else
2456 info->var.vmode &= ~FB_VMODE_YWRAP;
2457
2458 return 0;
2459 }
2460
2461 /*
2462 * generic drawing routines; imageblit needs updating for image depth > 1
2463 */
2464
2465 #if BITS_PER_LONG == 32
2466 #define BYTES_PER_LONG 4
2467 #define SHIFT_PER_LONG 5
2468 #elif BITS_PER_LONG == 64
2469 #define BYTES_PER_LONG 8
2470 #define SHIFT_PER_LONG 6
2471 #else
2472 #define Please update me
2473 #endif
2474
2475
atafb_fillrect(struct fb_info * info,const struct fb_fillrect * rect)2476 static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
2477 {
2478 struct atafb_par *par = (struct atafb_par *)info->par;
2479 int x2, y2;
2480 u32 width, height;
2481
2482 if (!rect->width || !rect->height)
2483 return;
2484
2485 #ifdef ATAFB_FALCON
2486 if (info->var.bits_per_pixel == 16) {
2487 cfb_fillrect(info, rect);
2488 return;
2489 }
2490 #endif
2491
2492 /*
2493 * We could use hardware clipping but on many cards you get around
2494 * hardware clipping by writing to framebuffer directly.
2495 * */
2496 x2 = rect->dx + rect->width;
2497 y2 = rect->dy + rect->height;
2498 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2499 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2500 width = x2 - rect->dx;
2501 height = y2 - rect->dy;
2502
2503 if (info->var.bits_per_pixel == 1)
2504 atafb_mfb_fillrect(info, par->next_line, rect->color,
2505 rect->dy, rect->dx, height, width);
2506 else if (info->var.bits_per_pixel == 2)
2507 atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
2508 rect->dy, rect->dx, height, width);
2509 else if (info->var.bits_per_pixel == 4)
2510 atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
2511 rect->dy, rect->dx, height, width);
2512 else
2513 atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
2514 rect->dy, rect->dx, height, width);
2515
2516 return;
2517 }
2518
atafb_copyarea(struct fb_info * info,const struct fb_copyarea * area)2519 static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2520 {
2521 struct atafb_par *par = (struct atafb_par *)info->par;
2522 int x2, y2;
2523 u32 dx, dy, sx, sy, width, height;
2524 int rev_copy = 0;
2525
2526 #ifdef ATAFB_FALCON
2527 if (info->var.bits_per_pixel == 16) {
2528 cfb_copyarea(info, area);
2529 return;
2530 }
2531 #endif
2532
2533 /* clip the destination */
2534 x2 = area->dx + area->width;
2535 y2 = area->dy + area->height;
2536 dx = area->dx > 0 ? area->dx : 0;
2537 dy = area->dy > 0 ? area->dy : 0;
2538 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2539 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2540 width = x2 - dx;
2541 height = y2 - dy;
2542
2543 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2544 return;
2545
2546 /* update sx,sy */
2547 sx = area->sx + (dx - area->dx);
2548 sy = area->sy + (dy - area->dy);
2549
2550 /* the source must be completely inside the virtual screen */
2551 if (sx + width > info->var.xres_virtual ||
2552 sy + height > info->var.yres_virtual)
2553 return;
2554
2555 if (dy > sy || (dy == sy && dx > sx)) {
2556 dy += height;
2557 sy += height;
2558 rev_copy = 1;
2559 }
2560
2561 if (info->var.bits_per_pixel == 1)
2562 atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2563 else if (info->var.bits_per_pixel == 2)
2564 atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2565 else if (info->var.bits_per_pixel == 4)
2566 atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2567 else
2568 atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
2569
2570 return;
2571 }
2572
atafb_imageblit(struct fb_info * info,const struct fb_image * image)2573 static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
2574 {
2575 struct atafb_par *par = (struct atafb_par *)info->par;
2576 int x2, y2;
2577 unsigned long *dst;
2578 int dst_idx;
2579 const char *src;
2580 u32 dx, dy, width, height, pitch;
2581
2582 #ifdef ATAFB_FALCON
2583 if (info->var.bits_per_pixel == 16) {
2584 cfb_imageblit(info, image);
2585 return;
2586 }
2587 #endif
2588
2589 /*
2590 * We could use hardware clipping but on many cards you get around
2591 * hardware clipping by writing to framebuffer directly like we are
2592 * doing here.
2593 */
2594 x2 = image->dx + image->width;
2595 y2 = image->dy + image->height;
2596 dx = image->dx;
2597 dy = image->dy;
2598 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2599 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2600 width = x2 - dx;
2601 height = y2 - dy;
2602
2603 if (image->depth == 1) {
2604 // used for font data
2605 dst = (unsigned long *)
2606 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2607 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2608 dst_idx += dy * par->next_line * 8 + dx;
2609 src = image->data;
2610 pitch = (image->width + 7) / 8;
2611 while (height--) {
2612
2613 if (info->var.bits_per_pixel == 1)
2614 atafb_mfb_linefill(info, par->next_line,
2615 dy, dx, width, src,
2616 image->bg_color, image->fg_color);
2617 else if (info->var.bits_per_pixel == 2)
2618 atafb_iplan2p2_linefill(info, par->next_line,
2619 dy, dx, width, src,
2620 image->bg_color, image->fg_color);
2621 else if (info->var.bits_per_pixel == 4)
2622 atafb_iplan2p4_linefill(info, par->next_line,
2623 dy, dx, width, src,
2624 image->bg_color, image->fg_color);
2625 else
2626 atafb_iplan2p8_linefill(info, par->next_line,
2627 dy, dx, width, src,
2628 image->bg_color, image->fg_color);
2629 dy++;
2630 src += pitch;
2631 }
2632 } else {
2633 c2p_iplan2(info->screen_base, image->data, dx, dy, width,
2634 height, par->next_line, image->width,
2635 info->var.bits_per_pixel);
2636 }
2637 }
2638
2639 static int
atafb_ioctl(struct fb_info * info,unsigned int cmd,unsigned long arg)2640 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2641 {
2642 switch (cmd) {
2643 #ifdef FBCMD_GET_CURRENTPAR
2644 case FBCMD_GET_CURRENTPAR:
2645 if (copy_to_user((void *)arg, (void *)¤t_par,
2646 sizeof(struct atafb_par)))
2647 return -EFAULT;
2648 return 0;
2649 #endif
2650 #ifdef FBCMD_SET_CURRENTPAR
2651 case FBCMD_SET_CURRENTPAR:
2652 if (copy_from_user((void *)¤t_par, (void *)arg,
2653 sizeof(struct atafb_par)))
2654 return -EFAULT;
2655 ata_set_par(¤t_par);
2656 return 0;
2657 #endif
2658 }
2659 return -EINVAL;
2660 }
2661
2662 /* (un)blank/poweroff
2663 * 0 = unblank
2664 * 1 = blank
2665 * 2 = suspend vsync
2666 * 3 = suspend hsync
2667 * 4 = off
2668 */
atafb_blank(int blank,struct fb_info * info)2669 static int atafb_blank(int blank, struct fb_info *info)
2670 {
2671 unsigned short black[16];
2672 struct fb_cmap cmap;
2673 if (fbhw->blank && !fbhw->blank(blank))
2674 return 1;
2675 if (blank) {
2676 memset(black, 0, 16 * sizeof(unsigned short));
2677 cmap.red = black;
2678 cmap.green = black;
2679 cmap.blue = black;
2680 cmap.transp = NULL;
2681 cmap.start = 0;
2682 cmap.len = 16;
2683 fb_set_cmap(&cmap, info);
2684 }
2685 #if 0
2686 else
2687 do_install_cmap(info);
2688 #endif
2689 return 0;
2690 }
2691
2692 /*
2693 * New fbcon interface ...
2694 */
2695
2696 /* check var by decoding var into hw par, rounding if necessary,
2697 * then encoding hw par back into new, validated var */
atafb_check_var(struct fb_var_screeninfo * var,struct fb_info * info)2698 static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2699 {
2700 int err;
2701 struct atafb_par par;
2702
2703 /* Validate wanted screen parameters */
2704 // if ((err = ata_decode_var(var, &par)))
2705 err = fbhw->decode_var(var, &par);
2706 if (err)
2707 return err;
2708
2709 /* Encode (possibly rounded) screen parameters */
2710 fbhw->encode_var(var, &par);
2711 return 0;
2712 }
2713
2714 /* actually set hw par by decoding var, then setting hardware from
2715 * hw par just decoded */
atafb_set_par(struct fb_info * info)2716 static int atafb_set_par(struct fb_info *info)
2717 {
2718 struct atafb_par *par = (struct atafb_par *)info->par;
2719
2720 /* Decode wanted screen parameters */
2721 fbhw->decode_var(&info->var, par);
2722 mutex_lock(&info->mm_lock);
2723 fbhw->encode_fix(&info->fix, par);
2724 mutex_unlock(&info->mm_lock);
2725
2726 /* Set new videomode */
2727 ata_set_par(par);
2728
2729 return 0;
2730 }
2731
2732
2733 static struct fb_ops atafb_ops = {
2734 .owner = THIS_MODULE,
2735 .fb_check_var = atafb_check_var,
2736 .fb_set_par = atafb_set_par,
2737 .fb_setcolreg = atafb_setcolreg,
2738 .fb_blank = atafb_blank,
2739 .fb_pan_display = atafb_pan_display,
2740 .fb_fillrect = atafb_fillrect,
2741 .fb_copyarea = atafb_copyarea,
2742 .fb_imageblit = atafb_imageblit,
2743 .fb_ioctl = atafb_ioctl,
2744 };
2745
check_default_par(int detected_mode)2746 static void check_default_par(int detected_mode)
2747 {
2748 char default_name[10];
2749 int i;
2750 struct fb_var_screeninfo var;
2751 unsigned long min_mem;
2752
2753 /* First try the user supplied mode */
2754 if (default_par) {
2755 var = atafb_predefined[default_par - 1];
2756 var.activate = FB_ACTIVATE_TEST;
2757 if (do_fb_set_var(&var, 1))
2758 default_par = 0; /* failed */
2759 }
2760 /* Next is the autodetected one */
2761 if (!default_par) {
2762 var = atafb_predefined[detected_mode - 1]; /* autodetect */
2763 var.activate = FB_ACTIVATE_TEST;
2764 if (!do_fb_set_var(&var, 1))
2765 default_par = detected_mode;
2766 }
2767 /* If that also failed, try some default modes... */
2768 if (!default_par) {
2769 /* try default1, default2... */
2770 for (i = 1; i < 10; i++) {
2771 sprintf(default_name,"default%d", i);
2772 default_par = get_video_mode(default_name);
2773 if (!default_par)
2774 panic("can't set default video mode");
2775 var = atafb_predefined[default_par - 1];
2776 var.activate = FB_ACTIVATE_TEST;
2777 if (!do_fb_set_var(&var,1))
2778 break; /* ok */
2779 }
2780 }
2781 min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
2782 if (default_mem_req < min_mem)
2783 default_mem_req = min_mem;
2784 }
2785
2786 #ifdef ATAFB_EXT
atafb_setup_ext(char * spec)2787 static void __init atafb_setup_ext(char *spec)
2788 {
2789 int xres, xres_virtual, yres, depth, planes;
2790 unsigned long addr, len;
2791 char *p;
2792
2793 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2794 * <screen mem addr>
2795 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2796 * [;<xres-virtual>]]]]]
2797 *
2798 * 09/23/97 Juergen
2799 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2800 *
2801 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2802 */
2803 p = strsep(&spec, ";");
2804 if (!p || !*p)
2805 return;
2806 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2807 if (xres <= 0)
2808 return;
2809
2810 p = strsep(&spec, ";");
2811 if (!p || !*p)
2812 return;
2813 yres = simple_strtoul(p, NULL, 10);
2814 if (yres <= 0)
2815 return;
2816
2817 p = strsep(&spec, ";");
2818 if (!p || !*p)
2819 return;
2820 depth = simple_strtoul(p, NULL, 10);
2821 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2822 depth != 16 && depth != 24)
2823 return;
2824
2825 p = strsep(&spec, ";");
2826 if (!p || !*p)
2827 return;
2828 if (*p == 'i')
2829 planes = FB_TYPE_INTERLEAVED_PLANES;
2830 else if (*p == 'p')
2831 planes = FB_TYPE_PACKED_PIXELS;
2832 else if (*p == 'n')
2833 planes = FB_TYPE_PLANES;
2834 else if (*p == 't')
2835 planes = -1; /* true color */
2836 else
2837 return;
2838
2839 p = strsep(&spec, ";");
2840 if (!p || !*p)
2841 return;
2842 addr = simple_strtoul(p, NULL, 0);
2843
2844 p = strsep(&spec, ";");
2845 if (!p || !*p)
2846 len = xres * yres * depth / 8;
2847 else
2848 len = simple_strtoul(p, NULL, 0);
2849
2850 p = strsep(&spec, ";");
2851 if (p && *p)
2852 external_vgaiobase = simple_strtoul(p, NULL, 0);
2853
2854 p = strsep(&spec, ";");
2855 if (p && *p) {
2856 external_bitspercol = simple_strtoul(p, NULL, 0);
2857 if (external_bitspercol > 8)
2858 external_bitspercol = 8;
2859 else if (external_bitspercol < 1)
2860 external_bitspercol = 1;
2861 }
2862
2863 p = strsep(&spec, ";");
2864 if (p && *p) {
2865 if (!strcmp(p, "vga"))
2866 external_card_type = IS_VGA;
2867 if (!strcmp(p, "mv300"))
2868 external_card_type = IS_MV300;
2869 }
2870
2871 p = strsep(&spec, ";");
2872 if (p && *p) {
2873 xres_virtual = simple_strtoul(p, NULL, 10);
2874 if (xres_virtual < xres)
2875 xres_virtual = xres;
2876 if (xres_virtual * yres * depth / 8 > len)
2877 len = xres_virtual * yres * depth / 8;
2878 }
2879
2880 external_xres = xres;
2881 external_xres_virtual = xres_virtual;
2882 external_yres = yres;
2883 external_depth = depth;
2884 external_pmode = planes;
2885 external_addr = addr;
2886 external_len = len;
2887
2888 if (external_card_type == IS_MV300) {
2889 switch (external_depth) {
2890 case 1:
2891 MV300_reg = MV300_reg_1bit;
2892 break;
2893 case 4:
2894 MV300_reg = MV300_reg_4bit;
2895 break;
2896 case 8:
2897 MV300_reg = MV300_reg_8bit;
2898 break;
2899 }
2900 }
2901 }
2902 #endif /* ATAFB_EXT */
2903
atafb_setup_int(char * spec)2904 static void __init atafb_setup_int(char *spec)
2905 {
2906 /* Format to config extended internal video hardware like OverScan:
2907 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2908 * Explanation:
2909 * <xres>: x-resolution
2910 * <yres>: y-resolution
2911 * The following are only needed if you have an overscan which
2912 * needs a black border:
2913 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2914 * <yres_max>: max. number of lines your OverScan hardware would allow
2915 * <offset>: Offset from physical beginning to visible beginning
2916 * of screen in bytes
2917 */
2918 int xres;
2919 char *p;
2920
2921 if (!(p = strsep(&spec, ";")) || !*p)
2922 return;
2923 xres = simple_strtoul(p, NULL, 10);
2924 if (!(p = strsep(&spec, ";")) || !*p)
2925 return;
2926 sttt_xres = xres;
2927 tt_yres = st_yres = simple_strtoul(p, NULL, 10);
2928 if ((p = strsep(&spec, ";")) && *p)
2929 sttt_xres_virtual = simple_strtoul(p, NULL, 10);
2930 if ((p = strsep(&spec, ";")) && *p)
2931 sttt_yres_virtual = simple_strtoul(p, NULL, 0);
2932 if ((p = strsep(&spec, ";")) && *p)
2933 ovsc_offset = simple_strtoul(p, NULL, 0);
2934
2935 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2936 use_hwscroll = 0;
2937 }
2938
2939 #ifdef ATAFB_FALCON
atafb_setup_mcap(char * spec)2940 static void __init atafb_setup_mcap(char *spec)
2941 {
2942 char *p;
2943 int vmin, vmax, hmin, hmax;
2944
2945 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2946 * <V*> vertical freq. in Hz
2947 * <H*> horizontal freq. in kHz
2948 */
2949 if (!(p = strsep(&spec, ";")) || !*p)
2950 return;
2951 vmin = simple_strtoul(p, NULL, 10);
2952 if (vmin <= 0)
2953 return;
2954 if (!(p = strsep(&spec, ";")) || !*p)
2955 return;
2956 vmax = simple_strtoul(p, NULL, 10);
2957 if (vmax <= 0 || vmax <= vmin)
2958 return;
2959 if (!(p = strsep(&spec, ";")) || !*p)
2960 return;
2961 hmin = 1000 * simple_strtoul(p, NULL, 10);
2962 if (hmin <= 0)
2963 return;
2964 if (!(p = strsep(&spec, "")) || !*p)
2965 return;
2966 hmax = 1000 * simple_strtoul(p, NULL, 10);
2967 if (hmax <= 0 || hmax <= hmin)
2968 return;
2969
2970 fb_info.monspecs.vfmin = vmin;
2971 fb_info.monspecs.vfmax = vmax;
2972 fb_info.monspecs.hfmin = hmin;
2973 fb_info.monspecs.hfmax = hmax;
2974 }
2975 #endif /* ATAFB_FALCON */
2976
atafb_setup_user(char * spec)2977 static void __init atafb_setup_user(char *spec)
2978 {
2979 /* Format of user defined video mode is: <xres>;<yres>;<depth>
2980 */
2981 char *p;
2982 int xres, yres, depth, temp;
2983
2984 p = strsep(&spec, ";");
2985 if (!p || !*p)
2986 return;
2987 xres = simple_strtoul(p, NULL, 10);
2988 p = strsep(&spec, ";");
2989 if (!p || !*p)
2990 return;
2991 yres = simple_strtoul(p, NULL, 10);
2992 p = strsep(&spec, "");
2993 if (!p || !*p)
2994 return;
2995 depth = simple_strtoul(p, NULL, 10);
2996 temp = get_video_mode("user0");
2997 if (temp) {
2998 default_par = temp;
2999 atafb_predefined[default_par - 1].xres = xres;
3000 atafb_predefined[default_par - 1].yres = yres;
3001 atafb_predefined[default_par - 1].bits_per_pixel = depth;
3002 }
3003 }
3004
atafb_setup(char * options)3005 int __init atafb_setup(char *options)
3006 {
3007 char *this_opt;
3008 int temp;
3009
3010 if (!options || !*options)
3011 return 0;
3012
3013 while ((this_opt = strsep(&options, ",")) != NULL) {
3014 if (!*this_opt)
3015 continue;
3016 if ((temp = get_video_mode(this_opt))) {
3017 default_par = temp;
3018 mode_option = this_opt;
3019 } else if (!strcmp(this_opt, "inverse"))
3020 inverse = 1;
3021 else if (!strncmp(this_opt, "hwscroll_", 9)) {
3022 hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
3023 if (hwscroll < 0)
3024 hwscroll = 0;
3025 if (hwscroll > 200)
3026 hwscroll = 200;
3027 }
3028 #ifdef ATAFB_EXT
3029 else if (!strcmp(this_opt, "mv300")) {
3030 external_bitspercol = 8;
3031 external_card_type = IS_MV300;
3032 } else if (!strncmp(this_opt, "external:", 9))
3033 atafb_setup_ext(this_opt + 9);
3034 #endif
3035 else if (!strncmp(this_opt, "internal:", 9))
3036 atafb_setup_int(this_opt + 9);
3037 #ifdef ATAFB_FALCON
3038 else if (!strncmp(this_opt, "eclock:", 7)) {
3039 fext.f = simple_strtoul(this_opt + 7, NULL, 10);
3040 /* external pixelclock in kHz --> ps */
3041 fext.t = 1000000000 / fext.f;
3042 fext.f *= 1000;
3043 } else if (!strncmp(this_opt, "monitorcap:", 11))
3044 atafb_setup_mcap(this_opt + 11);
3045 #endif
3046 else if (!strcmp(this_opt, "keep"))
3047 DontCalcRes = 1;
3048 else if (!strncmp(this_opt, "R", 1))
3049 atafb_setup_user(this_opt + 1);
3050 }
3051 return 0;
3052 }
3053
atafb_probe(struct platform_device * pdev)3054 static int __init atafb_probe(struct platform_device *pdev)
3055 {
3056 int pad, detected_mode, error;
3057 unsigned int defmode = 0;
3058 unsigned long mem_req;
3059 char *option = NULL;
3060
3061 if (fb_get_options("atafb", &option))
3062 return -ENODEV;
3063 atafb_setup(option);
3064 dev_dbg(&pdev->dev, "%s: start\n", __func__);
3065
3066 do {
3067 #ifdef ATAFB_EXT
3068 if (external_addr) {
3069 dev_dbg(&pdev->dev, "initializing external hw\n");
3070 fbhw = &ext_switch;
3071 atafb_ops.fb_setcolreg = &ext_setcolreg;
3072 defmode = DEFMODE_EXT;
3073 break;
3074 }
3075 #endif
3076 #ifdef ATAFB_TT
3077 if (ATARIHW_PRESENT(TT_SHIFTER)) {
3078 dev_dbg(&pdev->dev, "initializing TT hw\n");
3079 fbhw = &tt_switch;
3080 atafb_ops.fb_setcolreg = &tt_setcolreg;
3081 defmode = DEFMODE_TT;
3082 break;
3083 }
3084 #endif
3085 #ifdef ATAFB_FALCON
3086 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
3087 dev_dbg(&pdev->dev, "initializing Falcon hw\n");
3088 fbhw = &falcon_switch;
3089 atafb_ops.fb_setcolreg = &falcon_setcolreg;
3090 error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 0,
3091 "framebuffer:modeswitch",
3092 falcon_vbl_switcher);
3093 if (error)
3094 return error;
3095 defmode = DEFMODE_F30;
3096 break;
3097 }
3098 #endif
3099 #ifdef ATAFB_STE
3100 if (ATARIHW_PRESENT(STND_SHIFTER) ||
3101 ATARIHW_PRESENT(EXTD_SHIFTER)) {
3102 dev_dbg(&pdev->dev, "initializing ST/E hw\n");
3103 fbhw = &st_switch;
3104 atafb_ops.fb_setcolreg = &stste_setcolreg;
3105 defmode = DEFMODE_STE;
3106 break;
3107 }
3108 fbhw = &st_switch;
3109 atafb_ops.fb_setcolreg = &stste_setcolreg;
3110 dev_warn(&pdev->dev,
3111 "Cannot determine video hardware; defaulting to ST(e)\n");
3112 #else /* ATAFB_STE */
3113 /* no default driver included */
3114 /* Nobody will ever see this message :-) */
3115 panic("Cannot initialize video hardware");
3116 #endif
3117 } while (0);
3118
3119 /* Multisync monitor capabilities */
3120 /* Atari-TOS defaults if no boot option present */
3121 if (fb_info.monspecs.hfmin == 0) {
3122 fb_info.monspecs.hfmin = 31000;
3123 fb_info.monspecs.hfmax = 32000;
3124 fb_info.monspecs.vfmin = 58;
3125 fb_info.monspecs.vfmax = 62;
3126 }
3127
3128 detected_mode = fbhw->detect();
3129 check_default_par(detected_mode);
3130 #ifdef ATAFB_EXT
3131 if (!external_addr) {
3132 #endif /* ATAFB_EXT */
3133 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
3134 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
3135 screen_base = atari_stram_alloc(mem_req, "atafb");
3136 if (!screen_base)
3137 panic("Cannot allocate screen memory");
3138 memset(screen_base, 0, mem_req);
3139 pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
3140 screen_base += pad;
3141 phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
3142 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
3143 st_ovsc_switch();
3144 if (CPU_IS_040_OR_060) {
3145 /* On a '040+, the cache mode of video RAM must be set to
3146 * write-through also for internal video hardware! */
3147 cache_push(atari_stram_to_phys(screen_base), screen_len);
3148 kernel_set_cachemode(screen_base, screen_len,
3149 IOMAP_WRITETHROUGH);
3150 }
3151 dev_info(&pdev->dev, "phys_screen_base %lx screen_len %d\n",
3152 phys_screen_base, screen_len);
3153 #ifdef ATAFB_EXT
3154 } else {
3155 /* Map the video memory (physical address given) to somewhere
3156 * in the kernel address space.
3157 */
3158 external_screen_base = ioremap_wt(external_addr, external_len);
3159 if (external_vgaiobase)
3160 external_vgaiobase =
3161 (unsigned long)ioremap(external_vgaiobase, 0x10000);
3162 screen_base = external_screen_base;
3163 phys_screen_base = external_addr;
3164 screen_len = external_len & PAGE_MASK;
3165 memset (screen_base, 0, external_len);
3166 }
3167 #endif /* ATAFB_EXT */
3168
3169 // strcpy(fb_info.mode->name, "Atari Builtin ");
3170 fb_info.fbops = &atafb_ops;
3171 // try to set default (detected; requested) var
3172 do_fb_set_var(&atafb_predefined[default_par - 1], 1);
3173 // reads hw state into current par, which may not be sane yet
3174 ata_get_par(¤t_par);
3175 fb_info.par = ¤t_par;
3176 // tries to read from HW which may not be initialized yet
3177 // so set sane var first, then call atafb_set_par
3178 atafb_get_var(&fb_info.var, &fb_info);
3179
3180 #ifdef ATAFB_FALCON
3181 fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
3182 #endif
3183 fb_info.flags = FBINFO_FLAG_DEFAULT;
3184
3185 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
3186 NUM_TOTAL_MODES, &atafb_modedb[defmode],
3187 fb_info.var.bits_per_pixel)) {
3188 return -EINVAL;
3189 }
3190
3191 fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
3192 &fb_info.modelist);
3193
3194 atafb_set_disp(&fb_info);
3195
3196 fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
3197
3198
3199 dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
3200 fb_info.var.yres, fb_info.var.bits_per_pixel);
3201 if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
3202 (fb_info.var.yres != fb_info.var.yres_virtual))
3203 dev_info(&pdev->dev, " virtual %dx%d\n",
3204 fb_info.var.xres_virtual, fb_info.var.yres_virtual);
3205
3206 if (register_framebuffer(&fb_info) < 0) {
3207 #ifdef ATAFB_EXT
3208 if (external_addr) {
3209 iounmap(external_screen_base);
3210 external_addr = 0;
3211 }
3212 if (external_vgaiobase) {
3213 iounmap((void*)external_vgaiobase);
3214 external_vgaiobase = 0;
3215 }
3216 #endif
3217 return -EINVAL;
3218 }
3219
3220 fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
3221 screen_len >> 10);
3222
3223 /* TODO: This driver cannot be unloaded yet */
3224 return 0;
3225 }
3226
atafb_shutdown(struct platform_device * pdev)3227 static void atafb_shutdown(struct platform_device *pdev)
3228 {
3229 /* Unblank before kexec */
3230 if (fbhw->blank)
3231 fbhw->blank(0);
3232 }
3233
3234 static struct platform_driver atafb_driver = {
3235 .shutdown = atafb_shutdown,
3236 .driver = {
3237 .name = "atafb",
3238 },
3239 };
3240
atafb_init(void)3241 static int __init atafb_init(void)
3242 {
3243 struct platform_device *pdev;
3244
3245 if (!MACH_IS_ATARI)
3246 return -ENODEV;
3247
3248 pdev = platform_device_register_simple("atafb", -1, NULL, 0);
3249 if (IS_ERR(pdev))
3250 return PTR_ERR(pdev);
3251
3252 return platform_driver_probe(&atafb_driver, atafb_probe);
3253 }
3254
3255 device_initcall(atafb_init);
3256