clgenfb.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:96k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets
  3.  *
  4.  * Copyright 1999-2001 Jeff Garzik <jgarzik@mandrakesoft.com>
  5.  *
  6.  * Contributors (thanks, all!)
  7.  *
  8.  *      Jeff Rugen:
  9.  *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
  10.  *      GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
  11.  *
  12.  * Geert Uytterhoeven:
  13.  * Excellent code review.
  14.  *
  15.  * Lars Hecking:
  16.  * Amiga updates and testing.
  17.  *
  18.  * Original clgenfb author:  Frank Neumann
  19.  *
  20.  * Based on retz3fb.c and clgen.c:
  21.  *      Copyright (C) 1997 Jes Sorensen
  22.  *      Copyright (C) 1996 Frank Neumann
  23.  *
  24.  ***************************************************************
  25.  *
  26.  * Format this code with GNU indent '-kr -i8 -pcs' options.
  27.  *
  28.  * This file is subject to the terms and conditions of the GNU General Public
  29.  * License.  See the file COPYING in the main directory of this archive
  30.  * for more details.
  31.  *
  32.  */
  33. #define CLGEN_VERSION "1.9.9.1"
  34. #include <linux/config.h>
  35. #include <linux/module.h>
  36. #include <linux/kernel.h>
  37. #include <linux/errno.h>
  38. #include <linux/string.h>
  39. #include <linux/mm.h>
  40. #include <linux/tty.h>
  41. #include <linux/slab.h>
  42. #include <linux/delay.h>
  43. #include <linux/fb.h>
  44. #include <linux/init.h>
  45. #include <linux/selection.h>
  46. #include <asm/pgtable.h>
  47. #ifdef CONFIG_ZORRO
  48. #include <linux/zorro.h>
  49. #endif
  50. #ifdef CONFIG_PCI
  51. #include <linux/pci.h>
  52. #endif
  53. #ifdef CONFIG_AMIGA
  54. #include <asm/amigahw.h>
  55. #endif
  56. #ifdef CONFIG_ALL_PPC
  57. #include <asm/processor.h>
  58. #define isPReP (_machine == _MACH_prep)
  59. #else
  60. #define isPReP 0
  61. #endif
  62. #include <video/fbcon.h>
  63. #include <video/fbcon-mfb.h>
  64. #include <video/fbcon-cfb8.h>
  65. #include <video/fbcon-cfb16.h>
  66. #include <video/fbcon-cfb24.h>
  67. #include <video/fbcon-cfb32.h>
  68. #include "clgenfb.h"
  69. #include "vga.h"
  70. /*****************************************************************
  71.  *
  72.  * debugging and utility macros
  73.  *
  74.  */
  75. /* enable debug output? */
  76. /* #define CLGEN_DEBUG 1 */
  77. /* disable runtime assertions? */
  78. /* #define CLGEN_NDEBUG */
  79. /* debug output */
  80. #ifdef CLGEN_DEBUG
  81. #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
  82. #else
  83. #define DPRINTK(fmt, args...)
  84. #endif
  85. /* debugging assertions */
  86. #ifndef CLGEN_NDEBUG
  87. #define assert(expr) 
  88.         if(!(expr)) { 
  89.         printk( "Assertion failed! %s,%s,%s,line=%dn",
  90.         #expr,__FILE__,__FUNCTION__,__LINE__); 
  91.         }
  92. #else
  93. #define assert(expr)
  94. #endif
  95. #ifdef TRUE
  96. #undef TRUE
  97. #endif
  98. #ifdef FALSE
  99. #undef FALSE
  100. #endif
  101. #define TRUE  1
  102. #define FALSE 0
  103. #define MB_ (1024*1024)
  104. #define KB_ (1024)
  105. #define MAX_NUM_BOARDS 7
  106. /*****************************************************************
  107.  *
  108.  * chipset information
  109.  *
  110.  */
  111. /* board types */
  112. typedef enum {
  113. BT_NONE = 0,
  114. BT_SD64,
  115. BT_PICCOLO,
  116. BT_PICASSO,
  117. BT_SPECTRUM,
  118. BT_PICASSO4, /* GD5446 */
  119. BT_ALPINE, /* GD543x/4x */
  120. BT_GD5480,
  121. BT_LAGUNA, /* GD546x */
  122. } clgen_board_t;
  123. /*
  124.  * per-board-type information, used for enumerating and abstracting
  125.  * chip-specific information
  126.  * NOTE: MUST be in the same order as clgen_board_t in order to
  127.  * use direct indexing on this array
  128.  * NOTE: '__initdata' cannot be used as some of this info
  129.  * is required at runtime.  Maybe separate into an init-only and
  130.  * a run-time table?
  131.  */
  132. static const struct clgen_board_info_rec {
  133. clgen_board_t btype; /* chipset enum, not strictly necessary, as
  134.  * clgen_board_info[] is directly indexed
  135.  * by this value */
  136. char *name; /* ASCII name of chipset */
  137. long maxclock; /* maximum video clock */
  138. unsigned init_sr07 : 1; /* init SR07 during init_vgachip() */
  139. unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */
  140. unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
  141. /* initial SR07 value, then for each mode */
  142. unsigned char sr07;
  143. unsigned char sr07_1bpp;
  144. unsigned char sr07_1bpp_mux;
  145. unsigned char sr07_8bpp;
  146. unsigned char sr07_8bpp_mux;
  147. unsigned char sr1f; /* SR1F VGA initial register value */
  148. } clgen_board_info[] = {
  149. { BT_NONE, }, /* dummy record */
  150. { BT_SD64,
  151. "CL SD64",
  152. 140000, /* the SD64/P4 have a higher max. videoclock */
  153. TRUE,
  154. TRUE,
  155. TRUE,
  156. 0xF0,
  157. 0xF0,
  158. 0, /* unused, does not multiplex */
  159. 0xF1,
  160. 0, /* unused, does not multiplex */
  161. 0x20 },
  162. { BT_PICCOLO,
  163. "CL Piccolo",
  164. 90000,
  165. TRUE,
  166. TRUE,
  167. FALSE,
  168. 0x80,
  169. 0x80,
  170. 0, /* unused, does not multiplex */
  171. 0x81,
  172. 0, /* unused, does not multiplex */
  173. 0x22 },
  174. { BT_PICASSO,
  175. "CL Picasso",
  176. 90000,
  177. TRUE,
  178. TRUE,
  179. FALSE,
  180. 0x20,
  181. 0x20,
  182. 0, /* unused, does not multiplex */
  183. 0x21,
  184. 0, /* unused, does not multiplex */
  185. 0x22 },
  186. { BT_SPECTRUM,
  187. "CL Spectrum",
  188. 90000,
  189. TRUE,
  190. TRUE,
  191. FALSE,
  192. 0x80,
  193. 0x80,
  194. 0, /* unused, does not multiplex */
  195. 0x81,
  196. 0, /* unused, does not multiplex */
  197. 0x22 },
  198. { BT_PICASSO4,
  199. "CL Picasso4",
  200. 140000, /* the SD64/P4 have a higher max. videoclock */
  201. TRUE,
  202. FALSE,
  203. TRUE,
  204. 0x20,
  205. 0x20,
  206. 0, /* unused, does not multiplex */
  207. 0x21,
  208. 0, /* unused, does not multiplex */
  209. 0 },
  210. { BT_ALPINE,
  211. "CL Alpine",
  212. 110000, /* 135100 for some, 85500 for others */
  213. TRUE,
  214. TRUE,
  215. TRUE,
  216. 0xA0,
  217. 0xA1,
  218. 0xA7,
  219. 0xA1,
  220. 0xA7,
  221. 0x1C },
  222. { BT_GD5480,
  223. "CL GD5480",
  224. 90000,
  225. TRUE,
  226. TRUE,
  227. TRUE,
  228. 0x10,
  229. 0x11,
  230. 0, /* unused, does not multiplex */
  231. 0x11,
  232. 0, /* unused, does not multiplex */
  233. 0x1C },
  234. { BT_LAGUNA,
  235. "CL Laguna",
  236. 135100,
  237. FALSE,
  238. FALSE,
  239. TRUE,
  240. 0, /* unused */
  241. 0, /* unused */
  242. 0, /* unused */
  243. 0, /* unused */
  244. 0, /* unused */
  245. 0 }, /* unused */
  246. };
  247. #ifdef CONFIG_PCI
  248. /* the list of PCI devices for which we probe, and the
  249.  * order in which we do it */
  250. static const struct {
  251. clgen_board_t btype;
  252. const char *nameOverride; /* XXX unused... for now */
  253. unsigned short device;
  254. } clgen_pci_probe_list[] __initdata = {
  255. { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5436 },
  256. { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_8 },
  257. { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_4 },
  258. { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5430 }, /* GD-5440 has identical id */
  259. { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_7543 },
  260. { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_7548 },
  261. { BT_GD5480, NULL, PCI_DEVICE_ID_CIRRUS_5480 }, /* MacPicasso probably */
  262. { BT_PICASSO4, NULL, PCI_DEVICE_ID_CIRRUS_5446 }, /* Picasso 4 is a GD5446 */
  263. { BT_LAGUNA, "CL Laguna", PCI_DEVICE_ID_CIRRUS_5462 },
  264. { BT_LAGUNA, "CL Laguna 3D", PCI_DEVICE_ID_CIRRUS_5464 },
  265. { BT_LAGUNA, "CL Laguna 3DA", PCI_DEVICE_ID_CIRRUS_5465 },
  266. };
  267. #endif /* CONFIG_PCI */
  268. #ifdef CONFIG_ZORRO
  269. static const struct {
  270. clgen_board_t btype;
  271. zorro_id id, id2;
  272. unsigned long size;
  273. } clgen_zorro_probe_list[] __initdata = {
  274. { BT_SD64,
  275. ZORRO_PROD_HELFRICH_SD64_RAM,
  276. ZORRO_PROD_HELFRICH_SD64_REG,
  277. 0x400000 },
  278. { BT_PICCOLO,
  279. ZORRO_PROD_HELFRICH_PICCOLO_RAM,
  280. ZORRO_PROD_HELFRICH_PICCOLO_REG,
  281. 0x200000 },
  282. { BT_PICASSO,
  283. ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
  284. ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
  285. 0x200000 },
  286. { BT_SPECTRUM,
  287. ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
  288. ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
  289. 0x200000 },
  290. { BT_PICASSO4,
  291. ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
  292. 0,
  293. 0x400000 },
  294. };
  295. #endif /* CONFIG_ZORRO */
  296. struct clgenfb_par {
  297. struct fb_var_screeninfo var;
  298. __u32 line_length; /* in BYTES! */
  299. __u32 visual;
  300. __u32 type;
  301. long freq;
  302. long nom;
  303. long den;
  304. long div;
  305. long multiplexing;
  306. long mclk;
  307. long divMCLK;
  308. long HorizRes; /* The x resolution in pixel */
  309. long HorizTotal;
  310. long HorizDispEnd;
  311. long HorizBlankStart;
  312. long HorizBlankEnd;
  313. long HorizSyncStart;
  314. long HorizSyncEnd;
  315. long VertRes; /* the physical y resolution in scanlines */
  316. long VertTotal;
  317. long VertDispEnd;
  318. long VertSyncStart;
  319. long VertSyncEnd;
  320. long VertBlankStart;
  321. long VertBlankEnd;
  322. };
  323. #ifdef CLGEN_DEBUG
  324. typedef enum {
  325.         CRT,
  326.         SEQ
  327. } clgen_dbg_reg_class_t;
  328. #endif                          /* CLGEN_DEBUG */
  329. /* info about board */
  330. struct clgenfb_info {
  331. struct fb_info_gen gen;
  332. caddr_t fbmem;
  333. caddr_t regs;
  334. caddr_t mem;
  335. unsigned long size;
  336. clgen_board_t btype;
  337. int smallboard;
  338. unsigned char SFR; /* Shadow of special function register */
  339. unsigned long fbmem_phys;
  340. unsigned long fbregs_phys;
  341. struct clgenfb_par currentmode;
  342. struct { u8 red, green, blue, pad; } palette[256];
  343. union {
  344. #ifdef FBCON_HAS_CFB16
  345. u16 cfb16[16];
  346. #endif
  347. #ifdef FBCON_HAS_CFB24
  348. u32 cfb24[16];
  349. #endif
  350. #ifdef FBCON_HAS_CFB32
  351. u32 cfb32[16];
  352. #endif
  353. } fbcon_cmap;
  354. #ifdef CONFIG_ZORRO
  355. unsigned long board_addr,
  356.       board_size;
  357. #endif
  358. #ifdef CONFIG_PCI
  359. struct pci_dev *pdev;
  360. #endif
  361. };
  362. static struct display disp;
  363. static struct clgenfb_info boards[MAX_NUM_BOARDS]; /* the boards */
  364. static unsigned clgen_def_mode = 1;
  365. static int noaccel = 0;
  366. /*
  367.  *    Predefined Video Modes
  368.  */
  369. static const struct {
  370. const char *name;
  371. struct fb_var_screeninfo var;
  372. } clgenfb_predefined[] __initdata =
  373. {
  374. {"Autodetect", /* autodetect mode */
  375.  {0}
  376. },
  377. {"640x480", /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
  378.  {
  379.  640, 480, 640, 480, 0, 0, 8, 0,
  380.  {0, 8, 0},
  381.  {0, 8, 0},
  382.  {0, 8, 0},
  383.  {0, 0, 0},
  384.        0, 0, -1, -1, FB_ACCEL_NONE, 40000, 48, 16, 32, 8, 96, 4,
  385.      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  386.  }
  387. },
  388. {"800x600", /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
  389.  {
  390.  800, 600, 800, 600, 0, 0, 8, 0,
  391.  {0, 8, 0},
  392.  {0, 8, 0},
  393.  {0, 8, 0},
  394.  {0, 0, 0},
  395.        0, 0, -1, -1, FB_ACCEL_NONE, 20000, 128, 16, 24, 2, 96, 6,
  396.      0, FB_VMODE_NONINTERLACED
  397.  }
  398. },
  399. /*
  400.    Modeline from XF86Config:
  401.    Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
  402.  */
  403. {"1024x768", /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
  404. {
  405. 1024, 768, 1024, 768, 0, 0, 8, 0,
  406. {0, 8, 0},
  407. {0, 8, 0},
  408. {0, 8, 0},
  409. {0, 0, 0},
  410.       0, 0, -1, -1, FB_ACCEL_NONE, 12500, 144, 32, 30, 2, 192, 6,
  411.      0, FB_VMODE_NONINTERLACED
  412. }
  413. }
  414. };
  415. #define NUM_TOTAL_MODES    ARRAY_SIZE(clgenfb_predefined)
  416. static struct fb_var_screeninfo clgenfb_default;
  417. /*
  418.  *    Frame Buffer Name
  419.  */
  420. static const char *clgenfb_name = "CLgen";
  421. /****************************************************************************/
  422. /**** BEGIN PROTOTYPES ******************************************************/
  423. /*--- Interface used by the world ------------------------------------------*/
  424. int clgenfb_init (void);
  425. int clgenfb_setup (char *options);
  426. static int clgenfb_open (struct fb_info *info, int user);
  427. static int clgenfb_release (struct fb_info *info, int user);
  428. /* function table of the above functions */
  429. static struct fb_ops clgenfb_ops = {
  430. owner: THIS_MODULE,
  431. fb_open: clgenfb_open,
  432. fb_release: clgenfb_release,
  433. fb_get_fix: fbgen_get_fix,
  434. fb_get_var: fbgen_get_var,
  435. fb_set_var: fbgen_set_var,
  436. fb_get_cmap: fbgen_get_cmap,
  437. fb_set_cmap: fbgen_set_cmap,
  438. fb_pan_display: fbgen_pan_display,
  439. };
  440. /*--- Hardware Specific Routines -------------------------------------------*/
  441. static void clgen_detect (void);
  442. static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
  443.      struct fb_info_gen *info);
  444. static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
  445.      struct fb_info_gen *info);
  446. static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
  447.      struct fb_info_gen *info);
  448. static void clgen_get_par (void *par, struct fb_info_gen *info);
  449. static void clgen_set_par (const void *par, struct fb_info_gen *info);
  450. static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
  451.     unsigned *blue, unsigned *transp,
  452.     struct fb_info *info);
  453. static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
  454.     unsigned blue, unsigned transp,
  455.     struct fb_info *info);
  456. static int clgen_pan_display (const struct fb_var_screeninfo *var,
  457.       struct fb_info_gen *info);
  458. static int clgen_blank (int blank_mode, struct fb_info_gen *info);
  459. static void clgen_set_disp (const void *par, struct display *disp,
  460.     struct fb_info_gen *info);
  461. /* function table of the above functions */
  462. static struct fbgen_hwswitch clgen_hwswitch =
  463. {
  464. clgen_detect,
  465. clgen_encode_fix,
  466. clgen_decode_var,
  467. clgen_encode_var,
  468. clgen_get_par,
  469. clgen_set_par,
  470. clgen_getcolreg,
  471. clgen_setcolreg,
  472. clgen_pan_display,
  473. clgen_blank,
  474. clgen_set_disp
  475. };
  476. /* Text console acceleration */
  477. #ifdef FBCON_HAS_CFB8
  478. static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
  479. int dy, int dx, int height, int width);
  480. static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
  481. int sy, int sx, int height, int width);
  482. static struct display_switch fbcon_clgen_8 = {
  483. setup: fbcon_cfb8_setup,
  484. bmove: fbcon_clgen8_bmove,
  485. clear: fbcon_clgen8_clear,
  486. putc: fbcon_cfb8_putc,
  487. putcs: fbcon_cfb8_putcs,
  488. revc: fbcon_cfb8_revc,
  489. clear_margins: fbcon_cfb8_clear_margins,
  490. fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
  491. };
  492. #endif
  493. #ifdef FBCON_HAS_CFB16
  494. static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
  495.  int dy, int dx, int height, int width);
  496. static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
  497.  int sy, int sx, int height, int width);
  498. static struct display_switch fbcon_clgen_16 = {
  499. setup: fbcon_cfb16_setup,
  500. bmove: fbcon_clgen16_bmove,
  501. clear: fbcon_clgen16_clear,
  502. putc: fbcon_cfb16_putc,
  503. putcs: fbcon_cfb16_putcs,
  504. revc: fbcon_cfb16_revc,
  505. clear_margins: fbcon_cfb16_clear_margins,
  506. fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
  507. };
  508. #endif
  509. #ifdef FBCON_HAS_CFB32
  510. static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
  511.  int dy, int dx, int height, int width);
  512. static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
  513.  int sy, int sx, int height, int width);
  514. static struct display_switch fbcon_clgen_32 = {
  515. setup: fbcon_cfb32_setup,
  516. bmove: fbcon_clgen32_bmove,
  517. clear: fbcon_clgen32_clear,
  518. putc: fbcon_cfb32_putc,
  519. putcs: fbcon_cfb32_putcs,
  520. revc: fbcon_cfb32_revc,
  521. clear_margins: fbcon_cfb32_clear_margins,
  522. fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
  523. };
  524. #endif
  525. /*--- Internal routines ----------------------------------------------------*/
  526. static void init_vgachip (struct clgenfb_info *fb_info);
  527. static void switch_monitor (struct clgenfb_info *fb_info, int on);
  528. static void WGen (const struct clgenfb_info *fb_info,
  529.   int regnum, unsigned char val);
  530. static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum);
  531. static void AttrOn (const struct clgenfb_info *fb_info);
  532. static void WHDR (const struct clgenfb_info *fb_info, unsigned char val);
  533. static void WSFR (struct clgenfb_info *fb_info, unsigned char val);
  534. static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val);
  535. static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
  536.    unsigned char green,
  537.    unsigned char blue);
  538. #if 0
  539. static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
  540.    unsigned char *green,
  541.    unsigned char *blue);
  542. #endif
  543. static void clgen_WaitBLT (caddr_t regbase);
  544. static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury,
  545.   u_short destx, u_short desty,
  546.   u_short width, u_short height,
  547.   u_short line_length);
  548. static void clgen_RectFill (struct clgenfb_info *fb_info, u_short x, u_short y,
  549.     u_short width, u_short height,
  550.     u_char color, u_short line_length);
  551. static void bestclock (long freq, long *best,
  552.        long *nom, long *den,
  553.        long *div, long maxfreq);
  554. #ifdef CLGEN_DEBUG
  555. static void clgen_dump (void);
  556. static void clgen_dbg_reg_dump (caddr_t regbase);
  557. static void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...);
  558. static void clgen_dbg_print_byte (const char *name, unsigned char val);
  559. #endif /* CLGEN_DEBUG */
  560. /*** END   PROTOTYPES ********************************************************/
  561. /*****************************************************************************/
  562. /*** BEGIN Interface Used by the World ***************************************/
  563. static int opencount = 0;
  564. /*--- Open /dev/fbx ---------------------------------------------------------*/
  565. static int clgenfb_open (struct fb_info *info, int user)
  566. {
  567. if (opencount++ == 0)
  568. switch_monitor ((struct clgenfb_info *) info, 1);
  569. return 0;
  570. }
  571. /*--- Close /dev/fbx --------------------------------------------------------*/
  572. static int clgenfb_release (struct fb_info *info, int user)
  573. {
  574. if (--opencount == 0)
  575. switch_monitor ((struct clgenfb_info *) info, 0);
  576. return 0;
  577. }
  578. /**** END   Interface used by the World *************************************/
  579. /****************************************************************************/
  580. /**** BEGIN Hardware specific Routines **************************************/
  581. static void clgen_detect (void)
  582. {
  583. DPRINTK ("ENTERn");
  584. DPRINTK ("EXITn");
  585. }
  586. static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
  587.      struct fb_info_gen *info)
  588. {
  589. struct clgenfb_par *_par = (struct clgenfb_par *) par;
  590. struct clgenfb_info *_info = (struct clgenfb_info *) info;
  591. DPRINTK ("ENTERn");
  592. memset (fix, 0, sizeof (struct fb_fix_screeninfo));
  593. strcpy (fix->id, clgenfb_name);
  594. if (_info->btype == BT_GD5480) {
  595. /* Select proper byte-swapping aperture */
  596. switch (_par->var.bits_per_pixel) {
  597. case 1:
  598. case 8:
  599. fix->smem_start = _info->fbmem_phys;
  600. break;
  601. case 16:
  602. fix->smem_start = _info->fbmem_phys + 1 * MB_;
  603. break;
  604. case 24:
  605. case 32:
  606. fix->smem_start = _info->fbmem_phys + 2 * MB_;
  607. break;
  608. }
  609. } else {
  610. fix->smem_start = _info->fbmem_phys;
  611. }
  612. /* monochrome: only 1 memory plane */
  613. /* 8 bit and above: Use whole memory area */
  614. fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4
  615.     : _info->size;
  616. fix->type = _par->type;
  617. fix->type_aux = 0;
  618. fix->visual = _par->visual;
  619. fix->xpanstep = 1;
  620. fix->ypanstep = 1;
  621. fix->ywrapstep = 0;
  622. fix->line_length = _par->line_length;
  623. /* FIXME: map region at 0xB8000 if available, fill in here */
  624. fix->mmio_start = 0;
  625. fix->mmio_len = 0;
  626. fix->accel = FB_ACCEL_NONE;
  627. DPRINTK ("EXITn");
  628. return 0;
  629. }
  630. /* Get a good MCLK value */
  631. static long clgen_get_mclk (long freq, int bpp, long *div)
  632. {
  633. long mclk;
  634. assert (div != NULL);
  635. /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
  636.  * Assume a 64-bit data path for now.  The formula is:
  637.  * ((B * PCLK * 2)/W) * 1.2
  638.  * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
  639. mclk = ((bpp / 8) * freq * 2) / 4;
  640. mclk = (mclk * 12) / 10;
  641. if (mclk < 50000)
  642. mclk = 50000;
  643. DPRINTK ("Use MCLK of %ld kHzn", mclk);
  644. /* Calculate value for SR1F.  Multiply by 2 so we can round up. */
  645. mclk = ((mclk * 16) / 14318);
  646. mclk = (mclk + 1) / 2;
  647. DPRINTK ("Set SR1F[5:0] to 0x%lxn", mclk);
  648. /* Determine if we should use MCLK instead of VCLK, and if so, what we
  649.    * should divide it by to get VCLK */
  650. switch (freq) {
  651. case 24751 ... 25249:
  652. *div = 2;
  653. DPRINTK ("Using VCLK = MCLK/2n");
  654. break;
  655. case 49501 ... 50499:
  656. *div = 1;
  657. DPRINTK ("Using VCLK = MCLKn");
  658. break;
  659. default:
  660. *div = 0;
  661. break;
  662. }
  663. return mclk;
  664. }
  665. static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
  666.      struct fb_info_gen *info)
  667. {
  668. long freq;
  669. long maxclock;
  670. int xres, hfront, hsync, hback;
  671. int yres, vfront, vsync, vback;
  672. int nom, den; /* translyting from pixels->bytes */
  673. int i;
  674. static struct {
  675. int xres, yres;
  676. } modes[] = { {
  677. 1600, 1280
  678. }, {
  679. 1280, 1024
  680. }, {
  681. 1024, 768
  682. },
  683. {
  684. 800, 600
  685. }, {
  686. 640, 480
  687. }, {
  688. -1, -1
  689. }
  690. };
  691. struct clgenfb_par *_par = (struct clgenfb_par *) par;
  692. struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
  693. assert (var != NULL);
  694. assert (par != NULL);
  695. assert (info != NULL);
  696. DPRINTK ("ENTERn");
  697. DPRINTK ("Requested: %dx%dx%dn", var->xres, var->yres, var->bits_per_pixel);
  698. DPRINTK ("  virtual: %dx%dn", var->xres_virtual, var->yres_virtual);
  699. DPRINTK ("   offset: (%d,%d)n", var->xoffset, var->yoffset);
  700. DPRINTK ("grayscale: %dn", var->grayscale);
  701. memset (par, 0, sizeof (struct clgenfb_par));
  702. _par->var = *var;
  703. switch (var->bits_per_pixel) {
  704. case 1:
  705. nom = 4;
  706. den = 8;
  707. break; /* 8 pixel per byte, only 1/4th of mem usable */
  708. case 2 ... 8:
  709. _par->var.bits_per_pixel = 8;
  710. nom = 1;
  711. den = 1;
  712. break; /* 1 pixel == 1 byte */
  713. case 9 ... 16:
  714. _par->var.bits_per_pixel = 16;
  715. nom = 2;
  716. den = 1;
  717. break; /* 2 bytes per pixel */
  718. case 17 ... 24:
  719. _par->var.bits_per_pixel = 24;
  720. nom = 3;
  721. den = 1;
  722. break; /* 3 bytes per pixel */
  723. case 25 ... 32:
  724. _par->var.bits_per_pixel = 32;
  725. nom = 4;
  726. den = 1;
  727. break; /* 4 bytes per pixel */
  728. default:
  729. printk ("clgen: mode %dx%dx%d rejected...color depth not supported.n",
  730. var->xres, var->yres, var->bits_per_pixel);
  731. DPRINTK ("EXIT - EINVAL errorn");
  732. return -EINVAL;
  733. }
  734. if (_par->var.xres * nom / den * _par->var.yres > fb_info->size) {
  735. printk ("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!n",
  736. var->xres, var->yres, var->bits_per_pixel);
  737. DPRINTK ("EXIT - EINVAL errorn");
  738. return -EINVAL;
  739. }
  740. /* use highest possible virtual resolution */
  741. if (_par->var.xres_virtual == -1 &&
  742.     _par->var.yres_virtual == -1) {
  743. printk ("clgen: using maximum available virtual resolutionn");
  744. for (i = 0; modes[i].xres != -1; i++) {
  745. if (modes[i].xres * nom / den * modes[i].yres < fb_info->size / 2)
  746. break;
  747. }
  748. if (modes[i].xres == -1) {
  749. printk ("clgen: could not find a virtual resolution that fits into video memory!!n");
  750. DPRINTK ("EXIT - EINVAL errorn");
  751. return -EINVAL;
  752. }
  753. _par->var.xres_virtual = modes[i].xres;
  754. _par->var.yres_virtual = modes[i].yres;
  755. printk ("clgen: virtual resolution set to maximum of %dx%dn",
  756. _par->var.xres_virtual, _par->var.yres_virtual);
  757. } else if (_par->var.xres_virtual == -1) {
  758. /* FIXME: maximize X virtual resolution only */
  759. } else if (_par->var.yres_virtual == -1) {
  760. /* FIXME: maximize Y virtual resolution only */
  761. }
  762. if (_par->var.xoffset < 0)
  763. _par->var.xoffset = 0;
  764. if (_par->var.yoffset < 0)
  765. _par->var.yoffset = 0;
  766. /* truncate xoffset and yoffset to maximum if too high */
  767. if (_par->var.xoffset > _par->var.xres_virtual - _par->var.xres)
  768. _par->var.xoffset = _par->var.xres_virtual - _par->var.xres - 1;
  769. if (_par->var.yoffset > _par->var.yres_virtual - _par->var.yres)
  770. _par->var.yoffset = _par->var.yres_virtual - _par->var.yres - 1;
  771. switch (_par->var.bits_per_pixel) {
  772. case 1:
  773. _par->line_length = _par->var.xres_virtual / 8;
  774. _par->visual = FB_VISUAL_MONO10;
  775. break;
  776. case 8:
  777. _par->line_length = _par->var.xres_virtual;
  778. _par->visual = FB_VISUAL_PSEUDOCOLOR;
  779. _par->var.red.offset = 0;
  780. _par->var.red.length = 6;
  781. _par->var.green.offset = 0;
  782. _par->var.green.length = 6;
  783. _par->var.blue.offset = 0;
  784. _par->var.blue.length = 6;
  785. break;
  786. case 16:
  787. _par->line_length = _par->var.xres_virtual * 2;
  788. _par->visual = FB_VISUAL_DIRECTCOLOR;
  789. if(isPReP) {
  790. _par->var.red.offset = 2;
  791. _par->var.green.offset = -3;
  792. _par->var.blue.offset = 8;
  793. } else {
  794. _par->var.red.offset = 10;
  795. _par->var.green.offset = 5;
  796. _par->var.blue.offset = 0;
  797. }
  798. _par->var.red.length = 5;
  799. _par->var.green.length = 5;
  800. _par->var.blue.length = 5;
  801. break;
  802. case 24:
  803. _par->line_length = _par->var.xres_virtual * 3;
  804. _par->visual = FB_VISUAL_DIRECTCOLOR;
  805. if(isPReP) {
  806. _par->var.red.offset = 8;
  807. _par->var.green.offset = 16;
  808. _par->var.blue.offset = 24;
  809. } else {
  810. _par->var.red.offset = 16;
  811. _par->var.green.offset = 8;
  812. _par->var.blue.offset = 0;
  813. }
  814. _par->var.red.length = 8;
  815. _par->var.green.length = 8;
  816. _par->var.blue.length = 8;
  817. break;
  818. case 32:
  819. _par->line_length = _par->var.xres_virtual * 4;
  820. _par->visual = FB_VISUAL_DIRECTCOLOR;
  821. if(isPReP) {
  822. _par->var.red.offset = 8;
  823. _par->var.green.offset = 16;
  824. _par->var.blue.offset = 24;
  825. } else {
  826. _par->var.red.offset = 16;
  827. _par->var.green.offset = 8;
  828. _par->var.blue.offset = 0;
  829. }
  830. _par->var.red.length = 8;
  831. _par->var.green.length = 8;
  832. _par->var.blue.length = 8;
  833. break;
  834. default:
  835. DPRINTK("Unsupported bpp size: %dn", _par->var.bits_per_pixel);
  836. assert (FALSE);
  837. /* should never occur */
  838. break;
  839. }
  840. _par->var.red.msb_right =
  841.     _par->var.green.msb_right =
  842.     _par->var.blue.msb_right =
  843.     _par->var.transp.offset =
  844.     _par->var.transp.length =
  845.     _par->var.transp.msb_right = 0;
  846. _par->type = FB_TYPE_PACKED_PIXELS;
  847. /* convert from ps to kHz */
  848. freq = 1000000000 / var->pixclock;
  849. DPRINTK ("desired pixclock: %ld kHzn", freq);
  850. maxclock = clgen_board_info[fb_info->btype].maxclock;
  851. _par->multiplexing = 0;
  852. /* If the frequency is greater than we can support, we might be able
  853.  * to use multiplexing for the video mode */
  854. if (freq > maxclock) {
  855. switch (fb_info->btype) {
  856. case BT_ALPINE:
  857. case BT_GD5480:
  858. _par->multiplexing = 1;
  859. break;
  860. default:
  861. printk (KERN_WARNING "clgen: ERROR: Frequency greater than maxclock (%ld kHz)n", maxclock);
  862. DPRINTK ("EXIT - return -EINVALn");
  863. return -EINVAL;
  864. }
  865. }
  866. #if 0
  867. /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
  868.  * the VCLK is double the pixel clock. */
  869. switch (var->bits_per_pixel) {
  870. case 16:
  871. case 32:
  872. if (_par->HorizRes <= 800)
  873. freq /= 2; /* Xbh has this type of clock for 32-bit */
  874. break;
  875. }
  876. #endif
  877. bestclock (freq, &_par->freq, &_par->nom, &_par->den, &_par->div,
  878.    maxclock);
  879. _par->mclk = clgen_get_mclk (freq, _par->var.bits_per_pixel, &_par->divMCLK);
  880. xres = _par->var.xres;
  881. hfront = _par->var.right_margin;
  882. hsync = _par->var.hsync_len;
  883. hback = _par->var.left_margin;
  884. yres = _par->var.yres;
  885. vfront = _par->var.lower_margin;
  886. vsync = _par->var.vsync_len;
  887. vback = _par->var.upper_margin;
  888. if (_par->var.vmode & FB_VMODE_DOUBLE) {
  889. yres *= 2;
  890. vfront *= 2;
  891. vsync *= 2;
  892. vback *= 2;
  893. } else if (_par->var.vmode & FB_VMODE_INTERLACED) {
  894. yres = (yres + 1) / 2;
  895. vfront = (vfront + 1) / 2;
  896. vsync = (vsync + 1) / 2;
  897. vback = (vback + 1) / 2;
  898. }
  899. _par->HorizRes = xres;
  900. _par->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
  901. _par->HorizDispEnd = xres / 8 - 1;
  902. _par->HorizBlankStart = xres / 8;
  903. _par->HorizBlankEnd = _par->HorizTotal + 5; /* does not count with "-5" */
  904. _par->HorizSyncStart = (xres + hfront) / 8 + 1;
  905. _par->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
  906. _par->VertRes = yres;
  907. _par->VertTotal = yres + vfront + vsync + vback - 2;
  908. _par->VertDispEnd = yres - 1;
  909. _par->VertBlankStart = yres;
  910. _par->VertBlankEnd = _par->VertTotal;
  911. _par->VertSyncStart = yres + vfront - 1;
  912. _par->VertSyncEnd = yres + vfront + vsync - 1;
  913. if (_par->VertRes >= 1024) {
  914. _par->VertTotal /= 2;
  915. _par->VertSyncStart /= 2;
  916. _par->VertSyncEnd /= 2;
  917. _par->VertDispEnd /= 2;
  918. }
  919. if (_par->multiplexing) {
  920. _par->HorizTotal /= 2;
  921. _par->HorizSyncStart /= 2;
  922. _par->HorizSyncEnd /= 2;
  923. _par->HorizDispEnd /= 2;
  924. }
  925. if (_par->VertRes >= 1280) {
  926. printk (KERN_WARNING "clgen: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)n");
  927. DPRINTK ("EXIT - EINVAL errorn");
  928. return -EINVAL;
  929. }
  930. DPRINTK ("EXITn");
  931. return 0;
  932. }
  933. static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
  934.      struct fb_info_gen *info)
  935. {
  936. DPRINTK ("ENTERn");
  937. *var = ((struct clgenfb_par *) par)->var;
  938. DPRINTK ("EXITn");
  939. return 0;
  940. }
  941. /* get current video mode */
  942. static void clgen_get_par (void *par, struct fb_info_gen *info)
  943. {
  944. struct clgenfb_par *_par = (struct clgenfb_par *) par;
  945. struct clgenfb_info *_info = (struct clgenfb_info *) info;
  946. DPRINTK ("ENTERn");
  947. *_par = _info->currentmode;
  948. DPRINTK ("EXITn");
  949. }
  950. static void clgen_set_mclk (const struct clgenfb_info *fb_info, int val, int div)
  951. {
  952. assert (fb_info != NULL);
  953. if (div == 2) {
  954. /* VCLK = MCLK/2 */
  955. unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
  956. vga_wseq (fb_info->regs, CL_SEQR1E, old | 0x1);
  957. vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
  958. } else if (div == 1) {
  959. /* VCLK = MCLK */
  960. unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
  961. vga_wseq (fb_info->regs, CL_SEQR1E, old & ~0x1);
  962. vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
  963. } else {
  964. vga_wseq (fb_info->regs, CL_SEQR1F, val & 0x3f);
  965. }
  966. }
  967. /*************************************************************************
  968. clgen_set_par()
  969. actually writes the values for a new video mode into the hardware,
  970. **************************************************************************/
  971. static void clgen_set_par (const void *par, struct fb_info_gen *info)
  972. {
  973. unsigned char tmp;
  974. int offset = 0;
  975. struct clgenfb_par *_par = (struct clgenfb_par *) par;
  976. struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
  977. const struct clgen_board_info_rec *bi;
  978. DPRINTK ("ENTERn");
  979. DPRINTK ("Requested mode: %dx%dx%dn",
  980.        _par->var.xres, _par->var.yres, _par->var.bits_per_pixel);
  981. DPRINTK ("pixclock: %dn", _par->var.pixclock);
  982. bi = &clgen_board_info[fb_info->btype];
  983. /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
  984. vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
  985. /* if debugging is enabled, all parameters get output before writing */
  986. DPRINTK ("CRT0: %ldn", _par->HorizTotal);
  987. vga_wcrt (fb_info->regs, VGA_CRTC_H_TOTAL, _par->HorizTotal);
  988. DPRINTK ("CRT1: %ldn", _par->HorizDispEnd);
  989. vga_wcrt (fb_info->regs, VGA_CRTC_H_DISP, _par->HorizDispEnd);
  990. DPRINTK ("CRT2: %ldn", _par->HorizBlankStart);
  991. vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_START, _par->HorizBlankStart);
  992. DPRINTK ("CRT3: 128+%ldn", _par->HorizBlankEnd % 32); /*  + 128: Compatible read */
  993. vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_END, 128 + (_par->HorizBlankEnd % 32));
  994. DPRINTK ("CRT4: %ldn", _par->HorizSyncStart);
  995. vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_START, _par->HorizSyncStart);
  996. tmp = _par->HorizSyncEnd % 32;
  997. if (_par->HorizBlankEnd & 32)
  998. tmp += 128;
  999. DPRINTK ("CRT5: %dn", tmp);
  1000. vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_END, tmp);
  1001. DPRINTK ("CRT6: %ldn", _par->VertTotal & 0xff);
  1002. vga_wcrt (fb_info->regs, VGA_CRTC_V_TOTAL, (_par->VertTotal & 0xff));
  1003. tmp = 16; /* LineCompare bit #9 */
  1004. if (_par->VertTotal & 256)
  1005. tmp |= 1;
  1006. if (_par->VertDispEnd & 256)
  1007. tmp |= 2;
  1008. if (_par->VertSyncStart & 256)
  1009. tmp |= 4;
  1010. if (_par->VertBlankStart & 256)
  1011. tmp |= 8;
  1012. if (_par->VertTotal & 512)
  1013. tmp |= 32;
  1014. if (_par->VertDispEnd & 512)
  1015. tmp |= 64;
  1016. if (_par->VertSyncStart & 512)
  1017. tmp |= 128;
  1018. DPRINTK ("CRT7: %dn", tmp);
  1019. vga_wcrt (fb_info->regs, VGA_CRTC_OVERFLOW, tmp);
  1020. tmp = 0x40; /* LineCompare bit #8 */
  1021. if (_par->VertBlankStart & 512)
  1022. tmp |= 0x20;
  1023. if (_par->var.vmode & FB_VMODE_DOUBLE)
  1024. tmp |= 0x80;
  1025. DPRINTK ("CRT9: %dn", tmp);
  1026. vga_wcrt (fb_info->regs, VGA_CRTC_MAX_SCAN, tmp);
  1027. DPRINTK ("CRT10: %ldn", _par->VertSyncStart & 0xff);
  1028. vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_START, (_par->VertSyncStart & 0xff));
  1029. DPRINTK ("CRT11: 64+32+%ldn", _par->VertSyncEnd % 16);
  1030. vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, (_par->VertSyncEnd % 16 + 64 + 32));
  1031. DPRINTK ("CRT12: %ldn", _par->VertDispEnd & 0xff);
  1032. vga_wcrt (fb_info->regs, VGA_CRTC_V_DISP_END, (_par->VertDispEnd & 0xff));
  1033. DPRINTK ("CRT15: %ldn", _par->VertBlankStart & 0xff);
  1034. vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_START, (_par->VertBlankStart & 0xff));
  1035. DPRINTK ("CRT16: %ldn", _par->VertBlankEnd & 0xff);
  1036. vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_END, (_par->VertBlankEnd & 0xff));
  1037. DPRINTK ("CRT18: 0xffn");
  1038. vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0xff);
  1039. tmp = 0;
  1040. if (_par->var.vmode & FB_VMODE_INTERLACED)
  1041. tmp |= 1;
  1042. if (_par->HorizBlankEnd & 64)
  1043. tmp |= 16;
  1044. if (_par->HorizBlankEnd & 128)
  1045. tmp |= 32;
  1046. if (_par->VertBlankEnd & 256)
  1047. tmp |= 64;
  1048. if (_par->VertBlankEnd & 512)
  1049. tmp |= 128;
  1050. DPRINTK ("CRT1a: %dn", tmp);
  1051. vga_wcrt (fb_info->regs, CL_CRT1A, tmp);
  1052. /* set VCLK0 */
  1053. /* hardware RefClock: 14.31818 MHz */
  1054. /* formula: VClk = (OSC * N) / (D * (1+P)) */
  1055. /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
  1056. vga_wseq (fb_info->regs, CL_SEQRB, _par->nom);
  1057. tmp = _par->den << 1;
  1058. if (_par->div != 0)
  1059. tmp |= 1;
  1060. if ((fb_info->btype == BT_SD64) ||
  1061.     (fb_info->btype == BT_ALPINE) ||
  1062.     (fb_info->btype == BT_GD5480))
  1063. tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
  1064. DPRINTK ("CL_SEQR1B: %ldn", (long) tmp);
  1065. vga_wseq (fb_info->regs, CL_SEQR1B, tmp);
  1066. if (_par->VertRes >= 1024)
  1067. /* 1280x1024 */
  1068. vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc7);
  1069. else
  1070. /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
  1071.  * address wrap, no compat. */
  1072. vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3);
  1073. /* HAEH?        vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20);  * previously: 0x00  unlock VGA_CRTC_H_TOTAL..CRT7 */
  1074. /* don't know if it would hurt to also program this if no interlaced */
  1075. /* mode is used, but I feel better this way.. :-) */
  1076. if (_par->var.vmode & FB_VMODE_INTERLACED)
  1077. vga_wcrt (fb_info->regs, VGA_CRTC_REGS, _par->HorizTotal / 2);
  1078. else
  1079. vga_wcrt (fb_info->regs, VGA_CRTC_REGS, 0x00); /* interlace control */
  1080. vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0);
  1081. /* adjust horizontal/vertical sync type (low/high) */
  1082. tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */
  1083. if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT)
  1084. tmp |= 0x40;
  1085. if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT)
  1086. tmp |= 0x80;
  1087. WGen (fb_info, VGA_MIS_W, tmp);
  1088. vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0); /* Screen A Preset Row-Scan register */
  1089. vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0); /* text cursor on and start line */
  1090. vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 31); /* text cursor end line */
  1091. /******************************************************
  1092.  *
  1093.  * 1 bpp
  1094.  *
  1095.  */
  1096. /* programming for different color depths */
  1097. if (_par->var.bits_per_pixel == 1) {
  1098. DPRINTK ("clgen: preparing for 1 bit deep displayn");
  1099. vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0); /* mode register */
  1100. /* SR07 */
  1101. switch (fb_info->btype) {
  1102. case BT_SD64:
  1103. case BT_PICCOLO:
  1104. case BT_PICASSO:
  1105. case BT_SPECTRUM:
  1106. case BT_PICASSO4:
  1107. case BT_ALPINE:
  1108. case BT_GD5480:
  1109. DPRINTK (" (for GD54xx)n");
  1110. vga_wseq (fb_info->regs, CL_SEQR7,
  1111.   _par->multiplexing ?
  1112.    bi->sr07_1bpp_mux : bi->sr07_1bpp);
  1113. break;
  1114. case BT_LAGUNA:
  1115. DPRINTK (" (for GD546x)n");
  1116. vga_wseq (fb_info->regs, CL_SEQR7,
  1117. vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
  1118. break;
  1119. default:
  1120. printk (KERN_WARNING "clgen: unknown Boardn");
  1121. break;
  1122. }
  1123. /* Extended Sequencer Mode */
  1124. switch (fb_info->btype) {
  1125. case BT_SD64:
  1126. /* setting the SEQRF on SD64 is not necessary (only during init) */
  1127. DPRINTK ("(for SD64)n");
  1128. vga_wseq (fb_info->regs, CL_SEQR1F, 0x1a); /*  MCLK select */
  1129. break;
  1130. case BT_PICCOLO:
  1131. DPRINTK ("(for Piccolo)n");
  1132. /* ### ueberall 0x22? */
  1133. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
  1134. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
  1135. break;
  1136. case BT_PICASSO:
  1137. DPRINTK ("(for Picasso)n");
  1138. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 22 MCLK select */
  1139. vga_wseq (fb_info->regs, CL_SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */
  1140. break;
  1141. case BT_SPECTRUM:
  1142. DPRINTK ("(for Spectrum)n");
  1143. /* ### ueberall 0x22? */
  1144. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */
  1145. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */
  1146. break;
  1147. case BT_PICASSO4:
  1148. case BT_ALPINE:
  1149. case BT_GD5480:
  1150. case BT_LAGUNA:
  1151. DPRINTK (" (for GD54xx)n");
  1152. /* do nothing */
  1153. break;
  1154. default:
  1155. printk (KERN_WARNING "clgen: unknown Boardn");
  1156. break;
  1157. }
  1158. WGen (fb_info, VGA_PEL_MSK, 0x01); /* pixel mask: pass-through for first plane */
  1159. if (_par->multiplexing)
  1160. WHDR (fb_info, 0x4a); /* hidden dac reg: 1280x1024 */
  1161. else
  1162. WHDR (fb_info, 0); /* hidden dac: nothing */
  1163. vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x06); /* memory mode: odd/even, ext. memory */
  1164. vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0x01); /* plane mask: only write to first plane */
  1165. offset = _par->var.xres_virtual / 16;
  1166. }
  1167. /******************************************************
  1168.  *
  1169.  * 8 bpp
  1170.  *
  1171.  */
  1172. else if (_par->var.bits_per_pixel == 8) {
  1173. DPRINTK ("clgen: preparing for 8 bit deep displayn");
  1174. switch (fb_info->btype) {
  1175. case BT_SD64:
  1176. case BT_PICCOLO:
  1177. case BT_PICASSO:
  1178. case BT_SPECTRUM:
  1179. case BT_PICASSO4:
  1180. case BT_ALPINE:
  1181. case BT_GD5480:
  1182. DPRINTK (" (for GD54xx)n");
  1183. vga_wseq (fb_info->regs, CL_SEQR7,
  1184.   _par->multiplexing ?
  1185.    bi->sr07_8bpp_mux : bi->sr07_8bpp);
  1186. break;
  1187. case BT_LAGUNA:
  1188. DPRINTK (" (for GD546x)n");
  1189. vga_wseq (fb_info->regs, CL_SEQR7,
  1190. vga_rseq (fb_info->regs, CL_SEQR7) | 0x01);
  1191. break;
  1192. default:
  1193. printk (KERN_WARNING "clgen: unknown Boardn");
  1194. break;
  1195. }
  1196. switch (fb_info->btype) {
  1197. case BT_SD64:
  1198. vga_wseq (fb_info->regs, CL_SEQR1F, 0x1d); /* MCLK select */
  1199. break;
  1200. case BT_PICCOLO:
  1201. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
  1202. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
  1203. break;
  1204. case BT_PICASSO:
  1205. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
  1206. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
  1207. break;
  1208. case BT_SPECTRUM:
  1209. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */
  1210. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
  1211. break;
  1212. case BT_PICASSO4:
  1213. #ifdef CONFIG_ZORRO
  1214. vga_wseq (fb_info->regs, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */
  1215. #endif
  1216. /*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
  1217. break;
  1218. case BT_ALPINE:
  1219. DPRINTK (" (for GD543x)n");
  1220. clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
  1221. /* We already set SRF and SR1F */
  1222. break;
  1223. case BT_GD5480:
  1224. case BT_LAGUNA:
  1225. DPRINTK (" (for GD54xx)n");
  1226. /* do nothing */
  1227. break;
  1228. default:
  1229. printk (KERN_WARNING "clgen: unknown Boardn");
  1230. break;
  1231. }
  1232. vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
  1233. WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
  1234. if (_par->multiplexing)
  1235. WHDR (fb_info, 0x4a); /* hidden dac reg: 1280x1024 */
  1236. else
  1237. WHDR (fb_info, 0); /* hidden dac: nothing */
  1238. vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
  1239. vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
  1240. offset = _par->var.xres_virtual / 8;
  1241. }
  1242. /******************************************************
  1243.  *
  1244.  * 16 bpp
  1245.  *
  1246.  */
  1247. else if (_par->var.bits_per_pixel == 16) {
  1248. DPRINTK ("clgen: preparing for 16 bit deep displayn");
  1249. switch (fb_info->btype) {
  1250. case BT_SD64:
  1251. vga_wseq (fb_info->regs, CL_SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */
  1252. vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e); /* MCLK select */
  1253. break;
  1254. case BT_PICCOLO:
  1255. vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
  1256. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
  1257. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
  1258. break;
  1259. case BT_PICASSO:
  1260. vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
  1261. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
  1262. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
  1263. break;
  1264. case BT_SPECTRUM:
  1265. vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
  1266. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
  1267. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
  1268. break;
  1269. case BT_PICASSO4:
  1270. vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
  1271. /*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c);  */
  1272. break;
  1273. case BT_ALPINE:
  1274. DPRINTK (" (for GD543x)n");
  1275. if (_par->HorizRes >= 1024)
  1276. vga_wseq (fb_info->regs, CL_SEQR7, 0xa7);
  1277. else
  1278. vga_wseq (fb_info->regs, CL_SEQR7, 0xa3);
  1279. clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
  1280. break;
  1281. case BT_GD5480:
  1282. DPRINTK (" (for GD5480)n");
  1283. vga_wseq (fb_info->regs, CL_SEQR7, 0x17);
  1284. /* We already set SRF and SR1F */
  1285. break;
  1286. case BT_LAGUNA:
  1287. DPRINTK (" (for GD546x)n");
  1288. vga_wseq (fb_info->regs, CL_SEQR7,
  1289. vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
  1290. break;
  1291. default:
  1292. printk (KERN_WARNING "CLGEN: unknown Boardn");
  1293. break;
  1294. }
  1295. vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
  1296. WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
  1297. #ifdef CONFIG_PCI
  1298. WHDR (fb_info, 0xc0); /* Copy Xbh */
  1299. #elif defined(CONFIG_ZORRO)
  1300. /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
  1301. WHDR (fb_info, 0xa0); /* hidden dac reg: nothing special */
  1302. #endif
  1303. vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
  1304. vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
  1305. offset = _par->var.xres_virtual / 4;
  1306. }
  1307. /******************************************************
  1308.  *
  1309.  * 32 bpp
  1310.  *
  1311.  */
  1312. else if (_par->var.bits_per_pixel == 32) {
  1313. DPRINTK ("clgen: preparing for 24/32 bit deep displayn");
  1314. switch (fb_info->btype) {
  1315. case BT_SD64:
  1316. vga_wseq (fb_info->regs, CL_SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */
  1317. vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e); /* MCLK select */
  1318. break;
  1319. case BT_PICCOLO:
  1320. vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
  1321. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
  1322. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
  1323. break;
  1324. case BT_PICASSO:
  1325. vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
  1326. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
  1327. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
  1328. break;
  1329. case BT_SPECTRUM:
  1330. vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
  1331. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */
  1332. vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */
  1333. break;
  1334. case BT_PICASSO4:
  1335. vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
  1336. /*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c);  */
  1337. break;
  1338. case BT_ALPINE:
  1339. DPRINTK (" (for GD543x)n");
  1340. vga_wseq (fb_info->regs, CL_SEQR7, 0xa9);
  1341. clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
  1342. break;
  1343. case BT_GD5480:
  1344. DPRINTK (" (for GD5480)n");
  1345. vga_wseq (fb_info->regs, CL_SEQR7, 0x19);
  1346. /* We already set SRF and SR1F */
  1347. break;
  1348. case BT_LAGUNA:
  1349. DPRINTK (" (for GD546x)n");
  1350. vga_wseq (fb_info->regs, CL_SEQR7,
  1351. vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
  1352. break;
  1353. default:
  1354. printk (KERN_WARNING "clgen: unknown Boardn");
  1355. break;
  1356. }
  1357. vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */
  1358. WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */
  1359. WHDR (fb_info, 0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */
  1360. vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */
  1361. vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */
  1362. offset = _par->var.xres_virtual / 4;
  1363. }
  1364. /******************************************************
  1365.  *
  1366.  * unknown/unsupported bpp
  1367.  *
  1368.  */
  1369. else {
  1370. printk (KERN_ERR "clgen: What's this?? requested color depth == %d.n",
  1371. _par->var.bits_per_pixel);
  1372. }
  1373. vga_wcrt (fb_info->regs, VGA_CRTC_OFFSET, offset & 0xff);
  1374. tmp = 0x22;
  1375. if (offset & 0x100)
  1376. tmp |= 0x10; /* offset overflow bit */
  1377. vga_wcrt (fb_info->regs, CL_CRT1B, tmp); /* screen start addr #16-18, fastpagemode cycles */
  1378. if (fb_info->btype == BT_SD64 ||
  1379.     fb_info->btype == BT_PICASSO4 ||
  1380.     fb_info->btype == BT_ALPINE ||
  1381.     fb_info->btype == BT_GD5480)
  1382. vga_wcrt (fb_info->regs, CL_CRT1D, 0x00); /* screen start address bit 19 */
  1383. vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0); /* text cursor location high */
  1384. vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0); /* text cursor location low */
  1385. vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0); /* underline row scanline = at very bottom */
  1386. vga_wattr (fb_info->regs, VGA_ATC_MODE, 1); /* controller mode */
  1387. vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0); /* overscan (border) color */
  1388. vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 15); /* color plane enable */
  1389. vga_wattr (fb_info->regs, CL_AR33, 0); /* pixel panning */
  1390. vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0); /* color select */
  1391. /* [ EGS: SetOffset(); ] */
  1392. /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
  1393. AttrOn (fb_info);
  1394. vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0); /* set/reset register */
  1395. vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0); /* set/reset enable */
  1396. vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0); /* color compare */
  1397. vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0); /* data rotate */
  1398. vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0); /* read map select */
  1399. vga_wgfx (fb_info->regs, VGA_GFX_MISC, 1); /* miscellaneous register */
  1400. vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 15); /* color don't care */
  1401. vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 255); /* bit mask */
  1402. vga_wseq (fb_info->regs, CL_SEQR12, 0x0); /* graphics cursor attributes: nothing special */
  1403. /* finally, turn on everything - turn off "FullBandwidth" bit */
  1404. /* also, set "DotClock%2" bit where requested */
  1405. tmp = 0x01;
  1406. /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
  1407.     if (var->vmode & FB_VMODE_CLOCK_HALVE)
  1408. tmp |= 0x08;
  1409. */
  1410. vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, tmp);
  1411. DPRINTK ("CL_SEQR1: %dn", tmp);
  1412. fb_info->currentmode = *_par;
  1413. DPRINTK ("virtual offset: (%d,%d)n", _par->var.xoffset, _par->var.yoffset);
  1414. /* pan to requested offset */
  1415. clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen *) fb_info);
  1416. #ifdef CLGEN_DEBUG
  1417. clgen_dump ();
  1418. #endif
  1419. DPRINTK ("EXITn");
  1420. return;
  1421. }
  1422. static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
  1423.     unsigned *blue, unsigned *transp,
  1424.     struct fb_info *info)
  1425. {
  1426.     struct clgenfb_info *fb_info = (struct clgenfb_info *)info;
  1427.     if (regno > 255)
  1428. return 1;
  1429.     *red = fb_info->palette[regno].red;
  1430.     *green = fb_info->palette[regno].green;
  1431.     *blue = fb_info->palette[regno].blue;
  1432.     *transp = 0;
  1433.     return 0;
  1434. }
  1435. static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
  1436.     unsigned blue, unsigned transp,
  1437.     struct fb_info *info)
  1438. {
  1439. struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
  1440. if (regno > 255)
  1441. return -EINVAL;
  1442. #ifdef FBCON_HAS_CFB8
  1443. switch (fb_info->currentmode.var.bits_per_pixel) {
  1444. case 8:
  1445. /* "transparent" stuff is completely ignored. */
  1446. WClut (fb_info, regno, red >> 10, green >> 10, blue >> 10);
  1447. break;
  1448. default:
  1449. /* do nothing */
  1450. break;
  1451. }
  1452. #endif /* FBCON_HAS_CFB8 */
  1453. fb_info->palette[regno].red = red;
  1454. fb_info->palette[regno].green = green;
  1455. fb_info->palette[regno].blue = blue;
  1456. if (regno >= 16)
  1457. return 0;
  1458. switch (fb_info->currentmode.var.bits_per_pixel) {
  1459. #ifdef FBCON_HAS_CFB16
  1460. case 16:
  1461. assert (regno < 16);
  1462. if(isPReP) {
  1463. fb_info->fbcon_cmap.cfb16[regno] =
  1464.     ((red & 0xf800) >> 9) |
  1465.     ((green & 0xf800) >> 14) |
  1466.     ((green & 0xf800) << 2) |
  1467.     ((blue & 0xf800) >> 3);
  1468. } else {
  1469. fb_info->fbcon_cmap.cfb16[regno] =
  1470.     ((red & 0xf800) >> 1) |
  1471.     ((green & 0xf800) >> 6) |
  1472.     ((blue & 0xf800) >> 11);
  1473. }
  1474. #endif /* FBCON_HAS_CFB16 */
  1475. #ifdef FBCON_HAS_CFB24
  1476. case 24:
  1477. assert (regno < 16);
  1478. fb_info->fbcon_cmap.cfb24[regno] =
  1479. (red   << fb_info->currentmode.var.red.offset)   |
  1480. (green << fb_info->currentmode.var.green.offset) |
  1481. (blue  << fb_info->currentmode.var.blue.offset);
  1482. break;
  1483. #endif /* FBCON_HAS_CFB24 */
  1484. #ifdef FBCON_HAS_CFB32
  1485. case 32:
  1486. assert (regno < 16);
  1487. if(isPReP) {
  1488. fb_info->fbcon_cmap.cfb32[regno] =
  1489.     ((red & 0xff00)) |
  1490.     ((green & 0xff00) << 8) |
  1491.     ((blue & 0xff00) << 16);
  1492. } else {
  1493. fb_info->fbcon_cmap.cfb32[regno] =
  1494.     ((red & 0xff00) << 8) |
  1495.     ((green & 0xff00)) |
  1496.     ((blue & 0xff00) >> 8);
  1497. }
  1498. break;
  1499. #endif /* FBCON_HAS_CFB32 */
  1500. default:
  1501. /* do nothing */
  1502. break;
  1503. }
  1504. return 0;
  1505. }
  1506. /*************************************************************************
  1507. clgen_pan_display()
  1508. performs display panning - provided hardware permits this
  1509. **************************************************************************/
  1510. static int clgen_pan_display (const struct fb_var_screeninfo *var,
  1511.       struct fb_info_gen *info)
  1512. {
  1513. int xoffset = 0;
  1514. int yoffset = 0;
  1515. unsigned long base;
  1516. unsigned char tmp = 0, tmp2 = 0, xpix;
  1517. struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
  1518. DPRINTK ("ENTERn");
  1519. /* no range checks for xoffset and yoffset,   */
  1520. /* as fbgen_pan_display has already done this */
  1521. fb_info->currentmode.var.xoffset = var->xoffset;
  1522. fb_info->currentmode.var.yoffset = var->yoffset;
  1523. xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8;
  1524. yoffset = var->yoffset;
  1525. base = yoffset * fb_info->currentmode.line_length + xoffset;
  1526. if (fb_info->currentmode.var.bits_per_pixel == 1) {
  1527. /* base is already correct */
  1528. xpix = (unsigned char) (var->xoffset % 8);
  1529. } else {
  1530. base /= 4;
  1531. xpix = (unsigned char) ((xoffset % 4) * 2);
  1532. }
  1533. /* lower 8 + 8 bits of screen start address */
  1534. vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
  1535. vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
  1536. /* construct bits 16, 17 and 18 of screen start address */
  1537. if (base & 0x10000)
  1538. tmp |= 0x01;
  1539. if (base & 0x20000)
  1540. tmp |= 0x04;
  1541. if (base & 0x40000)
  1542. tmp |= 0x08;
  1543. tmp2 = (vga_rcrt (fb_info->regs, CL_CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */
  1544. vga_wcrt (fb_info->regs, CL_CRT1B, tmp2);
  1545. /* construct bit 19 of screen start address */
  1546. if (clgen_board_info[fb_info->btype].scrn_start_bit19) {
  1547. tmp2 = 0;
  1548. if (base & 0x80000)
  1549. tmp2 = 0x80;
  1550. vga_wcrt (fb_info->regs, CL_CRT1D, tmp2);
  1551. }
  1552. /* write pixel panning value to AR33; this does not quite work in 8bpp */
  1553. /* ### Piccolo..? Will this work? */
  1554. if (fb_info->currentmode.var.bits_per_pixel == 1)
  1555. vga_wattr (fb_info->regs, CL_AR33, xpix);
  1556. DPRINTK ("EXITn");
  1557. return (0);
  1558. }
  1559. static int clgen_blank (int blank_mode, struct fb_info_gen *info)
  1560. {
  1561. /*
  1562.  *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
  1563.  *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
  1564.  *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
  1565.  *  to e.g. a video mode which doesn't support it. Implements VESA suspend
  1566.  *  and powerdown modes on hardware that supports disabling hsync/vsync:
  1567.  *    blank_mode == 2: suspend vsync
  1568.  *    blank_mode == 3: suspend hsync
  1569.  *    blank_mode == 4: powerdown
  1570.  */
  1571. unsigned char val;
  1572. static int current_mode = 0;
  1573. struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
  1574. DPRINTK ("ENTER, blank mode = %dn", blank_mode);
  1575. if (current_mode == blank_mode) {
  1576. DPRINTK ("EXIT, returning 0n");
  1577. return 0;
  1578. }
  1579. /* Undo current */
  1580. switch (current_mode) {
  1581. case 0: /* Screen is normal */
  1582. break;
  1583. case 1: /* Screen is blanked */
  1584. val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
  1585. vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* clear "FullBandwidth" bit */
  1586. break;
  1587. case 2: /* vsync suspended */
  1588. case 3: /* hsync suspended */
  1589. case 4: /* sceen is powered down */
  1590. vga_wgfx (fb_info->regs, CL_GRE, 0x00);
  1591. break;
  1592. default:
  1593. DPRINTK ("EXIT, returning 1n");
  1594. return 1;
  1595. }
  1596. /* set new */
  1597. switch (blank_mode) {
  1598. case 0: /* Unblank screen */
  1599. break;
  1600. case 1: /* Blank screen */
  1601. val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
  1602. vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val | 0x20); /* set "FullBandwidth" bit */
  1603. break;
  1604. case 2: /* suspend vsync */
  1605. vga_wgfx (fb_info->regs, CL_GRE, 0x04);
  1606. break;
  1607. case 3: /* suspend hsync */
  1608. vga_wgfx (fb_info->regs, CL_GRE, 0x02);
  1609. break;
  1610. case 4: /* powerdown */
  1611. vga_wgfx (fb_info->regs, CL_GRE, 0x06);
  1612. break;
  1613. default:
  1614. DPRINTK ("EXIT, returning 1n");
  1615. return 1;
  1616. }
  1617. current_mode = blank_mode;
  1618. DPRINTK ("EXIT, returning 0n");
  1619. return 0;
  1620. }
  1621. /**** END   Hardware specific Routines **************************************/
  1622. /****************************************************************************/
  1623. /**** BEGIN Internal Routines ***********************************************/
  1624. static void __init init_vgachip (struct clgenfb_info *fb_info)
  1625. {
  1626. const struct clgen_board_info_rec *bi;
  1627. DPRINTK ("ENTERn");
  1628. assert (fb_info != NULL);
  1629. bi = &clgen_board_info[fb_info->btype];
  1630. /* reset board globally */
  1631. switch (fb_info->btype) {
  1632. case BT_PICCOLO:
  1633. WSFR (fb_info, 0x01);
  1634. udelay (500);
  1635. WSFR (fb_info, 0x51);
  1636. udelay (500);
  1637. break;
  1638. case BT_PICASSO:
  1639. WSFR2 (fb_info, 0xff);
  1640. udelay (500);
  1641. break;
  1642. case BT_SD64:
  1643. case BT_SPECTRUM:
  1644. WSFR (fb_info, 0x1f);
  1645. udelay (500);
  1646. WSFR (fb_info, 0x4f);
  1647. udelay (500);
  1648. break;
  1649. case BT_PICASSO4:
  1650. vga_wcrt (fb_info->regs, CL_CRT51, 0x00); /* disable flickerfixer */
  1651. mdelay (100);
  1652. vga_wgfx (fb_info->regs, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
  1653. vga_wgfx (fb_info->regs, CL_GR33, 0x00); /* put blitter into 542x compat */
  1654. vga_wgfx (fb_info->regs, CL_GR31, 0x00); /* mode */
  1655. break;
  1656. case BT_GD5480:
  1657. vga_wgfx (fb_info->regs, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */
  1658. break;
  1659. case BT_ALPINE:
  1660. /* Nothing to do to reset the board. */
  1661. break;
  1662. default:
  1663. printk (KERN_ERR "clgen: Warning: Unknown board typen");
  1664. break;
  1665. }
  1666. assert (fb_info->size > 0); /* make sure RAM size set by this point */
  1667. /* assume it's a "large memory" board (2/4 MB) */
  1668. fb_info->smallboard = FALSE;
  1669. /* the P4 is not fully initialized here; I rely on it having been */
  1670. /* inited under AmigaOS already, which seems to work just fine    */
  1671. /* (Klaus advised to do it this way)                              */
  1672. if (fb_info->btype != BT_PICASSO4) {
  1673. WGen (fb_info, CL_VSSM, 0x10); /* EGS: 0x16 */
  1674. WGen (fb_info, CL_POS102, 0x01);
  1675. WGen (fb_info, CL_VSSM, 0x08); /* EGS: 0x0e */
  1676. if (fb_info->btype != BT_SD64)
  1677. WGen (fb_info, CL_VSSM2, 0x01);
  1678. vga_wseq (fb_info->regs, CL_SEQR0, 0x03); /* reset sequencer logic */
  1679. vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */
  1680. WGen (fb_info, VGA_MIS_W, 0xc1); /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
  1681. /*      vga_wgfx (fb_info->regs, CL_GRA, 0xce);    "magic cookie" - doesn't make any sense to me.. */
  1682. vga_wseq (fb_info->regs, CL_SEQR6, 0x12); /* unlock all extension registers */
  1683. vga_wgfx (fb_info->regs, CL_GR31, 0x04); /* reset blitter */
  1684. switch (fb_info->btype) {
  1685. case BT_GD5480:
  1686. vga_wseq (fb_info->regs, CL_SEQRF, 0x98);
  1687. break;
  1688. case BT_ALPINE:
  1689. break;
  1690. case BT_SD64:
  1691. vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);
  1692. break;
  1693. default:
  1694. vga_wseq (fb_info->regs, CL_SEQR16, 0x0f);
  1695. vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);
  1696. break;
  1697. }
  1698. }
  1699. vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: nothing */
  1700. vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */
  1701. vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */
  1702. /* controller-internal base address of video memory */
  1703. if (bi->init_sr07)
  1704. vga_wseq (fb_info->regs, CL_SEQR7, bi->sr07);
  1705. /*  vga_wseq (fb_info->regs, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
  1706. vga_wseq (fb_info->regs, CL_SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */
  1707. vga_wseq (fb_info->regs, CL_SEQR11, 0x00); /* graphics cursor Y position (..."... ) */
  1708. vga_wseq (fb_info->regs, CL_SEQR12, 0x00); /* graphics cursor attributes */
  1709. vga_wseq (fb_info->regs, CL_SEQR13, 0x00); /* graphics cursor pattern address */
  1710. /* writing these on a P4 might give problems..  */
  1711. if (fb_info->btype != BT_PICASSO4) {
  1712. vga_wseq (fb_info->regs, CL_SEQR17, 0x00); /* configuration readback and ext. color */
  1713. vga_wseq (fb_info->regs, CL_SEQR18, 0x02); /* signature generator */
  1714. }
  1715. /* MCLK select etc. */
  1716. if (bi->init_sr1f)
  1717. vga_wseq (fb_info->regs, CL_SEQR1F, bi->sr1f);
  1718. vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0x00); /* Screen A preset row scan: none */
  1719. vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */
  1720. vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 0x00); /* Text cursor end: - */
  1721. vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, 0x00); /* Screen start address high: 0 */
  1722. vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, 0x00); /* Screen start address low: 0 */
  1723. vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location high: 0 */
  1724. vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0x00); /* text cursor location low: 0 */
  1725. vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0x00); /* Underline Row scanline: - */
  1726. vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */
  1727. vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */
  1728. /* ### add 0x40 for text modes with > 30 MHz pixclock */
  1729. vga_wcrt (fb_info->regs, CL_CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */
  1730. vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset registes: - */
  1731. vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0x00); /* Set/Reset enable: - */
  1732. vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */
  1733. vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0x00); /* Data Rotate: - */
  1734. vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0x00); /* Read Map Select: - */
  1735. vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
  1736. vga_wgfx (fb_info->regs, VGA_GFX_MISC, 0x01); /* Miscellaneous: memory map base address, graphics mode */
  1737. vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 0x0f); /* Color Don't care: involve all planes */
  1738. vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 0xff); /* Bit Mask: no mask at all */
  1739. if (fb_info->btype == BT_ALPINE)
  1740. vga_wgfx (fb_info->regs, CL_GRB, 0x20); /* (5434 can't have bit 3 set for bitblt) */
  1741. else
  1742. vga_wgfx (fb_info->regs, CL_GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */
  1743. vga_wgfx (fb_info->regs, CL_GRC, 0xff); /* Color Key compare: - */
  1744. vga_wgfx (fb_info->regs, CL_GRD, 0x00); /* Color Key compare mask: - */
  1745. vga_wgfx (fb_info->regs, CL_GRE, 0x00); /* Miscellaneous control: - */
  1746. /*  vga_wgfx (fb_info->regs, CL_GR10, 0x00); *//* Background color byte 1: - */
  1747. /*  vga_wgfx (fb_info->regs, CL_GR11, 0x00); */
  1748. vga_wattr (fb_info->regs, VGA_ATC_PALETTE0, 0x00); /* Attribute Controller palette registers: "identity mapping" */
  1749. vga_wattr (fb_info->regs, VGA_ATC_PALETTE1, 0x01);
  1750. vga_wattr (fb_info->regs, VGA_ATC_PALETTE2, 0x02);
  1751. vga_wattr (fb_info->regs, VGA_ATC_PALETTE3, 0x03);
  1752. vga_wattr (fb_info->regs, VGA_ATC_PALETTE4, 0x04);
  1753. vga_wattr (fb_info->regs, VGA_ATC_PALETTE5, 0x05);
  1754. vga_wattr (fb_info->regs, VGA_ATC_PALETTE6, 0x06);
  1755. vga_wattr (fb_info->regs, VGA_ATC_PALETTE7, 0x07);
  1756. vga_wattr (fb_info->regs, VGA_ATC_PALETTE8, 0x08);
  1757. vga_wattr (fb_info->regs, VGA_ATC_PALETTE9, 0x09);
  1758. vga_wattr (fb_info->regs, VGA_ATC_PALETTEA, 0x0a);
  1759. vga_wattr (fb_info->regs, VGA_ATC_PALETTEB, 0x0b);
  1760. vga_wattr (fb_info->regs, VGA_ATC_PALETTEC, 0x0c);
  1761. vga_wattr (fb_info->regs, VGA_ATC_PALETTED, 0x0d);
  1762. vga_wattr (fb_info->regs, VGA_ATC_PALETTEE, 0x0e);
  1763. vga_wattr (fb_info->regs, VGA_ATC_PALETTEF, 0x0f);
  1764. vga_wattr (fb_info->regs, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */
  1765. vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0x00); /* Overscan color reg.: reg. 0 */
  1766. vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */
  1767. /* ###  vga_wattr (fb_info->regs, CL_AR33, 0x00); * Pixel Panning: - */
  1768. vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0x00); /* Color Select: - */
  1769. WGen (fb_info, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
  1770. if (fb_info->btype != BT_ALPINE && fb_info->btype != BT_GD5480)
  1771. WGen (fb_info, VGA_MIS_W, 0xc3); /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
  1772. vga_wgfx (fb_info->regs, CL_GR31, 0x04); /* BLT Start/status: Blitter reset */
  1773. vga_wgfx (fb_info->regs, CL_GR31, 0x00); /* - " -           : "end-of-reset" */
  1774. /* CLUT setup */
  1775. WClut (fb_info, 0, 0x00, 0x00, 0x00); /* background: black */
  1776. WClut (fb_info, 1, 0x3f, 0x3f, 0x3f); /* foreground: white */
  1777. WClut (fb_info, 2, 0x00, 0x20, 0x00);
  1778. WClut (fb_info, 3, 0x00, 0x20, 0x20);
  1779. WClut (fb_info, 4, 0x20, 0x00, 0x00);
  1780. WClut (fb_info, 5, 0x20, 0x00, 0x20);
  1781. WClut (fb_info, 6, 0x20, 0x10, 0x00);
  1782. WClut (fb_info, 7, 0x20, 0x20, 0x20);
  1783. WClut (fb_info, 8, 0x10, 0x10, 0x10);
  1784. WClut (fb_info, 9, 0x10, 0x10, 0x30);
  1785. WClut (fb_info, 10, 0x10, 0x30, 0x10);
  1786. WClut (fb_info, 11, 0x10, 0x30, 0x30);
  1787. WClut (fb_info, 12, 0x30, 0x10, 0x10);
  1788. WClut (fb_info, 13, 0x30, 0x10, 0x30);
  1789. WClut (fb_info, 14, 0x30, 0x30, 0x10);
  1790. WClut (fb_info, 15, 0x30, 0x30, 0x30);
  1791. /* the rest a grey ramp */
  1792. {
  1793. int i;
  1794. for (i = 16; i < 256; i++)
  1795. WClut (fb_info, i, i >> 2, i >> 2, i >> 2);
  1796. }
  1797. /* misc... */
  1798. WHDR (fb_info, 0); /* Hidden DAC register: - */
  1799. printk (KERN_INFO "clgen: This board has %ld bytes of DRAM memoryn", fb_info->size);
  1800. DPRINTK ("EXITn");
  1801. return;
  1802. }
  1803. static void switch_monitor (struct clgenfb_info *fb_info, int on)
  1804. {
  1805. #ifdef CONFIG_ZORRO /* only works on Zorro boards */
  1806. static int IsOn = 0; /* XXX not ok for multiple boards */
  1807. DPRINTK ("ENTERn");
  1808. if (fb_info->btype == BT_PICASSO4)
  1809. return; /* nothing to switch */
  1810. if (fb_info->btype == BT_ALPINE)
  1811. return; /* nothing to switch */
  1812. if (fb_info->btype == BT_GD5480)
  1813. return; /* nothing to switch */
  1814. if (fb_info->btype == BT_PICASSO) {
  1815. if ((on && !IsOn) || (!on && IsOn))
  1816. WSFR (fb_info, 0xff);
  1817. DPRINTK ("EXITn");
  1818. return;
  1819. }
  1820. if (on) {
  1821. switch (fb_info->btype) {
  1822. case BT_SD64:
  1823. WSFR (fb_info, fb_info->SFR | 0x21);
  1824. break;
  1825. case BT_PICCOLO:
  1826. WSFR (fb_info, fb_info->SFR | 0x28);
  1827. break;
  1828. case BT_SPECTRUM:
  1829. WSFR (fb_info, 0x6f);
  1830. break;
  1831. default: /* do nothing */ break;
  1832. }
  1833. } else {
  1834. switch (fb_info->btype) {
  1835. case BT_SD64:
  1836. WSFR (fb_info, fb_info->SFR & 0xde);
  1837. break;
  1838. case BT_PICCOLO:
  1839. WSFR (fb_info, fb_info->SFR & 0xd7);
  1840. break;
  1841. case BT_SPECTRUM:
  1842. WSFR (fb_info, 0x4f);
  1843. break;
  1844. default: /* do nothing */ break;
  1845. }
  1846. }
  1847. DPRINTK ("EXITn");
  1848. #endif /* CONFIG_ZORRO */
  1849. }
  1850. static void clgen_set_disp (const void *par, struct display *disp,
  1851.     struct fb_info_gen *info)
  1852. {
  1853. struct clgenfb_par *_par = (struct clgenfb_par *) par;
  1854. struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
  1855. int accel_text;
  1856. DPRINTK ("ENTERn");
  1857. assert (_par != NULL);
  1858. assert (fb_info != NULL);
  1859. accel_text = _par->var.accel_flags & FB_ACCELF_TEXT;
  1860. printk ("Cirrus Logic video mode: ");
  1861. disp->screen_base = (char *) fb_info->fbmem;
  1862. switch (_par->var.bits_per_pixel) {
  1863. #ifdef FBCON_HAS_MFB
  1864. case 1:
  1865. printk ("monochromen");
  1866. if (fb_info->btype == BT_GD5480)
  1867. disp->screen_base = (char *) fb_info->fbmem;
  1868. disp->dispsw = &fbcon_mfb;
  1869. break;
  1870. #endif
  1871. #ifdef FBCON_HAS_CFB8
  1872. case 8:
  1873. printk ("8 bit color depthn");
  1874. if (fb_info->btype == BT_GD5480)
  1875. disp->screen_base = (char *) fb_info->fbmem;
  1876. if (accel_text)
  1877. disp->dispsw = &fbcon_clgen_8;
  1878. else
  1879. disp->dispsw = &fbcon_cfb8;
  1880. break;
  1881. #endif
  1882. #ifdef FBCON_HAS_CFB16
  1883. case 16:
  1884. printk ("16 bit color depthn");
  1885. if (accel_text)
  1886. disp->dispsw = &fbcon_clgen_16;
  1887. else
  1888. disp->dispsw = &fbcon_cfb16;
  1889. if (fb_info->btype == BT_GD5480)
  1890. disp->screen_base = (char *) fb_info->fbmem + 1 * MB_;
  1891. disp->dispsw_data = fb_info->fbcon_cmap.cfb16;
  1892. break;
  1893. #endif
  1894. #ifdef FBCON_HAS_CFB24
  1895. case 24:
  1896. printk ("24 bit color depthn");
  1897. disp->dispsw = &fbcon_cfb24;
  1898. if (fb_info->btype == BT_GD5480)
  1899. disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
  1900. disp->dispsw_data = fb_info->fbcon_cmap.cfb24;
  1901. break;
  1902. #endif
  1903. #ifdef FBCON_HAS_CFB32
  1904. case 32:
  1905. printk ("32 bit color depthn");
  1906. if (accel_text)
  1907. disp->dispsw = &fbcon_clgen_32;
  1908. else
  1909. disp->dispsw = &fbcon_cfb32;
  1910. if (fb_info->btype == BT_GD5480)
  1911. disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
  1912. disp->dispsw_data = fb_info->fbcon_cmap.cfb32;
  1913. break;
  1914. #endif
  1915. default:
  1916. printk ("unsupported color depthn");
  1917. disp->dispsw = &fbcon_dummy;
  1918. disp->dispsw_data = NULL;
  1919. break;
  1920. }
  1921. DPRINTK ("EXITn");
  1922. }
  1923. #ifdef FBCON_HAS_CFB8
  1924. static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
  1925. int dy, int dx, int height, int width)
  1926. {
  1927. struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
  1928. DPRINTK ("ENTERn");
  1929. sx *= fontwidth (p);
  1930. sy *= fontheight (p);
  1931. dx *= fontwidth (p);
  1932. dy *= fontheight (p);
  1933. width *= fontwidth (p);
  1934. height *= fontheight (p);
  1935. clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
  1936.       (unsigned short) dx, (unsigned short) dy,
  1937.       (unsigned short) width, (unsigned short) height,
  1938.       fb_info->currentmode.line_length);
  1939. DPRINTK ("EXITn");
  1940. }
  1941. static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
  1942. int sy, int sx, int height, int width)
  1943. {
  1944. struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
  1945. unsigned short col;
  1946. DPRINTK ("ENTERn");
  1947. sx *= fontwidth (p);
  1948. sy *= fontheight (p);
  1949. width *= fontwidth (p);
  1950. height *= fontheight (p);
  1951. col = attr_bgcol_ec (p, conp);
  1952. col &= 0xff;
  1953. clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
  1954. (unsigned short) width, (unsigned short) height,
  1955. col, fb_info->currentmode.line_length);
  1956. DPRINTK ("EXITn");
  1957. }
  1958. #endif
  1959. #ifdef FBCON_HAS_CFB16
  1960. static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
  1961.  int dy, int dx, int height, int width)
  1962. {
  1963. struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
  1964. DPRINTK ("ENTERn");
  1965. sx *= fontwidth (p) * 2; /* 2 bytes/pixel */
  1966. sy *= fontheight (p);
  1967. dx *= fontwidth (p) * 2; /* 2 bytes/pixel */
  1968. dy *= fontheight (p);
  1969. width *= fontwidth (p) * 2; /* 2 bytes/pixel */
  1970. height *= fontheight (p);
  1971. clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
  1972.       (unsigned short) dx, (unsigned short) dy,
  1973.       (unsigned short) width, (unsigned short) height,
  1974.       fb_info->currentmode.line_length);
  1975. DPRINTK ("EXITn");
  1976. }
  1977. static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
  1978.  int sy, int sx, int height, int width)
  1979. {
  1980. struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
  1981. unsigned short col;
  1982. DPRINTK ("ENTERn");
  1983. sx *= fontwidth (p) * 2; /* 2 bytes/pixel */
  1984. sy *= fontheight (p);
  1985. width *= fontwidth (p) * 2; /* 2 bytes/pixel? */
  1986. height *= fontheight (p);
  1987. col = attr_bgcol_ec (p, conp);
  1988. col &= 0xff;
  1989. clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
  1990. (unsigned short) width, (unsigned short) height,
  1991. col, fb_info->currentmode.line_length);
  1992. DPRINTK ("EXITn");
  1993. }
  1994. #endif
  1995. #ifdef FBCON_HAS_CFB32
  1996. static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
  1997.  int dy, int dx, int height, int width)
  1998. {
  1999. struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
  2000. DPRINTK ("ENTERn");
  2001. sx *= fontwidth (p) * 4; /* 4 bytes/pixel */
  2002. sy *= fontheight (p);
  2003. dx *= fontwidth (p) * 4; /* 4 bytes/pixel */
  2004. dy *= fontheight (p);
  2005. width *= fontwidth (p) * 4; /* 4 bytes/pixel */
  2006. height *= fontheight (p);
  2007. clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
  2008.       (unsigned short) dx, (unsigned short) dy,
  2009.       (unsigned short) width, (unsigned short) height,
  2010.       fb_info->currentmode.line_length);
  2011. DPRINTK ("EXITn");
  2012. }
  2013. static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
  2014.  int sy, int sx, int height, int width)
  2015. {
  2016. struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
  2017. unsigned short col;
  2018. DPRINTK ("ENTERn");
  2019. sx *= fontwidth (p) * 4; /* 4 bytes/pixel */
  2020. sy *= fontheight (p);
  2021. width *= fontwidth (p) * 4; /* 4 bytes/pixel? */
  2022. height *= fontheight (p);
  2023. col = attr_bgcol_ec (p, conp);
  2024. col &= 0xff;
  2025. clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
  2026. (unsigned short) width, (unsigned short) height,
  2027. col, fb_info->currentmode.line_length);
  2028. DPRINTK ("EXITn");
  2029. }
  2030. #endif /* FBCON_HAS_CFB32 */
  2031. #ifdef CONFIG_ALL_PPC
  2032. #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
  2033. #define PREP_IO_BASE    ((volatile unsigned char *) 0x80000000)
  2034. static void __init get_prep_addrs (unsigned long *display, unsigned long *registers)
  2035. {
  2036. DPRINTK ("ENTERn");
  2037. *display = PREP_VIDEO_BASE;
  2038. *registers = (unsigned long) PREP_IO_BASE;
  2039. DPRINTK ("EXITn");
  2040. }
  2041. #endif /* CONFIG_ALL_PPC */
  2042. #ifdef CONFIG_PCI
  2043. static int release_io_ports = 0;
  2044. /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
  2045.  * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
  2046.  * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
  2047.  * seem to have. */
  2048. static unsigned int __init clgen_get_memsize (caddr_t regbase)
  2049. {
  2050. unsigned long mem;
  2051. unsigned char SRF;
  2052. DPRINTK ("ENTERn");
  2053. SRF = vga_rseq (regbase, CL_SEQRF);
  2054. switch ((SRF & 0x18)) {
  2055.     case 0x08: mem = 512 * 1024; break;
  2056.     case 0x10: mem = 1024 * 1024; break;
  2057. /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
  2058.    * on the 5430. */
  2059.     case 0x18: mem = 2048 * 1024; break;
  2060.     default: printk ("CLgenfb: Unknown memory size!n");
  2061. mem = 1024 * 1024;
  2062. }
  2063. if (SRF & 0x80) {
  2064. /* If DRAM bank switching is enabled, there must be twice as much
  2065.    * memory installed. (4MB on the 5434) */
  2066. mem *= 2;
  2067. }
  2068. /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
  2069. return mem;
  2070. DPRINTK ("EXITn");
  2071. }
  2072. static struct pci_dev * __init clgen_pci_dev_get (clgen_board_t *btype)
  2073. {
  2074. struct pci_dev *pdev;
  2075. int i;
  2076. DPRINTK ("ENTERn");
  2077. for (i = 0; i < ARRAY_SIZE(clgen_pci_probe_list); i++) {
  2078. pdev = NULL;
  2079. while ((pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS,
  2080. clgen_pci_probe_list[i].device, pdev)) != NULL) {
  2081. if (pci_enable_device(pdev) == 0) {
  2082. *btype = clgen_pci_probe_list[i].btype;
  2083. DPRINTK ("EXIT, returning pdev=%pn", pdev);
  2084. return pdev;
  2085. }
  2086. }
  2087. }
  2088. DPRINTK ("EXIT, returning NULLn");
  2089. return NULL;
  2090. }
  2091. static void __init get_pci_addrs (const struct pci_dev *pdev,
  2092.    unsigned long *display, unsigned long *registers)
  2093. {
  2094. assert (pdev != NULL);
  2095. assert (display != NULL);
  2096. assert (registers != NULL);
  2097. DPRINTK ("ENTERn");
  2098. *display = 0;
  2099. *registers = 0;
  2100. /* This is a best-guess for now */
  2101. if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
  2102. *display = pci_resource_start(pdev, 1);
  2103. *registers = pci_resource_start(pdev, 0);
  2104. } else {
  2105. *display = pci_resource_start(pdev, 0);
  2106. *registers = pci_resource_start(pdev, 1);
  2107. }
  2108. assert (*display != 0);
  2109. DPRINTK ("EXITn");
  2110. }
  2111. static void __exit clgen_pci_unmap (struct clgenfb_info *info)
  2112. {
  2113. iounmap (info->fbmem);
  2114. release_mem_region(info->fbmem_phys, info->size);
  2115. #if 0 /* if system didn't claim this region, we would... */
  2116. release_mem_region(0xA0000, 65535);
  2117. #endif
  2118. if (release_io_ports)
  2119. release_region(0x3C0, 32);
  2120. }
  2121. static int __init clgen_pci_setup (struct clgenfb_info *info,
  2122.    clgen_board_t *btype)
  2123. {
  2124. struct pci_dev *pdev;
  2125. unsigned long board_addr, board_size;
  2126. DPRINTK ("ENTERn");
  2127. pdev = clgen_pci_dev_get (btype);
  2128. if (!pdev) {
  2129. printk (KERN_ERR " Couldn't find PCI devicen");
  2130. DPRINTK ("EXIT, returning 1n");
  2131. return 1;
  2132. }
  2133. DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %dn",
  2134.  pdev->resource[0].start, *btype);
  2135. DPRINTK (" base address 1 is 0x%lxn", pdev->resource[1].start);
  2136. info->pdev = pdev;
  2137. if(isPReP) {
  2138. /* Xbh does this, though 0 seems to be the init value */
  2139. pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0,
  2140. 0x00000000);
  2141. #ifdef CONFIG_ALL_PPC
  2142. get_prep_addrs (&board_addr, &info->fbregs_phys);
  2143. #endif
  2144. } else {
  2145. DPRINTK ("Attempt to get PCI info for Cirrus Graphics Cardn");
  2146. get_pci_addrs (pdev, &board_addr, &info->fbregs_phys);
  2147. }
  2148. DPRINTK ("Board address: 0x%lx, register address: 0x%lxn", board_addr, info->fbregs_phys);
  2149. if(isPReP) {
  2150. /* PReP dies if we ioremap the IO registers, but it works w/out... */
  2151. info->regs = (char *) info->fbregs_phys;
  2152. } else
  2153. info->regs = 0; /* FIXME: this forces VGA.  alternatives? */
  2154. if (*btype == BT_GD5480) {
  2155. board_size = 32 * MB_;
  2156. } else {
  2157. board_size = clgen_get_memsize (info->regs);
  2158. }
  2159. if (!request_mem_region(board_addr, board_size, "clgenfb")) {
  2160. printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abortn",
  2161.        board_addr);
  2162. return -1;
  2163. }
  2164. #if 0 /* if the system didn't claim this region, we would... */
  2165. if (!request_mem_region(0xA0000, 65535, "clgenfb")) {
  2166. printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abortn",
  2167.        0xA0000L);
  2168. release_mem_region(board_addr, board_size);
  2169. return -1;
  2170. }
  2171. #endif
  2172. if (request_region(0x3C0, 32, "clgenfb"))
  2173. release_io_ports = 1;
  2174. info->fbmem = ioremap (board_addr, board_size);
  2175. info->fbmem_phys = board_addr;
  2176. info->size = board_size;
  2177. printk (" RAM (%lu kB) at 0x%lx, ", info->size / KB_, board_addr);
  2178. printk ("Cirrus Logic chipset on PCI busn");
  2179. DPRINTK ("EXIT, returning 0n");
  2180. return 0;
  2181. }
  2182. #endif /* CONFIG_PCI */
  2183. #ifdef CONFIG_ZORRO
  2184. static int __init clgen_zorro_find (struct zorro_dev **z_o,
  2185.     struct zorro_dev **z2_o,
  2186.     clgen_board_t *btype, unsigned long *size)
  2187. {
  2188. struct zorro_dev *z = NULL;
  2189. int i;
  2190. assert (z_o != NULL);
  2191. assert (btype != NULL);
  2192. for (i = 0; i < ARRAY_SIZE(clgen_zorro_probe_list); i++)
  2193. if ((z = zorro_find_device(clgen_zorro_probe_list[i].id, NULL)))
  2194. break;
  2195. if (z) {
  2196. *z_o = z;
  2197. if (clgen_zorro_probe_list[i].id2)
  2198. *z2_o = zorro_find_device(clgen_zorro_probe_list[i].id2, NULL);
  2199. else
  2200. *z2_o = NULL;
  2201. *btype = clgen_zorro_probe_list[i].btype;
  2202. *size = clgen_zorro_probe_list[i].size;
  2203. printk (KERN_INFO "clgen: %s board detected; ",
  2204. clgen_board_info[*btype].name);
  2205. return 0;
  2206. }
  2207. printk (KERN_NOTICE "clgen: no supported board found.n");
  2208. return -1;
  2209. }
  2210. static void __exit clgen_zorro_unmap (struct clgenfb_info *info)
  2211. {
  2212. release_mem_region(info->board_addr, info->board_size);
  2213. if (info->btype == BT_PICASSO4) {
  2214. iounmap ((void *)info->board_addr);
  2215. iounmap ((void *)info->fbmem_phys);
  2216. } else {
  2217. if (info->board_addr > 0x01000000)
  2218. iounmap ((void *)info->board_addr);
  2219. }
  2220. }
  2221. static int __init clgen_zorro_setup (struct clgenfb_info *info,
  2222.      clgen_board_t *btype)
  2223. {
  2224. struct zorro_dev *z = NULL, *z2 = NULL;
  2225. unsigned long board_addr, board_size, size;
  2226. assert (info != NULL);
  2227. assert (btype != NULL);
  2228. if (clgen_zorro_find (&z, &z2, btype, &size))
  2229. return -1;
  2230. assert (z > 0);
  2231. assert (z2 >= 0);
  2232. assert (*btype != BT_NONE);
  2233. info->board_addr = board_addr = z->resource.start;
  2234. info->board_size = board_size = z->resource.end-z->resource.start+1;
  2235. info->size = size;
  2236. if (!request_mem_region(board_addr, board_size, "clgenfb")) {
  2237. printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abortn",
  2238.        board_addr);
  2239. return -1;
  2240. }
  2241. printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
  2242. if (*btype == BT_PICASSO4) {
  2243. printk (" REG at $%lxn", board_addr + 0x600000);
  2244. /* To be precise, for the P4 this is not the */
  2245. /* begin of the board, but the begin of RAM. */
  2246. /* for P4, map in its address space in 2 chunks (### TEST! ) */
  2247. /* (note the ugly hardcoded 16M number) */
  2248. info->regs = ioremap (board_addr, 16777216);
  2249. DPRINTK ("clgen: Virtual address for board set to: $%pn", info->regs);
  2250. info->regs += 0x600000;
  2251. info->fbregs_phys = board_addr + 0x600000;
  2252. info->fbmem_phys = board_addr + 16777216;
  2253. info->fbmem = ioremap (info->fbmem_phys, 16777216);
  2254. } else {
  2255. printk (" REG at $%lxn", (unsigned long) z2->resource.start);
  2256. info->fbmem_phys = board_addr;
  2257. if (board_addr > 0x01000000)
  2258. info->fbmem = ioremap (board_addr, board_size);
  2259. else
  2260. info->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
  2261. /* set address for REG area of board */
  2262. info->regs = (caddr_t) ZTWO_VADDR (z2->resource.start);
  2263. info->fbregs_phys = z2->resource.start;
  2264. DPRINTK ("clgen: Virtual address for board set to: $%pn", info->regs);
  2265. }
  2266. printk (KERN_INFO "Cirrus Logic chipset on Zorro busn");
  2267. return 0;
  2268. }
  2269. #endif /* CONFIG_ZORRO */
  2270. /********************************************************************/
  2271. /* clgenfb_init() - master initialization function                  */
  2272. /********************************************************************/
  2273. int __init clgenfb_init(void)
  2274. {
  2275. int err, j, k;
  2276. clgen_board_t btype = BT_NONE;
  2277. struct clgenfb_info *fb_info = NULL;
  2278. DPRINTK ("ENTERn");
  2279. printk (KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "n");
  2280. fb_info = &boards[0]; /* FIXME support multiple boards ... */
  2281. #ifdef CONFIG_PCI
  2282. if (clgen_pci_setup (fb_info, &btype)) { /* Also does OF setup */
  2283. DPRINTK ("EXIT, returning -ENXIOn");
  2284. return -ENXIO;
  2285. }
  2286. #elif defined(CONFIG_ZORRO)
  2287. /* FIXME: CONFIG_PCI and CONFIG_ZORRO may both be defined */
  2288. if (clgen_zorro_setup (fb_info, &btype)) {
  2289. DPRINTK ("EXIT, returning -ENXIOn");
  2290. return -ENXIO;
  2291. }
  2292. #else
  2293. #error This driver requires Zorro or PCI bus.
  2294. #endif /* !CONFIG_PCI, !CONFIG_ZORRO */
  2295. /* sanity checks */
  2296. assert (btype != BT_NONE);
  2297. assert (btype == clgen_board_info[btype].btype);
  2298. fb_info->btype = btype;
  2299. DPRINTK ("clgen: (RAM start set to: 0x%p)n", fb_info->fbmem);
  2300. if (noaccel)
  2301. {
  2302. printk("clgen: disabling text acceleration supportn");
  2303. #ifdef FBCON_HAS_CFB8
  2304. fbcon_clgen_8.bmove = fbcon_cfb8_bmove;
  2305. fbcon_clgen_8.clear = fbcon_cfb8_clear;
  2306. #endif
  2307. #ifdef FBCON_HAS_CFB16
  2308. fbcon_clgen_16.bmove = fbcon_cfb16_bmove;
  2309. fbcon_clgen_16.clear = fbcon_cfb16_clear;
  2310. #endif
  2311. #ifdef FBCON_HAS_CFB32
  2312. fbcon_clgen_32.bmove = fbcon_cfb32_bmove;
  2313. fbcon_clgen_32.clear = fbcon_cfb32_clear;
  2314. #endif
  2315. }
  2316. init_vgachip (fb_info);
  2317. /* set up a few more things, register framebuffer driver etc */
  2318. fb_info->gen.parsize = sizeof (struct clgenfb_par);
  2319. fb_info->gen.fbhw = &clgen_hwswitch;
  2320. strncpy (fb_info->gen.info.modename, clgen_board_info[btype].name,
  2321.  sizeof (fb_info->gen.info.modename));
  2322. fb_info->gen.info.modename [sizeof (fb_info->gen.info.modename) - 1] = 0;
  2323. fb_info->gen.info.node = -1;
  2324. fb_info->gen.info.fbops = &clgenfb_ops;
  2325. fb_info->gen.info.disp = &disp;
  2326. fb_info->gen.info.changevar = NULL;
  2327. fb_info->gen.info.switch_con = &fbgen_switch;
  2328. fb_info->gen.info.updatevar = &fbgen_update_var;
  2329. fb_info->gen.info.blank = &fbgen_blank;
  2330. fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;
  2331. for (j = 0; j < 256; j++) {
  2332. if (j < 16) {
  2333. k = color_table[j];
  2334. fb_info->palette[j].red = default_red[k];
  2335. fb_info->palette[j].green = default_grn[k];
  2336. fb_info->palette[j].blue = default_blu[k];
  2337. } else {
  2338. fb_info->palette[j].red =
  2339. fb_info->palette[j].green =
  2340. fb_info->palette[j].blue = j;
  2341. }
  2342. }
  2343. /* now that we know the board has been registered n' stuff, we */
  2344. /* can finally initialize it to a default mode */
  2345. clgenfb_default = clgenfb_predefined[clgen_def_mode].var;
  2346. clgenfb_default.activate = FB_ACTIVATE_NOW;
  2347. clgenfb_default.yres_virtual = 480 * 3; /* for fast scrolling (YPAN-Mode) */
  2348. err = fbgen_do_set_var (&clgenfb_default, 1, &fb_info->gen);
  2349. if (err) {
  2350. DPRINTK ("EXIT, returning -EINVALn");
  2351. return -EINVAL;
  2352. }
  2353. disp.var = clgenfb_default;
  2354. fbgen_set_disp (-1, &fb_info->gen);
  2355. fbgen_install_cmap (0, &fb_info->gen);
  2356. err = register_framebuffer (&fb_info->gen.info);
  2357. if (err) {
  2358. printk (KERN_ERR "clgen: ERROR - could not register fb device; err = %d!n", err);
  2359. DPRINTK ("EXIT, returning -EINVALn");
  2360. return -EINVAL;
  2361. }
  2362. DPRINTK ("EXIT, returning 0n");
  2363. return 0;
  2364. }
  2365.     /*
  2366.      *  Cleanup (only needed for module)
  2367.      */
  2368. static void __exit clgenfb_cleanup (struct clgenfb_info *info)
  2369. {
  2370. DPRINTK ("ENTERn");
  2371. #ifdef CONFIG_ZORRO
  2372. switch_monitor (info, 0);
  2373. clgen_zorro_unmap (info);
  2374. #else
  2375. clgen_pci_unmap (info);
  2376. #endif /* CONFIG_ZORRO */
  2377. unregister_framebuffer ((struct fb_info *) info);
  2378. printk ("Framebuffer unregisteredn");
  2379. DPRINTK ("EXITn");
  2380. }
  2381. #ifndef MODULE
  2382. int __init clgenfb_setup(char *options) {
  2383. char *this_opt, s[32];
  2384. int i;
  2385. DPRINTK ("ENTERn");
  2386. if (!options || !*options)
  2387. return 0;
  2388. for (this_opt = strtok (options, ","); this_opt != NULL;
  2389.      this_opt = strtok (NULL, ",")) {
  2390. if (!*this_opt) continue;
  2391. DPRINTK("clgenfb_setup: option '%s'n", this_opt);
  2392. for (i = 0; i < NUM_TOTAL_MODES; i++) {
  2393. sprintf (s, "mode:%s", clgenfb_predefined[i].name);
  2394. if (strcmp (this_opt, s) == 0)
  2395. clgen_def_mode = i;
  2396. }
  2397. if (!strcmp(this_opt, "noaccel"))
  2398. noaccel = 1;
  2399. }
  2400. return 0;
  2401. }
  2402. #endif
  2403.     /*
  2404.      *  Modularization
  2405.      */
  2406. MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>");
  2407. MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
  2408. MODULE_LICENSE("GPL");
  2409. static void __exit clgenfb_exit (void)
  2410. {
  2411. DPRINTK ("ENTERn");
  2412. clgenfb_cleanup (&boards[0]); /* FIXME: support multiple boards */
  2413. DPRINTK ("EXITn");
  2414. }
  2415. #ifdef MODULE
  2416. module_init(clgenfb_init);
  2417. #endif
  2418. module_exit(clgenfb_exit);
  2419. /**********************************************************************/
  2420. /* about the following functions - I have used the same names for the */
  2421. /* functions as Markus Wild did in his Retina driver for NetBSD as    */
  2422. /* they just made sense for this purpose. Apart from that, I wrote    */
  2423. /* these functions myself.                                            */
  2424. /**********************************************************************/
  2425. /*** WGen() - write into one of the external/general registers ***/
  2426. static void WGen (const struct clgenfb_info *fb_info,
  2427.   int regnum, unsigned char val)
  2428. {
  2429. unsigned long regofs = 0;
  2430. if (fb_info->btype == BT_PICASSO) {
  2431. /* Picasso II specific hack */
  2432. /*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
  2433. if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
  2434. regofs = 0xfff;
  2435. }
  2436. vga_w (fb_info->regs, regofs + regnum, val);
  2437. }
  2438. /*** RGen() - read out one of the external/general registers ***/
  2439. static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum)
  2440. {
  2441. unsigned long regofs = 0;
  2442. if (fb_info->btype == BT_PICASSO) {
  2443. /* Picasso II specific hack */
  2444. /*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
  2445. if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
  2446. regofs = 0xfff;
  2447. }
  2448. return vga_r (fb_info->regs, regofs + regnum);
  2449. }
  2450. /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
  2451. static void AttrOn (const struct clgenfb_info *fb_info)
  2452. {
  2453. assert (fb_info != NULL);
  2454. DPRINTK ("ENTERn");
  2455. if (vga_rcrt (fb_info->regs, CL_CRT24) & 0x80) {
  2456. /* if we're just in "write value" mode, write back the */
  2457. /* same value as before to not modify anything */
  2458. vga_w (fb_info->regs, VGA_ATT_IW,
  2459.        vga_r (fb_info->regs, VGA_ATT_R));
  2460. }
  2461. /* turn on video bit */
  2462. /*      vga_w (fb_info->regs, VGA_ATT_IW, 0x20); */
  2463. vga_w (fb_info->regs, VGA_ATT_IW, 0x33);
  2464. /* dummy write on Reg0 to be on "write index" mode next time */
  2465. vga_w (fb_info->regs, VGA_ATT_IW, 0x00);
  2466. DPRINTK ("EXITn");
  2467. }
  2468. /*** WHDR() - write into the Hidden DAC register ***/
  2469. /* as the HDR is the only extension register that requires special treatment
  2470.  * (the other extension registers are accessible just like the "ordinary"
  2471.  * registers of their functional group) here is a specialized routine for
  2472.  * accessing the HDR
  2473.  */
  2474. static void WHDR (const struct clgenfb_info *fb_info, unsigned char val)
  2475. {
  2476. unsigned char dummy;
  2477. if (fb_info->btype == BT_PICASSO) {
  2478. /* Klaus' hint for correct access to HDR on some boards */
  2479. /* first write 0 to pixel mask (3c6) */
  2480. WGen (fb_info, VGA_PEL_MSK, 0x00);
  2481. udelay (200);
  2482. /* next read dummy from pixel address (3c8) */
  2483. dummy = RGen (fb_info, VGA_PEL_IW);
  2484. udelay (200);
  2485. }
  2486. /* now do the usual stuff to access the HDR */
  2487. dummy = RGen (fb_info, VGA_PEL_MSK);
  2488. udelay (200);
  2489. dummy = RGen (fb_info, VGA_PEL_MSK);
  2490. udelay (200);
  2491. dummy = RGen (fb_info, VGA_PEL_MSK);
  2492. udelay (200);
  2493. dummy = RGen (fb_info, VGA_PEL_MSK);
  2494. udelay (200);
  2495. WGen (fb_info, VGA_PEL_MSK, val);
  2496. udelay (200);
  2497. if (fb_info->btype == BT_PICASSO) {
  2498. /* now first reset HDR access counter */
  2499. dummy = RGen (fb_info, VGA_PEL_IW);
  2500. udelay (200);
  2501. /* and at the end, restore the mask value */
  2502. /* ## is this mask always 0xff? */
  2503. WGen (fb_info, VGA_PEL_MSK, 0xff);
  2504. udelay (200);
  2505. }
  2506. }
  2507. /*** WSFR() - write to the "special function register" (SFR) ***/
  2508. static void WSFR (struct clgenfb_info *fb_info, unsigned char val)
  2509. {
  2510. #ifdef CONFIG_ZORRO
  2511. assert (fb_info->regs != NULL);
  2512. fb_info->SFR = val;
  2513. z_writeb (val, fb_info->regs + 0x8000);
  2514. #endif
  2515. }
  2516. /* The Picasso has a second register for switching the monitor bit */
  2517. static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val)
  2518. {
  2519. #ifdef CONFIG_ZORRO
  2520. /* writing an arbitrary value to this one causes the monitor switcher */
  2521. /* to flip to Amiga display */
  2522. assert (fb_info->regs != NULL);
  2523. fb_info->SFR = val;
  2524. z_writeb (val, fb_info->regs + 0x9000);
  2525. #endif
  2526. }
  2527. /*** WClut - set CLUT entry (range: 0..63) ***/
  2528. static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
  2529.     unsigned char green, unsigned char blue)
  2530. {
  2531. unsigned int data = VGA_PEL_D;
  2532. /* address write mode register is not translated.. */
  2533. vga_w (fb_info->regs, VGA_PEL_IW, regnum);
  2534. if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
  2535.     fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
  2536. /* but DAC data register IS, at least for Picasso II */
  2537. if (fb_info->btype == BT_PICASSO)
  2538. data += 0xfff;
  2539. vga_w (fb_info->regs, data, red);
  2540. vga_w (fb_info->regs, data, green);
  2541. vga_w (fb_info->regs, data, blue);
  2542. } else {
  2543. vga_w (fb_info->regs, data, blue);
  2544. vga_w (fb_info->regs, data, green);
  2545. vga_w (fb_info->regs, data, red);
  2546. }
  2547. }
  2548. #if 0
  2549. /*** RClut - read CLUT entry (range 0..63) ***/
  2550. static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
  2551.     unsigned char *green, unsigned char *blue)
  2552. {
  2553. unsigned int data = VGA_PEL_D;
  2554. vga_w (fb_info->regs, VGA_PEL_IR, regnum);
  2555. if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
  2556.     fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
  2557. if (fb_info->btype == BT_PICASSO)
  2558. data += 0xfff;
  2559. *red = vga_r (fb_info->regs, data);
  2560. *green = vga_r (fb_info->regs, data);
  2561. *blue = vga_r (fb_info->regs, data);
  2562. } else {
  2563. *blue = vga_r (fb_info->regs, data);
  2564. *green = vga_r (fb_info->regs, data);
  2565. *red = vga_r (fb_info->regs, data);
  2566. }
  2567. }
  2568. #endif
  2569. /*******************************************************************
  2570. clgen_WaitBLT()
  2571. Wait for the BitBLT engine to complete a possible earlier job
  2572. *********************************************************************/
  2573. /* FIXME: use interrupts instead */
  2574. static inline void clgen_WaitBLT (caddr_t regbase)
  2575. {
  2576. /* now busy-wait until we're done */
  2577. while (vga_rgfx (regbase, CL_GR31) & 0x08)
  2578. /* do nothing */ ;
  2579. }
  2580. /*******************************************************************
  2581. clgen_BitBLT()
  2582. perform accelerated "scrolling"
  2583. ********************************************************************/
  2584. static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, u_short destx, u_short desty,
  2585.    u_short width, u_short height, u_short line_length)
  2586. {
  2587. u_short nwidth, nheight;
  2588. u_long nsrc, ndest;
  2589. u_char bltmode;
  2590. DPRINTK ("ENTERn");
  2591. nwidth = width - 1;
  2592. nheight = height - 1;
  2593. bltmode = 0x00;
  2594. /* if source adr < dest addr, do the Blt backwards */
  2595. if (cury <= desty) {
  2596. if (cury == desty) {
  2597. /* if src and dest are on the same line, check x */
  2598. if (curx < destx)
  2599. bltmode |= 0x01;
  2600. } else
  2601. bltmode |= 0x01;
  2602. }
  2603. if (!bltmode) {
  2604. /* standard case: forward blitting */
  2605. nsrc = (cury * line_length) + curx;
  2606. ndest = (desty * line_length) + destx;
  2607. } else {
  2608. /* this means start addresses are at the end, counting backwards */
  2609. nsrc = cury * line_length + curx + nheight * line_length + nwidth;
  2610. ndest = desty * line_length + destx + nheight * line_length + nwidth;
  2611. }
  2612.         clgen_WaitBLT(regbase);
  2613. /*
  2614.    run-down of registers to be programmed:
  2615.    destination pitch
  2616.    source pitch
  2617.    BLT width/height
  2618.    source start
  2619.    destination start
  2620.    BLT mode
  2621.    BLT ROP
  2622.    VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
  2623.    start/stop
  2624.  */
  2625. /* pitch: set to line_length */
  2626. vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */
  2627. vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */
  2628. vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */
  2629. vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */
  2630. /* BLT width: actual number of pixels - 1 */
  2631. vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */
  2632. vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */
  2633. /* BLT height: actual number of lines -1 */
  2634. vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */
  2635. vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */
  2636. /* BLT destination */
  2637. vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
  2638. vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
  2639. vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
  2640. /* BLT source */
  2641. vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff)); /* BLT src low */
  2642. vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8)); /* BLT src mid */
  2643. vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16)); /* BLT src hi */
  2644. /* BLT mode */
  2645. vga_wgfx (regbase, CL_GR30, bltmode); /* BLT mode */
  2646. /* BLT ROP: SrcCopy */
  2647. vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */
  2648. /* and finally: GO! */
  2649. vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */
  2650. DPRINTK ("EXITn");
  2651. }
  2652. /*******************************************************************
  2653. clgen_RectFill()
  2654. perform accelerated rectangle fill
  2655. ********************************************************************/
  2656. static void clgen_RectFill (struct clgenfb_info *fb_info,
  2657.      u_short x, u_short y, u_short width, u_short height,
  2658.      u_char color, u_short line_length)
  2659. {
  2660. u_short nwidth, nheight;
  2661. u_long ndest;
  2662. u_char op;
  2663. DPRINTK ("ENTERn");
  2664. nwidth = width - 1;
  2665. nheight = height - 1;
  2666. ndest = (y * line_length) + x;
  2667.         clgen_WaitBLT(fb_info->regs);
  2668. /* pitch: set to line_length */
  2669. vga_wgfx (fb_info->regs, CL_GR24, line_length & 0xff); /* dest pitch low */
  2670. vga_wgfx (fb_info->regs, CL_GR25, (line_length >> 8)); /* dest pitch hi */
  2671. vga_wgfx (fb_info->regs, CL_GR26, line_length & 0xff); /* source pitch low */
  2672. vga_wgfx (fb_info->regs, CL_GR27, (line_length >> 8)); /* source pitch hi */
  2673. /* BLT width: actual number of pixels - 1 */
  2674. vga_wgfx (fb_info->regs, CL_GR20, nwidth & 0xff); /* BLT width low */
  2675. vga_wgfx (fb_info->regs, CL_GR21, (nwidth >> 8)); /* BLT width hi */
  2676. /* BLT height: actual number of lines -1 */
  2677. vga_wgfx (fb_info->regs, CL_GR22, nheight & 0xff); /* BLT height low */
  2678. vga_wgfx (fb_info->regs, CL_GR23, (nheight >> 8)); /* BLT width hi */
  2679. /* BLT destination */
  2680. vga_wgfx (fb_info->regs, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */
  2681. vga_wgfx (fb_info->regs, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */
  2682. vga_wgfx (fb_info->regs, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */
  2683. /* BLT source: set to 0 (is a dummy here anyway) */
  2684. vga_wgfx (fb_info->regs, CL_GR2C, 0x00); /* BLT src low */
  2685. vga_wgfx (fb_info->regs, CL_GR2D, 0x00); /* BLT src mid */
  2686. vga_wgfx (fb_info->regs, CL_GR2E, 0x00); /* BLT src hi */
  2687. /* This is a ColorExpand Blt, using the */
  2688. /* same color for foreground and background */
  2689. vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, color); /* foreground color */
  2690. vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, color); /* background color */
  2691. op = 0xc0;
  2692. if (fb_info->currentmode.var.bits_per_pixel == 16) {
  2693. vga_wgfx (fb_info->regs, CL_GR10, color); /* foreground color */
  2694. vga_wgfx (fb_info->regs, CL_GR11, color); /* background color */
  2695. op = 0x50;
  2696. op = 0xd0;
  2697. } else if (fb_info->currentmode.var.bits_per_pixel == 32) {
  2698. vga_wgfx (fb_info->regs, CL_GR10, color); /* foreground color */
  2699. vga_wgfx (fb_info->regs, CL_GR11, color); /* background color */
  2700. vga_wgfx (fb_info->regs, CL_GR12, color); /* foreground color */
  2701. vga_wgfx (fb_info->regs, CL_GR13, color); /* background color */
  2702. vga_wgfx (fb_info->regs, CL_GR14, 0); /* foreground color */
  2703. vga_wgfx (fb_info->regs, CL_GR15, 0); /* background color */
  2704. op = 0x50;
  2705. op = 0xf0;
  2706. }
  2707. /* BLT mode: color expand, Enable 8x8 copy (faster?) */
  2708. vga_wgfx (fb_info->regs, CL_GR30, op); /* BLT mode */
  2709. /* BLT ROP: SrcCopy */
  2710. vga_wgfx (fb_info->regs, CL_GR32, 0x0d); /* BLT ROP */
  2711. /* and finally: GO! */
  2712. vga_wgfx (fb_info->regs, CL_GR31, 0x02); /* BLT Start/status */
  2713. DPRINTK ("EXITn");
  2714. }
  2715. /**************************************************************************
  2716.  * bestclock() - determine closest possible clock lower(?) than the
  2717.  * desired pixel clock
  2718.  **************************************************************************/
  2719. static void bestclock (long freq, long *best, long *nom,
  2720.        long *den, long *div, long maxfreq)
  2721. {
  2722. long n, h, d, f;
  2723. assert (best != NULL);
  2724. assert (nom != NULL);
  2725. assert (den != NULL);
  2726. assert (div != NULL);
  2727. assert (maxfreq > 0);
  2728. *nom = 0;
  2729. *den = 0;
  2730. *div = 0;
  2731. DPRINTK ("ENTERn");
  2732. if (freq < 8000)
  2733. freq = 8000;
  2734. if (freq > maxfreq)
  2735. freq = maxfreq;
  2736. *best = 0;
  2737. f = freq * 10;
  2738. for (n = 32; n < 128; n++) {
  2739. d = (143181 * n) / f;
  2740. if ((d >= 7) && (d <= 63)) {
  2741. if (d > 31)
  2742. d = (d / 2) * 2;
  2743. h = (14318 * n) / d;
  2744. if (abs (h - freq) < abs (*best - freq)) {
  2745. *best = h;
  2746. *nom = n;
  2747. if (d < 32) {
  2748. *den = d;
  2749. *div = 0;
  2750. } else {
  2751. *den = d / 2;
  2752. *div = 1;
  2753. }
  2754. }
  2755. }
  2756. d = ((143181 * n) + f - 1) / f;
  2757. if ((d >= 7) && (d <= 63)) {
  2758. if (d > 31)
  2759. d = (d / 2) * 2;
  2760. h = (14318 * n) / d;
  2761. if (abs (h - freq) < abs (*best - freq)) {
  2762. *best = h;
  2763. *nom = n;
  2764. if (d < 32) {
  2765. *den = d;
  2766. *div = 0;
  2767. } else {
  2768. *den = d / 2;
  2769. *div = 1;
  2770. }
  2771. }
  2772. }
  2773. }
  2774. DPRINTK ("Best possible values for given frequency:n");
  2775. DPRINTK ("        best: %ld kHz  nom: %ld  den: %ld  div: %ldn",
  2776.  freq, *nom, *den, *div);
  2777. DPRINTK ("EXITn");
  2778. }
  2779. /* -------------------------------------------------------------------------
  2780.  *
  2781.  * debugging functions
  2782.  *
  2783.  * -------------------------------------------------------------------------
  2784.  */
  2785. #ifdef CLGEN_DEBUG
  2786. /**
  2787.  * clgen_dbg_print_byte
  2788.  * @name: name associated with byte value to be displayed
  2789.  * @val: byte value to be displayed
  2790.  *
  2791.  * DESCRIPTION:
  2792.  * Display an indented string, along with a hexidecimal byte value, and
  2793.  * its decoded bits.  Bits 7 through 0 are listed in left-to-right
  2794.  * order.
  2795.  */
  2796. static
  2797. void clgen_dbg_print_byte (const char *name, unsigned char val)
  2798. {
  2799. DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)n",
  2800.  name, val,
  2801.  val & 0x80 ? '1' : '0',
  2802.  val & 0x40 ? '1' : '0',
  2803.  val & 0x20 ? '1' : '0',
  2804.  val & 0x10 ? '1' : '0',
  2805.  val & 0x08 ? '1' : '0',
  2806.  val & 0x04 ? '1' : '0',
  2807.  val & 0x02 ? '1' : '0',
  2808.  val & 0x01 ? '1' : '0');
  2809. }
  2810. /**
  2811.  * clgen_dbg_print_regs
  2812.  * @base: If using newmmio, the newmmio base address, otherwise %NULL
  2813.  * @reg_class: type of registers to read: %CRT, or %SEQ
  2814.  *
  2815.  * DESCRIPTION:
  2816.  * Dumps the given list of VGA CRTC registers.  If @base is %NULL,
  2817.  * old-style I/O ports are queried for information, otherwise MMIO is
  2818.  * used at the given @base address to query the information.
  2819.  */
  2820. static
  2821. void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...)
  2822. {
  2823. va_list list;
  2824. unsigned char val = 0;
  2825. unsigned reg;
  2826. char *name;
  2827. va_start (list, reg_class);
  2828. name = va_arg (list, char *);
  2829. while (name != NULL) {
  2830. reg = va_arg (list, int);
  2831. switch (reg_class) {
  2832. case CRT:
  2833. val = vga_rcrt (regbase, (unsigned char) reg);
  2834. break;
  2835. case SEQ:
  2836. val = vga_rseq (regbase, (unsigned char) reg);
  2837. break;
  2838. default:
  2839. /* should never occur */
  2840. assert (FALSE);
  2841. break;
  2842. }
  2843. clgen_dbg_print_byte (name, val);
  2844. name = va_arg (list, char *);
  2845. }
  2846. va_end (list);
  2847. }
  2848. /**
  2849.  * clgen_dump
  2850.  * @clgeninfo:
  2851.  *
  2852.  * DESCRIPTION:
  2853.  */
  2854. static
  2855. void clgen_dump (void)
  2856. {
  2857. clgen_dbg_reg_dump (NULL);
  2858. }
  2859. /**
  2860.  * clgen_dbg_reg_dump
  2861.  * @base: If using newmmio, the newmmio base address, otherwise %NULL
  2862.  *
  2863.  * DESCRIPTION:
  2864.  * Dumps a list of interesting VGA and CLGEN registers.  If @base is %NULL,
  2865.  * old-style I/O ports are queried for information, otherwise MMIO is
  2866.  * used at the given @base address to query the information.
  2867.  */
  2868. static
  2869. void clgen_dbg_reg_dump (caddr_t regbase)
  2870. {
  2871. DPRINTK ("CLGEN VGA CRTC register dump:n");
  2872. clgen_dbg_print_regs (regbase, CRT,
  2873.    "CR00", 0x00,
  2874.    "CR01", 0x01,
  2875.    "CR02", 0x02,
  2876.    "CR03", 0x03,
  2877.    "CR04", 0x04,
  2878.    "CR05", 0x05,
  2879.    "CR06", 0x06,
  2880.    "CR07", 0x07,
  2881.    "CR08", 0x08,
  2882.    "CR09", 0x09,
  2883.    "CR0A", 0x0A,
  2884.    "CR0B", 0x0B,
  2885.    "CR0C", 0x0C,
  2886.    "CR0D", 0x0D,
  2887.    "CR0E", 0x0E,
  2888.    "CR0F", 0x0F,
  2889.    "CR10", 0x10,
  2890.    "CR11", 0x11,
  2891.    "CR12", 0x12,
  2892.    "CR13", 0x13,
  2893.    "CR14", 0x14,
  2894.    "CR15", 0x15,
  2895.    "CR16", 0x16,
  2896.    "CR17", 0x17,
  2897.    "CR18", 0x18,
  2898.    "CR22", 0x22,
  2899.    "CR24", 0x24,
  2900.    "CR26", 0x26,
  2901.    "CR2D", 0x2D,
  2902.    "CR2E", 0x2E,
  2903.    "CR2F", 0x2F,
  2904.    "CR30", 0x30,
  2905.    "CR31", 0x31,
  2906.    "CR32", 0x32,
  2907.    "CR33", 0x33,
  2908.    "CR34", 0x34,
  2909.    "CR35", 0x35,
  2910.    "CR36", 0x36,
  2911.    "CR37", 0x37,
  2912.    "CR38", 0x38,
  2913.    "CR39", 0x39,
  2914.    "CR3A", 0x3A,
  2915.    "CR3B", 0x3B,
  2916.    "CR3C", 0x3C,
  2917.    "CR3D", 0x3D,
  2918.    "CR3E", 0x3E,
  2919.    "CR3F", 0x3F,
  2920.    NULL);
  2921. DPRINTK ("n");
  2922. DPRINTK ("CLGEN VGA SEQ register dump:n");
  2923. clgen_dbg_print_regs (regbase, SEQ,
  2924.    "SR00", 0x00,
  2925.    "SR01", 0x01,
  2926.    "SR02", 0x02,
  2927.    "SR03", 0x03,
  2928.    "SR04", 0x04,
  2929.    "SR08", 0x08,
  2930.    "SR09", 0x09,
  2931.    "SR0A", 0x0A,
  2932.    "SR0B", 0x0B,
  2933.    "SR0D", 0x0D,
  2934.    "SR10", 0x10,
  2935.    "SR11", 0x11,
  2936.    "SR12", 0x12,
  2937.    "SR13", 0x13,
  2938.    "SR14", 0x14,
  2939.    "SR15", 0x15,
  2940.    "SR16", 0x16,
  2941.    "SR17", 0x17,
  2942.    "SR18", 0x18,
  2943.    "SR19", 0x19,
  2944.    "SR1A", 0x1A,
  2945.    "SR1B", 0x1B,
  2946.    "SR1C", 0x1C,
  2947.    "SR1D", 0x1D,
  2948.    "SR1E", 0x1E,
  2949.    "SR1F", 0x1F,
  2950.    NULL);
  2951. DPRINTK ("n");
  2952. }
  2953. #endif /* CLGEN_DEBUG */