maxinefb.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *      linux/drivers/video/maxinefb.c
  3.  *
  4.  * DECstation 5000/xx onboard framebuffer support ... derived from:
  5.  * "HP300 Topcat framebuffer support (derived from macfb of all things)
  6.  * Phil Blundell <philb@gnu.org> 1998", the original code can be
  7.  *      found in the file hpfb.c in the same directory.
  8.  *
  9.  *      DECstation related code Copyright (C) 1999,2000,2001 by
  10.  *      Michael Engel <engel@unix-ag.org> and
  11.  *      Karsten Merker <merker@linuxtag.org>.
  12.  *      This file is subject to the terms and conditions of the GNU General
  13.  *      Public License.  See the file COPYING in the main directory of this
  14.  *      archive for more details.
  15.  *
  16.  */
  17. /*
  18.  * Changes:
  19.  * 2001/01/27 removed debugging and testing code, fixed fb_ops
  20.  *            initialization which had caused a crash before,
  21.  *            general cleanup, first official release (KM)
  22.  *
  23.  */
  24. #include <linux/module.h>
  25. #include <linux/kernel.h>
  26. #include <linux/sched.h>
  27. #include <linux/errno.h>
  28. #include <linux/string.h>
  29. #include <linux/mm.h>
  30. #include <linux/tty.h>
  31. #include <linux/slab.h>
  32. #include <linux/delay.h>
  33. #include <linux/init.h>
  34. #include <linux/fb.h>
  35. #include <video/fbcon.h>
  36. #include "maxinefb.h"
  37. /* bootinfo.h defines the machine type values, needed when checking */
  38. /* whether are really running on a maxine, KM                       */
  39. #include <asm/bootinfo.h>
  40. #include <video/fbcon-mfb.h>
  41. #include <video/fbcon-cfb2.h>
  42. #include <video/fbcon-cfb4.h>
  43. #include <video/fbcon-cfb8.h>
  44. #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
  45. static struct display disp;
  46. static struct fb_info fb_info;
  47. unsigned long fb_start, fb_size = 1024 * 768, fb_line_length = 1024;
  48. unsigned long fb_regs;
  49. unsigned char fb_bitmask;
  50. static struct fb_var_screeninfo maxinefb_defined = {
  51. 0, 0, 0, 0, /* W,H, W, H (virtual) load xres,xres_virtual */
  52. 0, 0, /* virtual -> visible no offset */
  53. 0, /* depth -> load bits_per_pixel */
  54. 0, /* greyscale ? */
  55. {0, 0, 0}, /* R */
  56. {0, 0, 0}, /* G */
  57. {0, 0, 0}, /* B */
  58. {0, 0, 0}, /* transparency */
  59. 0, /* standard pixel format */
  60. FB_ACTIVATE_NOW,
  61. 274, 195, /* 14" monitor */
  62. FB_ACCEL_NONE,
  63. 0L, 0L, 0L, 0L, 0L,
  64. 0L, 0L, 0, /* No sync info */
  65. FB_VMODE_NONINTERLACED,
  66. {0, 0, 0, 0, 0, 0}
  67. };
  68. struct maxinefb_par {
  69. };
  70. static int currcon = 0;
  71. struct maxinefb_par current_par;
  72. /* Reference to machine type set in arch/mips/dec/prom/identify.c, KM */
  73. extern unsigned long mips_machtype;
  74. /* Handle the funny Inmos RamDAC/video controller ... */
  75. void maxinefb_ims332_write_register(int regno, register unsigned int val)
  76. {
  77. register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
  78. unsigned char *wptr;
  79. wptr = regs + 0xa0000 + (regno << 4);
  80. *((volatile unsigned int *) (regs)) = (val >> 8) & 0xff00;
  81. *((volatile unsigned short *) (wptr)) = val;
  82. }
  83. unsigned int maxinefb_ims332_read_register(int regno)
  84. {
  85. register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
  86. unsigned char *rptr;
  87. register unsigned int j, k;
  88. rptr = regs + 0x80000 + (regno << 4);
  89. j = *((volatile unsigned short *) rptr);
  90. k = *((volatile unsigned short *) regs);
  91. return (j & 0xffff) | ((k & 0xff00) << 8);
  92. }
  93. static void maxinefb_encode_var(struct fb_var_screeninfo *var,
  94. struct maxinefb_par *par)
  95. {
  96. int i = 0;
  97. var->xres = 1024;
  98. var->yres = 768;
  99. var->xres_virtual = 1024;
  100. var->yres_virtual = 768;
  101. var->xoffset = 0;
  102. var->yoffset = 0;
  103. var->bits_per_pixel = 8;
  104. var->grayscale = 0;
  105. var->transp.offset = 0;
  106. var->transp.length = 0;
  107. var->transp.msb_right = 0;
  108. var->nonstd = 0;
  109. var->activate = 1;
  110. var->height = -1;
  111. var->width = -1;
  112. var->vmode = FB_VMODE_NONINTERLACED;
  113. var->pixclock = 0;
  114. var->sync = 0;
  115. var->left_margin = 0;
  116. var->right_margin = 0;
  117. var->upper_margin = 0;
  118. var->lower_margin = 0;
  119. var->hsync_len = 0;
  120. var->vsync_len = 0;
  121. for (i = 0; i < arraysize(var->reserved); i++)
  122. var->reserved[i] = 0;
  123. }
  124. static void maxinefb_get_par(struct maxinefb_par *par)
  125. {
  126. *par = current_par;
  127. }
  128. static int maxinefb_fb_update_var(int con, struct fb_info *info)
  129. {
  130. return 0;
  131. }
  132. static int maxinefb_do_fb_set_var(struct fb_var_screeninfo *var,
  133.   int isactive)
  134. {
  135. struct maxinefb_par par;
  136. maxinefb_get_par(&par);
  137. maxinefb_encode_var(var, &par);
  138. return 0;
  139. }
  140. /* Get the palette */
  141. static int maxinefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  142.      struct fb_info *info)
  143. {
  144. unsigned int i;
  145. unsigned long hw_colorvalue = 0; /* raw color value from the register */
  146. unsigned int length;
  147. if (((cmap->start) + (cmap->len)) >= 256) {
  148. length = 256 - (cmap->start);
  149. } else {
  150. length = cmap->len;
  151. }
  152. for (i = 0; i < length; i++) {
  153. hw_colorvalue =
  154.     maxinefb_ims332_read_register(IMS332_REG_COLOR_PALETTE
  155.   + cmap->start + i);
  156. (cmap->red[i]) = ((hw_colorvalue & 0x0000ff));
  157. (cmap->green[i]) = ((hw_colorvalue & 0x00ff00) >> 8);
  158. (cmap->blue[i]) = ((hw_colorvalue & 0xff0000) >> 16);
  159. }
  160. return 0;
  161. }
  162. /* Set the palette */
  163. static int maxinefb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  164.      struct fb_info *info)
  165. {
  166. unsigned int i;
  167. unsigned long hw_colorvalue; /* value to be written into the palette reg. */
  168. unsigned short cmap_red;
  169. unsigned short cmap_green;
  170. unsigned short cmap_blue;
  171. unsigned int length;
  172. hw_colorvalue = 0;
  173. if (((cmap->start) + (cmap->len)) >= 256) {
  174. length = 256 - (cmap->start);
  175. } else {
  176. length = cmap->len;
  177. }
  178. for (i = 0; i < length; i++) {
  179. cmap_red = ((cmap->red[i]) >> 8); /* The cmap fields are 16 bits    */
  180. cmap_green = ((cmap->green[i]) >> 8); /* wide, but the harware colormap */
  181. cmap_blue = ((cmap->blue[i]) >> 8); /* registers are only 8 bits wide */
  182. hw_colorvalue =
  183.     (cmap_blue << 16) + (cmap_green << 8) + (cmap_red);
  184. maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE +
  185.        cmap->start + i,
  186.        hw_colorvalue);
  187. }
  188. return 0;
  189. }
  190. static int maxinefb_get_var(struct fb_var_screeninfo *var, int con,
  191.     struct fb_info *info)
  192. {
  193. struct maxinefb_par par;
  194. if (con == -1) {
  195. maxinefb_get_par(&par);
  196. maxinefb_encode_var(var, &par);
  197. } else
  198. *var = fb_display[con].var;
  199. return 0;
  200. }
  201. static int maxinefb_set_var(struct fb_var_screeninfo *var, int con,
  202.     struct fb_info *info)
  203. {
  204. int err;
  205. if ((err = maxinefb_do_fb_set_var(var, 1)))
  206. return err;
  207. return 0;
  208. }
  209. static void maxinefb_encode_fix(struct fb_fix_screeninfo *fix,
  210. struct maxinefb_par *par)
  211. {
  212. memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  213. strcpy(fix->id, "maxinefb");
  214. /* fix->id is a char[16], so a maximum of 15 characters, KM */
  215. fix->smem_start = (char *) fb_start; /* display memory base address, KM */
  216. fix->smem_len = fb_size;
  217. fix->type = FB_TYPE_PACKED_PIXELS;
  218. fix->visual = FB_VISUAL_PSEUDOCOLOR;
  219. fix->xpanstep = 0;
  220. fix->ypanstep = 0;
  221. fix->ywrapstep = 0;
  222. fix->line_length = fb_line_length;
  223. }
  224. static int maxinefb_get_fix(struct fb_fix_screeninfo *fix, int con,
  225.     struct fb_info *info)
  226. {
  227. struct maxinefb_par par;
  228. maxinefb_get_par(&par);
  229. maxinefb_encode_fix(fix, &par);
  230. return 0;
  231. }
  232. static int maxinefb_switch(int con, struct fb_info *info)
  233. {
  234. maxinefb_do_fb_set_var(&fb_display[con].var, 1);
  235. currcon = con;
  236. return 0;
  237. }
  238. static void maxinefb_set_disp(int con)
  239. {
  240. struct fb_fix_screeninfo fix;
  241. struct display *display;
  242. if (con >= 0)
  243. display = &fb_display[con];
  244. else
  245. display = &disp; /* used during initialization */
  246. maxinefb_get_fix(&fix, con, 0);
  247. display->screen_base = fix.smem_start;
  248. display->visual = fix.visual;
  249. display->type = fix.type;
  250. display->type_aux = fix.type_aux;
  251. display->ypanstep = fix.ypanstep;
  252. display->ywrapstep = fix.ywrapstep;
  253. display->line_length = fix.line_length;
  254. display->next_line = fix.line_length;
  255. display->can_soft_blank = 0;
  256. display->inverse = 0;
  257. display->dispsw = &fbcon_cfb8;
  258. }
  259. static struct fb_ops maxinefb_ops = {
  260. owner: THIS_MODULE,
  261. fb_get_fix: maxinefb_get_fix,
  262. fb_get_var: maxinefb_get_var,
  263. fb_set_var: maxinefb_set_var,
  264. fb_get_cmap: maxinefb_get_cmap,
  265. fb_set_cmap: maxinefb_set_cmap,
  266. };
  267. int __init maxinefb_init(void)
  268. {
  269. volatile unsigned char *fboff;
  270. int i;
  271. /* Validate we're on the proper machine type */
  272. if (mips_machtype != MACH_DS5000_XX) {
  273. return -EINVAL;
  274. }
  275. printk(KERN_INFO "Maxinefb: Personal DECstation detectedn");
  276. printk(KERN_INFO "Maxinefb: initializing onboard framebuffern");
  277. /* Framebuffer display memory base address */
  278. fb_start = DS5000_xx_ONBOARD_FBMEM_START;
  279. /* Clear screen */
  280. for (fboff = fb_start; fboff < fb_start + 0x1ffff; fboff++)
  281. *fboff = 0x0;
  282. /* erase hardware cursor */
  283. for (i = 0; i < 512; i++) {
  284. maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i,
  285.        0);
  286. /*
  287.    if (i&0x8 == 0)
  288.    maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0x0f);
  289.    else
  290.    maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0xf0);
  291.  */
  292. }
  293. /* Fill in the available video resolution */
  294. maxinefb_defined.xres = 1024;
  295. maxinefb_defined.yres = 768;
  296. maxinefb_defined.xres_virtual = 1024;
  297. maxinefb_defined.yres_virtual = 768;
  298. maxinefb_defined.bits_per_pixel = 8;
  299. /* Let there be consoles... */
  300. strcpy(fb_info.modename, "Maxine onboard graphics 1024x768x8");
  301. /* fb_info.modename: maximum of 39 characters + trailing nullbyte, KM */
  302. fb_info.changevar = NULL;
  303. fb_info.node = -1;
  304. fb_info.fbops = &maxinefb_ops;
  305. fb_info.disp = &disp;
  306. fb_info.switch_con = &maxinefb_switch;
  307. fb_info.updatevar = &maxinefb_fb_update_var;
  308. fb_info.blank = NULL;
  309. fb_info.flags = FBINFO_FLAG_DEFAULT;
  310. maxinefb_do_fb_set_var(&maxinefb_defined, 1);
  311. maxinefb_get_var(&disp.var, -1, &fb_info);
  312. maxinefb_set_disp(-1);
  313. if (register_framebuffer(&fb_info) < 0)
  314. return 1;
  315. return 0;
  316. }
  317. static void __exit maxinefb_exit(void)
  318. {
  319. unregister_framebuffer(&fb_info);
  320. }
  321. #ifdef MODULE
  322. MODULE_LICENSE("GPL");
  323. module_init(maxinefb_init);
  324. #endif
  325. module_exit(maxinefb_exit);