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