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

source code of linux/drivers/video/fbdev/atafb.c