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