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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/video/tgafb.c -- DEC 21030 TGA frame buffer device
  3.  *
  4.  * Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha
  5.  *  
  6.  *  $Id: tgafb.c,v 1.12.2.3 2000/04/04 06:44:56 mato Exp $
  7.  *
  8.  *  This driver is partly based on the original TGA framebuffer device, which 
  9.  *  was partly based on the original TGA console driver, which are
  10.  *
  11.  * Copyright (C) 1997 Geert Uytterhoeven
  12.  * Copyright (C) 1995 Jay Estabrook
  13.  *
  14.  *  This file is subject to the terms and conditions of the GNU General Public
  15.  *  License. See the file COPYING in the main directory of this archive for
  16.  *  more details.
  17.  */
  18. /* KNOWN PROBLEMS/TO DO ===================================================== *
  19.  *
  20.  * - How to set a single color register on 24-plane cards?
  21.  *
  22.  * - Hardware cursor/other text acceleration methods
  23.  *
  24.  * - Some redraws can stall kernel for several seconds
  25.  *   [This should now be solved by the fast memmove() patch in 2.3.6]
  26.  *
  27.  * KNOWN PROBLEMS/TO DO ==================================================== */
  28. #include <linux/module.h>
  29. #include <linux/sched.h>
  30. #include <linux/kernel.h>
  31. #include <linux/errno.h>
  32. #include <linux/string.h>
  33. #include <linux/mm.h>
  34. #include <linux/tty.h>
  35. #include <linux/slab.h>
  36. #include <linux/vmalloc.h>
  37. #include <linux/delay.h>
  38. #include <linux/interrupt.h>
  39. #include <linux/fb.h>
  40. #include <linux/init.h>
  41. #include <linux/pci.h>
  42. #include <linux/selection.h>
  43. #include <linux/console.h>
  44. #include <asm/io.h>
  45. #include <video/fbcon.h>
  46. #include <video/fbcon-cfb8.h>
  47. #include <video/fbcon-cfb32.h>
  48. #include "tgafb.h"
  49.     /*
  50.      *  Global declarations
  51.      */
  52. static struct tgafb_info fb_info;
  53. static struct tgafb_par current_par;
  54. static int current_par_valid = 0;
  55. static struct display disp;
  56. static char default_fontname[40] __initdata = { 0 };
  57. static struct fb_var_screeninfo default_var;
  58. static int default_var_valid = 0;
  59. static int currcon = 0;
  60. static struct { u_char red, green, blue, pad; } palette[256];
  61. #ifdef FBCON_HAS_CFB32
  62. static u32 fbcon_cfb32_cmap[16];
  63. #endif
  64.     /*
  65.      *  Hardware presets
  66.      */
  67. static unsigned int fb_offset_presets[4] = {
  68. TGA_8PLANE_FB_OFFSET,
  69. TGA_24PLANE_FB_OFFSET,
  70. 0xffffffff,
  71. TGA_24PLUSZ_FB_OFFSET
  72. };
  73. static unsigned int deep_presets[4] = {
  74.   0x00014000,
  75.   0x0001440d,
  76.   0xffffffff,
  77.   0x0001441d
  78. };
  79. static unsigned int rasterop_presets[4] = {
  80.   0x00000003,
  81.   0x00000303,
  82.   0xffffffff,
  83.   0x00000303
  84. };
  85. static unsigned int mode_presets[4] = {
  86.   0x00002000,
  87.   0x00002300,
  88.   0xffffffff,
  89.   0x00002300
  90. };
  91. static unsigned int base_addr_presets[4] = {
  92.   0x00000000,
  93.   0x00000001,
  94.   0xffffffff,
  95.   0x00000001
  96. };
  97.     /*
  98.      *  Predefined video modes
  99.      *  This is a subset of the standard VESA modes, recalculated from XFree86.
  100.      *
  101.      *  XXX Should we store these in terms of the encoded par structs? Even better,
  102.      *      fbcon should provide a general mechanism for doing something like this.
  103.      */
  104. static struct {
  105.     const char *name;
  106.     struct fb_var_screeninfo var;
  107. } tgafb_predefined[] __initdata = {
  108.     { "640x480-60", {
  109. 640, 480, 640, 480, 0, 0, 0, 0,
  110. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  111. 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
  112. 0,
  113. FB_VMODE_NONINTERLACED
  114.     }},
  115.     { "800x600-56", {
  116. 800, 600, 800, 600, 0, 0, 0, 0,
  117. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  118. 0, 0, -1, -1, FB_ACCELF_TEXT, 27777, 128, 24, 22, 1, 72, 2,
  119. 0,
  120. FB_VMODE_NONINTERLACED
  121.     }},
  122.     { "640x480-72", {
  123. 640, 480, 640, 480, 0, 0, 0, 0,
  124. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  125. 0, 0, -1, -1, FB_ACCELF_TEXT, 31746, 144, 40, 30, 8, 40, 3,
  126. 0,
  127. FB_VMODE_NONINTERLACED
  128.     }},
  129.     { "800x600-60", {
  130. 800, 600, 800, 600, 0, 0, 0, 0,
  131. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  132. 0, 0, -1, -1, FB_ACCELF_TEXT, 25000, 88, 40, 23, 1, 128, 4,
  133. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
  134. FB_VMODE_NONINTERLACED
  135.     }},
  136.     { "800x600-72", {
  137. 800, 600, 800, 600, 0, 0, 0, 0,
  138. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  139. 0, 0, -1, -1, FB_ACCELF_TEXT, 20000, 64, 56, 23, 37, 120, 6,
  140. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
  141. FB_VMODE_NONINTERLACED
  142.     }},
  143.     { "1024x768-60", {
  144. 1024, 768, 1024, 768, 0, 0, 0, 0,
  145. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  146. 0, 0, -1, -1, FB_ACCELF_TEXT, 15384, 168, 8, 29, 3, 144, 6,
  147. 0,
  148. FB_VMODE_NONINTERLACED
  149.     }},
  150.     { "1152x864-60", {
  151. 1152, 864, 1152, 864, 0, 0, 0, 0,
  152. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  153. 0, 0, -1, -1, FB_ACCELF_TEXT, 11123, 208, 64, 16, 4, 256, 8,
  154. 0,
  155. FB_VMODE_NONINTERLACED
  156.     }},
  157.     { "1024x768-70", {
  158. 1024, 768, 1024, 768, 0, 0, 0, 0,
  159. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  160. 0, 0, -1, -1, FB_ACCELF_TEXT, 13333, 144, 24, 29, 3, 136, 6,
  161. 0,
  162. FB_VMODE_NONINTERLACED
  163.     }},
  164.     { "1024x768-76", {
  165. 1024, 768, 1024, 768, 0, 0, 0, 0,
  166. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  167. 0, 0, -1, -1, FB_ACCELF_TEXT, 11764, 208, 8, 36, 16, 120, 3,
  168. 0,
  169. FB_VMODE_NONINTERLACED
  170.     }},
  171.     { "1152x864-70", {
  172. 1152, 864, 1152, 864, 0, 0, 0, 0,
  173. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  174. 0, 0, -1, -1, FB_ACCELF_TEXT, 10869, 106, 56, 20, 1, 160, 10,
  175. 0,
  176. FB_VMODE_NONINTERLACED
  177.     }},
  178.     { "1280x1024-61", {
  179. 1280, 1024, 1280, 1024, 0, 0, 0, 0,
  180. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  181. 0, 0, -1, -1, FB_ACCELF_TEXT, 9090, 200, 48, 26, 1, 184, 3,
  182. 0,
  183. FB_VMODE_NONINTERLACED
  184.     }},
  185.     { "1024x768-85", {
  186. 1024, 768, 1024, 768, 0, 0, 0, 0,
  187. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  188. 0, 0, -1, -1, FB_ACCELF_TEXT, 10111, 192, 32, 34, 14, 160, 6,
  189. 0,
  190. FB_VMODE_NONINTERLACED
  191.     }},
  192.     { "1280x1024-70", {
  193. 1280, 1024, 1280, 1024, 0, 0, 0, 0,
  194. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  195. 0, 0, -1, -1, FB_ACCELF_TEXT, 7905, 224, 32, 28, 8, 160, 8,
  196. 0,
  197. FB_VMODE_NONINTERLACED
  198.     }},
  199.     { "1152x864-84", {
  200. 1152, 864, 1152, 864, 0, 0, 0, 0,
  201. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  202. 0, 0, -1, -1, FB_ACCELF_TEXT, 7407, 184, 312, 32, 0, 128, 12,
  203. 0,
  204. FB_VMODE_NONINTERLACED
  205.     }},
  206.     { "1280x1024-76", {
  207. 1280, 1024, 1280, 1024, 0, 0, 0, 0,
  208. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  209. 0, 0, -1, -1, FB_ACCELF_TEXT, 7407, 248, 32, 34, 3, 104, 3,
  210. 0,
  211. FB_VMODE_NONINTERLACED
  212.     }},
  213.     { "1280x1024-85", {
  214. 1280, 1024, 1280, 1024, 0, 0, 0, 0,
  215. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  216. 0, 0, -1, -1, FB_ACCELF_TEXT, 6349, 224, 64, 44, 1, 160, 3,
  217. 0,
  218. FB_VMODE_NONINTERLACED
  219.     }},
  220.     /* These are modes used by the two fixed-frequency monitors I have at home. 
  221.      * You may or may not find these useful.
  222.      */
  223.     { "WYSE1", { /* 1280x1024 @ 72 Hz, 130 Mhz clock */
  224. 1280, 1024, 1280, 1024, 0, 0, 0, 0,
  225. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  226. 0, 0, -1, -1, FB_ACCELF_TEXT, 7692, 192, 32, 47, 0, 192, 5,
  227. FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
  228. FB_VMODE_NONINTERLACED
  229.     }},
  230.     { "IBM3", { /* 1280x1024 @ 70 Hz, 120 Mhz clock */
  231. 1280, 1024, 1280, 1024, 0, 0, 0, 0,
  232. {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  233. 0, 0, -1, -1, FB_ACCELF_TEXT, 8333, 192, 32, 47, 0, 192, 5,
  234. 0,
  235. FB_VMODE_NONINTERLACED
  236.     }}
  237. };
  238. #define NUM_TOTAL_MODES    ARRAY_SIZE(tgafb_predefined)
  239.     /*
  240.      *  Interface used by the world
  241.      */
  242. static void tgafb_detect(void);
  243. static int tgafb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
  244.         struct fb_info_gen *info);
  245. static int tgafb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
  246.         struct fb_info_gen *info);
  247. static int tgafb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
  248.         struct fb_info_gen *info);
  249. static void tgafb_get_par(void *fb_par, struct fb_info_gen *info);
  250. static void tgafb_set_par(const void *fb_par, struct fb_info_gen *info);
  251. static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, 
  252. u_int *transp, struct fb_info *info);
  253. static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 
  254. u_int transp, struct fb_info *info);
  255. static int tgafb_blank(int blank, struct fb_info_gen *info);
  256. static void tgafb_set_disp(const void *fb_par, struct display *disp, 
  257. struct fb_info_gen *info);
  258. #ifndef MODULE
  259. int tgafb_setup(char*);
  260. #endif
  261. static void tgafb_set_pll(int f);
  262. #if 1
  263. static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  264.   struct fb_info *info);
  265. static void tgafb_update_palette(void);
  266. #endif
  267.     /*
  268.      *  Chipset specific functions
  269.      */
  270. static void tgafb_detect(void)
  271. {
  272.     return;
  273. }
  274. static int tgafb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
  275. struct fb_info_gen *info)
  276. {
  277.     struct tgafb_par *par = (struct tgafb_par *)fb_par;
  278.     strcpy(fix->id, fb_info.gen.info.modename);
  279.     fix->type = FB_TYPE_PACKED_PIXELS;
  280.     fix->type_aux = 0;
  281.     if (fb_info.tga_type == TGA_TYPE_8PLANE) {
  282. fix->visual = FB_VISUAL_PSEUDOCOLOR;
  283.     } else {
  284. fix->visual = FB_VISUAL_TRUECOLOR;
  285.     }
  286.     fix->line_length = par->xres * (par->bits_per_pixel >> 3);
  287.     fix->smem_start = fb_info.tga_fb_base;
  288.     fix->smem_len = fix->line_length * par->yres;
  289.     fix->mmio_start = fb_info.tga_regs_base;
  290.     fix->mmio_len = 0x1000; /* Is this sufficient? */
  291.     fix->xpanstep = fix->ypanstep = fix->ywrapstep = 0;
  292.     fix->accel = FB_ACCEL_DEC_TGA;
  293.     return 0;
  294. }
  295. static int tgafb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
  296. struct fb_info_gen *info)
  297. {
  298.     struct tgafb_par *par = (struct tgafb_par *)fb_par;
  299.     /* round up some */
  300.     if (fb_info.tga_type == TGA_TYPE_8PLANE) {
  301. if (var->bits_per_pixel > 8) {
  302.     return -EINVAL;
  303. }
  304. par->bits_per_pixel = 8;
  305.     } else {
  306. if (var->bits_per_pixel > 32) {
  307.     return -EINVAL;
  308. }
  309. par->bits_per_pixel = 32;
  310.     }
  311.     /* check the values for sanity */
  312.     if (var->xres_virtual != var->xres ||
  313. var->yres_virtual != var->yres ||
  314. var->nonstd || (1000000000/var->pixclock) > TGA_PLL_MAX_FREQ ||
  315. (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED
  316. #if 0 /* fbmon not done.  uncomment for 2.5.x -brad */
  317. || !fbmon_valid_timings(var->pixclock, var->htotal, var->vtotal, info))
  318. #else
  319. )
  320. #endif
  321. return -EINVAL;
  322.     /* encode video timings */
  323.     par->htimings = ((var->xres/4) & TGA_HORIZ_ACT_LSB) | 
  324. (((var->xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB);
  325.     par->vtimings = (var->yres & TGA_VERT_ACTIVE);
  326.     par->htimings |= ((var->right_margin/4) << 9) & TGA_HORIZ_FP;
  327.     par->vtimings |= (var->lower_margin << 11) & TGA_VERT_FP;
  328.     par->htimings |= ((var->hsync_len/4) << 14) & TGA_HORIZ_SYNC;
  329.     par->vtimings |= (var->vsync_len << 16) & TGA_VERT_SYNC;
  330.     par->htimings |= ((var->left_margin/4) << 21) & TGA_HORIZ_BP;
  331.     par->vtimings |= (var->upper_margin << 22) & TGA_VERT_BP;
  332.     if (var->sync & FB_SYNC_HOR_HIGH_ACT)
  333. par->htimings |= TGA_HORIZ_POLARITY;
  334.     if (var->sync & FB_SYNC_VERT_HIGH_ACT)
  335. par->vtimings |= TGA_VERT_POLARITY;
  336.     if (var->sync & FB_SYNC_ON_GREEN) {
  337. par->sync_on_green = 1;
  338.     } else {
  339. par->sync_on_green = 0;
  340.     }
  341.     /* store other useful values in par */
  342.     par->xres = var->xres; 
  343.     par->yres = var->yres;
  344.     par->pll_freq = 1000000000/var->pixclock;
  345.     par->bits_per_pixel = var->bits_per_pixel;
  346.     return 0;
  347. }
  348. static int tgafb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
  349. struct fb_info_gen *info)
  350. {
  351.     struct tgafb_par *par = (struct tgafb_par *)fb_par;
  352.     /* decode video timings */
  353.     var->xres = ((par->htimings & TGA_HORIZ_ACT_LSB) | ((par->htimings & TGA_HORIZ_ACT_MSB) >> 19)) * 4;
  354.     var->yres = (par->vtimings & TGA_VERT_ACTIVE);
  355.     var->right_margin = ((par->htimings & TGA_HORIZ_FP) >> 9) * 4;
  356.     var->lower_margin = ((par->vtimings & TGA_VERT_FP) >> 11);
  357.     var->hsync_len = ((par->htimings & TGA_HORIZ_SYNC) >> 14) * 4;
  358.     var->vsync_len = ((par->vtimings & TGA_VERT_SYNC) >> 16);
  359.     var->left_margin = ((par->htimings & TGA_HORIZ_BP) >> 21) * 4;
  360.     var->upper_margin = ((par->vtimings & TGA_VERT_BP) >> 22);
  361.     if (par->htimings & TGA_HORIZ_POLARITY) 
  362.      var->sync |= FB_SYNC_HOR_HIGH_ACT;
  363.     if (par->vtimings & TGA_VERT_POLARITY)
  364.      var->sync |= FB_SYNC_VERT_HIGH_ACT;
  365.     if (par->sync_on_green == 1)
  366. var->sync |= FB_SYNC_ON_GREEN;
  367.     var->xres_virtual = var->xres;
  368.     var->yres_virtual = var->yres;
  369.     var->xoffset = var->yoffset = 0;
  370.     /* depth-related */
  371.     if (fb_info.tga_type == TGA_TYPE_8PLANE) {
  372. var->red.offset = 0;
  373. var->green.offset = 0;
  374. var->blue.offset = 0;
  375.     } else {
  376. var->red.offset = 16;
  377. var->green.offset = 8;
  378. var->blue.offset = 0;
  379.     }
  380.     var->bits_per_pixel = par->bits_per_pixel;
  381.     var->grayscale = 0;
  382.     var->red.length = var->green.length = var->blue.length = 8;
  383.     var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
  384.     var->transp.offset = var->transp.length = var->transp.msb_right = 0;
  385.     /* others */
  386.     var->xoffset = var->yoffset = 0;
  387.     var->pixclock = 1000000000/par->pll_freq;
  388.     var->nonstd = 0;
  389.     var->activate = 0;
  390.     var->height = var->width = -1;
  391.     var->accel_flags = 0;
  392.     return 0;
  393. }
  394. static void tgafb_get_par(void *fb_par, struct fb_info_gen *info)
  395. {
  396.     struct tgafb_par *par = (struct tgafb_par *)fb_par;
  397.     if (current_par_valid)
  398. *par = current_par;
  399.     else {
  400. if (fb_info.tga_type == TGA_TYPE_8PLANE)
  401.     default_var.bits_per_pixel = 8;
  402. else
  403.     default_var.bits_per_pixel = 32;
  404. tgafb_decode_var(&default_var, par, info);
  405.     }
  406. }
  407. static void tgafb_set_par(const void *fb_par, struct fb_info_gen *info)
  408. {
  409.     int i, j;
  410.     struct tgafb_par *par = (struct tgafb_par *)fb_par;
  411. #if 0
  412.     /* XXX this will break console switching with X11, maybe I need to test KD_GRAPHICS? */
  413.     /* if current_par is valid, check to see if we need to change anything */
  414.     if (current_par_valid) {
  415. if (!memcmp(par, &current_par, sizeof current_par)) {
  416.     return;
  417. }
  418.     }
  419. #endif
  420.     current_par = *par;
  421.     current_par_valid = 1;
  422.     /* first, disable video */
  423.     TGA_WRITE_REG(TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
  424.     
  425.     /* write the DEEP register */
  426.     while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
  427.       continue;
  428.     mb();
  429.     TGA_WRITE_REG(deep_presets[fb_info.tga_type], TGA_DEEP_REG);
  430.     while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
  431. continue;
  432.     mb();
  433.     /* write some more registers */
  434.     TGA_WRITE_REG(rasterop_presets[fb_info.tga_type], TGA_RASTEROP_REG);
  435.     TGA_WRITE_REG(mode_presets[fb_info.tga_type], TGA_MODE_REG);
  436.     TGA_WRITE_REG(base_addr_presets[fb_info.tga_type], TGA_BASE_ADDR_REG);
  437.     /* calculate & write the PLL */
  438.     tgafb_set_pll(par->pll_freq);
  439.     /* write some more registers */
  440.     TGA_WRITE_REG(0xffffffff, TGA_PLANEMASK_REG);
  441.     TGA_WRITE_REG(0xffffffff, TGA_PIXELMASK_REG);
  442.     TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR0_REG);
  443.     TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR1_REG);
  444.     /* init video timing regs */
  445.     TGA_WRITE_REG(par->htimings, TGA_HORIZ_REG);
  446.     TGA_WRITE_REG(par->vtimings, TGA_VERT_REG);
  447.     /* initalise RAMDAC */
  448.     if (fb_info.tga_type == TGA_TYPE_8PLANE) { 
  449. /* init BT485 RAMDAC registers */
  450. BT485_WRITE(0xa2 | (par->sync_on_green ? 0x8 : 0x0), BT485_CMD_0);
  451. BT485_WRITE(0x01, BT485_ADDR_PAL_WRITE);
  452. BT485_WRITE(0x14, BT485_CMD_3); /* cursor 64x64 */
  453. BT485_WRITE(0x40, BT485_CMD_1);
  454. BT485_WRITE(0x20, BT485_CMD_2); /* cursor off, for now */
  455. BT485_WRITE(0xff, BT485_PIXEL_MASK);
  456. /* fill palette registers */
  457. BT485_WRITE(0x00, BT485_ADDR_PAL_WRITE);
  458. TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
  459. for (i = 0; i < 16; i++) {
  460.     j = color_table[i];
  461.     TGA_WRITE_REG(default_red[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
  462.     TGA_WRITE_REG(default_grn[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
  463.     TGA_WRITE_REG(default_blu[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
  464.     palette[i].red=default_red[j];
  465.     palette[i].green=default_grn[j];
  466.     palette[i].blue=default_blu[j];
  467. }
  468. for (i = 0; i < 240*3; i += 4) {
  469.     TGA_WRITE_REG(0x55|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
  470.     TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
  471.     TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
  472.     TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
  473. }   
  474.     } else { /* 24-plane or 24plusZ */
  475. /* init BT463 registers */
  476. BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
  477. BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
  478. BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_2, 
  479. (par->sync_on_green ? 0x80 : 0x40));
  480. BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
  481. BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
  482. BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_2, 0xff);
  483. BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_3, 0x0f);
  484. BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_0, 0x00);
  485. BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_1, 0x00);
  486. BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_2, 0x00);
  487. BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_3, 0x00);
  488. /* fill the palette */
  489. BT463_LOAD_ADDR(0x0000);
  490. TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
  491. for (i = 0; i < 16; i++) {
  492.     j = color_table[i];
  493.     TGA_WRITE_REG(default_red[j]|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  494.     TGA_WRITE_REG(default_grn[j]|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  495.     TGA_WRITE_REG(default_blu[j]|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  496. }
  497. for (i = 0; i < 512*3; i += 4) {
  498.     TGA_WRITE_REG(0x55|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  499.     TGA_WRITE_REG(0x00|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  500.     TGA_WRITE_REG(0x00|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  501.     TGA_WRITE_REG(0x00|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  502. }   
  503. /* fill window type table after start of vertical retrace */
  504. while (!(TGA_READ_REG(TGA_INTR_STAT_REG) & 0x01))
  505.     continue;
  506. TGA_WRITE_REG(0x01, TGA_INTR_STAT_REG);
  507. mb();
  508. while (!(TGA_READ_REG(TGA_INTR_STAT_REG) & 0x01))
  509.     continue;
  510. TGA_WRITE_REG(0x01, TGA_INTR_STAT_REG);
  511. BT463_LOAD_ADDR(BT463_WINDOW_TYPE_BASE);
  512. TGA_WRITE_REG((BT463_REG_ACC<<2), TGA_RAMDAC_SETUP_REG);
  513. for (i = 0; i < 16; i++) {
  514.     TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
  515.     TGA_WRITE_REG(0x01|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
  516.     TGA_WRITE_REG(0x80|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
  517. }
  518.    
  519.     }
  520.     /* finally, enable video scan
  521. (and pray for the monitor... :-) */
  522.     TGA_WRITE_REG(TGA_VALID_VIDEO, TGA_VALID_REG);
  523. }
  524. #define DIFFCHECK(x) { if( m <= 0x3f ) { 
  525.       int delta = f - (TGA_PLL_BASE_FREQ * (x)) / (r << shift); 
  526.       if (delta < 0) delta = -delta; 
  527.       if (delta < min_diff) min_diff = delta, vm = m, va = a, vr = r; } }
  528. static void tgafb_set_pll(int f)
  529. {
  530.     int                 n, shift, base, min_diff, target;
  531.     int                 r,a,m,vm = 34, va = 1, vr = 30;
  532.     for( r = 0 ; r < 12 ; r++ )
  533. TGA_WRITE_REG(!r, TGA_CLOCK_REG);
  534.     if (f > TGA_PLL_MAX_FREQ)
  535. f = TGA_PLL_MAX_FREQ;
  536.     if (f >= TGA_PLL_MAX_FREQ / 2)
  537. shift = 0;
  538.     else if (f >= TGA_PLL_MAX_FREQ / 4)
  539. shift = 1;
  540.     else
  541. shift = 2;
  542.     TGA_WRITE_REG(shift & 1, TGA_CLOCK_REG);
  543.     TGA_WRITE_REG(shift >> 1, TGA_CLOCK_REG);
  544.     for( r = 0 ; r < 10 ; r++ ) {
  545. TGA_WRITE_REG(0, TGA_CLOCK_REG);
  546.     }
  547.     if (f <= 120000) {
  548. TGA_WRITE_REG(0, TGA_CLOCK_REG);
  549. TGA_WRITE_REG(0, TGA_CLOCK_REG);
  550.     }
  551.     else if (f <= 200000) {
  552. TGA_WRITE_REG(1, TGA_CLOCK_REG);
  553. TGA_WRITE_REG(0, TGA_CLOCK_REG);
  554.     }
  555.     else {
  556. TGA_WRITE_REG(0, TGA_CLOCK_REG);
  557. TGA_WRITE_REG(1, TGA_CLOCK_REG);
  558.     }
  559.     TGA_WRITE_REG(1, TGA_CLOCK_REG);
  560.     TGA_WRITE_REG(0, TGA_CLOCK_REG);
  561.     TGA_WRITE_REG(0, TGA_CLOCK_REG);
  562.     TGA_WRITE_REG(1, TGA_CLOCK_REG);
  563.     TGA_WRITE_REG(0, TGA_CLOCK_REG);
  564.     TGA_WRITE_REG(1, TGA_CLOCK_REG);
  565.     target = (f << shift) / TGA_PLL_BASE_FREQ;
  566.     min_diff = TGA_PLL_MAX_FREQ;
  567.     r = 7 / target;
  568.     if (!r)
  569. r = 1;
  570.     base = target * r;
  571.     while (base < 449) {
  572. for (n = base < 7 ? 7 : base ; n < base + target && n < 449; n++) {
  573. m = ((n + 3) / 7) - 1;
  574. a = 0;
  575. DIFFCHECK((m + 1) * 7);
  576. m++;
  577. DIFFCHECK((m + 1) * 7);
  578. m = (n / 6) - 1;
  579. if( (a = n % 6))
  580.     DIFFCHECK( n );
  581. }
  582. r++;
  583. base += target;
  584.     }
  585.     vr--;
  586.     for( r=0; r<8 ; r++) {
  587. TGA_WRITE_REG((vm >> r) & 1, TGA_CLOCK_REG);
  588.     }
  589.     for( r=0; r<8 ; r++) {
  590. TGA_WRITE_REG((va >> r) & 1, TGA_CLOCK_REG);
  591.     }
  592.     for( r=0; r<7 ; r++) {
  593. TGA_WRITE_REG((vr >> r) & 1, TGA_CLOCK_REG);
  594.     }
  595.     TGA_WRITE_REG(((vr >> 7) & 1)|2, TGA_CLOCK_REG);
  596. }
  597. static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
  598.                          u_int *transp, struct fb_info *info)
  599. {
  600.     if (regno > 255)
  601. return 1;
  602.     *red = (palette[regno].red<<8) | palette[regno].red;
  603.     *green = (palette[regno].green<<8) | palette[regno].green;
  604.     *blue = (palette[regno].blue<<8) | palette[regno].blue;
  605.     *transp = 0;
  606.     return 0;
  607. }
  608. static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  609.                          u_int transp, struct fb_info *info)
  610. {
  611.     if (regno > 255)
  612. return 1;
  613.     red >>= 8;
  614.     green >>= 8;
  615.     blue >>= 8;
  616.     palette[regno].red = red;
  617.     palette[regno].green = green;
  618.     palette[regno].blue = blue;
  619. #ifdef FBCON_HAS_CFB32
  620.     if (regno < 16 && fb_info.tga_type != TGA_TYPE_8PLANE)
  621. fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
  622. #endif
  623.     if (fb_info.tga_type == TGA_TYPE_8PLANE) { 
  624.         BT485_WRITE(regno, BT485_ADDR_PAL_WRITE);
  625.         TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
  626.         TGA_WRITE_REG(red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
  627.         TGA_WRITE_REG(green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
  628.         TGA_WRITE_REG(blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
  629.     }                                                    
  630.     /* How to set a single color register on 24-plane cards?? */
  631.     return 0;
  632. }
  633. #if 1
  634.     /*
  635.      * FIXME: since I don't know how to set a single arbitrary color register
  636.      *  on 24-plane cards, all color palette registers have to be updated
  637.      */
  638. static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  639.   struct fb_info *info)
  640. {
  641.     int err;
  642.     if (!fb_display[con].cmap.len) { /* no colormap allocated? */
  643. if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
  644.     return err;
  645.     }
  646.     if (con == currcon) { /* current console? */
  647. err = fb_set_cmap(cmap, kspc, tgafb_setcolreg, info);
  648. #if 1
  649. if (fb_info.tga_type != TGA_TYPE_8PLANE)
  650. tgafb_update_palette();
  651. #endif
  652. return err;
  653.     } else
  654. fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  655.     return 0;
  656. }
  657. static void tgafb_update_palette(void)
  658. {
  659.     int i;
  660.     BT463_LOAD_ADDR(0x0000);
  661.     TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
  662.     for (i = 0; i < 256; i++) {
  663.  TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  664.  TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  665.  TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
  666.     }
  667. }
  668. #endif
  669. static int tgafb_blank(int blank, struct fb_info_gen *info)
  670. {
  671.     static int tga_vesa_blanked = 0;
  672.     u32 vhcr, vvcr, vvvr;
  673.     unsigned long flags;
  674.     
  675.     save_flags(flags);
  676.     cli();
  677.     vhcr = TGA_READ_REG(TGA_HORIZ_REG);
  678.     vvcr = TGA_READ_REG(TGA_VERT_REG);
  679.     vvvr = TGA_READ_REG(TGA_VALID_REG) & ~(TGA_VALID_VIDEO | TGA_VALID_BLANK);
  680.     switch (blank) {
  681.     case 0: /* Unblanking */
  682.         if (tga_vesa_blanked) {
  683.    TGA_WRITE_REG(vhcr & 0xbfffffff, TGA_HORIZ_REG);
  684.    TGA_WRITE_REG(vvcr & 0xbfffffff, TGA_VERT_REG);
  685.    tga_vesa_blanked = 0;
  686. }
  687.   TGA_WRITE_REG(vvvr | TGA_VALID_VIDEO, TGA_VALID_REG);
  688. break;
  689.     case 1: /* Normal blanking */
  690. TGA_WRITE_REG(vvvr | TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
  691. break;
  692.     case 2: /* VESA blank (vsync off) */
  693. TGA_WRITE_REG(vvcr | 0x40000000, TGA_VERT_REG);
  694. TGA_WRITE_REG(vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
  695. tga_vesa_blanked = 1;
  696. break;
  697.     case 3: /* VESA blank (hsync off) */
  698. TGA_WRITE_REG(vhcr | 0x40000000, TGA_HORIZ_REG);
  699. TGA_WRITE_REG(vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
  700. tga_vesa_blanked = 1;
  701. break;
  702.     case 4: /* Poweroff */
  703. TGA_WRITE_REG(vhcr | 0x40000000, TGA_HORIZ_REG);
  704. TGA_WRITE_REG(vvcr | 0x40000000, TGA_VERT_REG);
  705. TGA_WRITE_REG(vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
  706. tga_vesa_blanked = 1;
  707. break;
  708.     }
  709.     restore_flags(flags);
  710.     return 0;
  711. }
  712. static void tgafb_set_disp(const void *fb_par, struct display *disp,
  713. struct fb_info_gen *info)
  714. {
  715.     disp->screen_base = (char *)fb_info.tga_fb_base;
  716.     switch (fb_info.tga_type) {
  717. #ifdef FBCON_HAS_CFB8
  718. case TGA_TYPE_8PLANE:
  719.     disp->dispsw = &fbcon_cfb8;
  720.             break;
  721. #endif
  722. #ifdef FBCON_HAS_CFB32
  723.         case TGA_TYPE_24PLANE:
  724.         case TGA_TYPE_24PLUSZ:
  725.     disp->dispsw = &fbcon_cfb32; 
  726.             disp->dispsw_data = &fbcon_cfb32_cmap;
  727.             break;
  728. #endif
  729.         default:
  730.             disp->dispsw = &fbcon_dummy;
  731.     }
  732.     disp->scrollmode = SCROLL_YREDRAW;
  733. }
  734. struct fbgen_hwswitch tgafb_hwswitch = {
  735.     tgafb_detect, tgafb_encode_fix, tgafb_decode_var, tgafb_encode_var, tgafb_get_par,
  736.     tgafb_set_par, tgafb_getcolreg, tgafb_setcolreg, NULL, tgafb_blank, 
  737.     tgafb_set_disp
  738. };
  739.     /*
  740.      *  Hardware Independent functions
  741.      */
  742.     /* 
  743.      *  Frame buffer operations
  744.      */
  745. static struct fb_ops tgafb_ops = {
  746. owner: THIS_MODULE,
  747. fb_get_fix: fbgen_get_fix,
  748. fb_get_var: fbgen_get_var,
  749. fb_set_var: fbgen_set_var,
  750. fb_get_cmap: fbgen_get_cmap,
  751. fb_set_cmap: tgafb_set_cmap,
  752. };
  753. #ifndef MODULE
  754.     /*
  755.      *  Setup
  756.      */
  757. int __init tgafb_setup(char *options) {
  758.     char *this_opt;
  759.     int i;
  760.     
  761.     if (options && *options) {
  762.      while ((this_opt = strsep(&options, ",")) != NULL) {
  763.             if (!*this_opt) { continue; }
  764.         
  765.     if (!strncmp(this_opt, "font:", 5)) {
  766.       strncpy(default_fontname, this_opt+5, sizeof default_fontname);
  767.     }
  768.     else if (!strncmp(this_opt, "mode:", 5)) {
  769.      for (i = 0; i < NUM_TOTAL_MODES; i++) {
  770.          if (!strcmp(this_opt+5, tgafb_predefined[i].name))
  771.      default_var = tgafb_predefined[i].var;
  772.      default_var_valid = 1;
  773.      }
  774.          } 
  775.     
  776.     else {
  777.        printk(KERN_ERR "tgafb: unknown parameter %sn", this_opt);
  778.          }
  779.        }
  780.     }
  781.     return 0;
  782. }
  783. #endif
  784.     /*
  785.      *  Initialisation
  786.      */
  787. int __init tgafb_init(void)
  788. {
  789.     struct pci_dev *pdev;
  790.     pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL);
  791.     if (!pdev)
  792. return -ENXIO;
  793.     /* divine board type */
  794.     fb_info.tga_mem_base = (unsigned long)ioremap(pdev->resource[0].start, 0);
  795.     fb_info.tga_type = (readl(fb_info.tga_mem_base) >> 12) & 0x0f;
  796.     fb_info.tga_regs_base = fb_info.tga_mem_base + TGA_REGS_OFFSET;
  797.     fb_info.tga_fb_base = (fb_info.tga_mem_base
  798.    + fb_offset_presets[fb_info.tga_type]);
  799.     pci_read_config_byte(pdev, PCI_REVISION_ID, &fb_info.tga_chip_rev);
  800.     /* setup framebuffer */
  801.     fb_info.gen.info.node = -1;
  802.     fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
  803.     fb_info.gen.info.fbops = &tgafb_ops;
  804.     fb_info.gen.info.disp = &disp;
  805.     fb_info.gen.info.changevar = NULL;
  806.     fb_info.gen.info.switch_con = &fbgen_switch;
  807.     fb_info.gen.info.updatevar = &fbgen_update_var;
  808.     fb_info.gen.info.blank = &fbgen_blank;
  809.     strcpy(fb_info.gen.info.fontname, default_fontname);
  810.     fb_info.gen.parsize = sizeof (struct tgafb_par);
  811.     fb_info.gen.fbhw = &tgafb_hwswitch;
  812.     fb_info.gen.fbhw->detect();
  813.     printk (KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02xn", fb_info.tga_chip_rev);
  814.     printk (KERN_INFO "tgafb: at PCI bus %d, device %d, function %dn", 
  815.     pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
  816.     
  817.     switch (fb_info.tga_type) 
  818.     { 
  819. case TGA_TYPE_8PLANE:
  820.     strcpy (fb_info.gen.info.modename,"Digital ZLXp-E1"); 
  821.     break;
  822. case TGA_TYPE_24PLANE:
  823.     strcpy (fb_info.gen.info.modename,"Digital ZLXp-E2"); 
  824.     break;
  825. case TGA_TYPE_24PLUSZ:
  826.     strcpy (fb_info.gen.info.modename,"Digital ZLXp-E3"); 
  827.     break;
  828.     }
  829.     /* This should give a reasonable default video mode */
  830.     if (!default_var_valid) {
  831. default_var = tgafb_predefined[0].var;
  832.     }
  833.     fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
  834.     disp.var.activate = FB_ACTIVATE_NOW;
  835.     fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
  836.     fbgen_set_disp(-1, &fb_info.gen);
  837.     fbgen_install_cmap(0, &fb_info.gen);
  838.     if (register_framebuffer(&fb_info.gen.info) < 0)
  839. return -EINVAL;
  840.     printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lxn", 
  841.     GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename, 
  842.     pdev->resource[0].start);
  843.     return 0;
  844. }
  845.     /*
  846.      *  Cleanup
  847.      */
  848. void __exit tgafb_cleanup(void)
  849. {
  850.     unregister_framebuffer(&fb_info.gen.info);
  851. }
  852.     /*
  853.      *  Modularisation
  854.      */
  855. #ifdef MODULE
  856. MODULE_LICENSE("GPL");
  857. module_init(tgafb_init);
  858. #endif
  859. module_exit(tgafb_cleanup);