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