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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: g364fb.c,v 1.3 1998/08/28 22:43:00 tsbogend Exp $
  2.  *
  3.  * linux/drivers/video/g364fb.c -- Mips Magnum frame buffer device
  4.  *
  5.  * (C) 1998 Thomas Bogendoerfer
  6.  *
  7.  *  This driver is based on tgafb.c
  8.  *
  9.  * Copyright (C) 1997 Geert Uytterhoeven 
  10.  * Copyright (C) 1995  Jay Estabrook
  11.  *
  12.  *  This file is subject to the terms and conditions of the GNU General Public
  13.  *  License. See the file COPYING in the main directory of this archive for
  14.  *  more details.
  15.  */
  16. #include <linux/module.h>
  17. #include <linux/sched.h>
  18. #include <linux/kernel.h>
  19. #include <linux/errno.h>
  20. #include <linux/string.h>
  21. #include <linux/mm.h>
  22. #include <linux/tty.h>
  23. #include <linux/slab.h>
  24. #include <linux/vmalloc.h>
  25. #include <linux/delay.h>
  26. #include <linux/interrupt.h>
  27. #include <linux/fb.h>
  28. #include <linux/init.h>
  29. #include <linux/pci.h>
  30. #include <linux/selection.h>
  31. #include <linux/console.h>
  32. #include <asm/io.h>
  33. #include <asm/jazz.h>
  34. #include <video/fbcon.h>
  35. #include <video/fbcon-cfb8.h>
  36. /* 
  37.  * Various defines for the G364
  38.  */
  39. #define G364_MEM_BASE   0xe4400000
  40. #define G364_PORT_BASE  0xe4000000
  41. #define ID_REG  0xe4000000   /* Read only */
  42. #define BOOT_REG  0xe4080000
  43. #define TIMING_REG  0xe4080108  /* to 0x080170 - DON'T TOUCH! */
  44. #define DISPLAY_REG  0xe4080118
  45. #define VDISPLAY_REG  0xe4080150
  46. #define MASK_REG  0xe4080200
  47. #define CTLA_REG  0xe4080300
  48. #define CURS_TOGGLE  0x800000
  49. #define BIT_PER_PIX 0x700000 /* bits 22 to 20 of Control A */
  50. #define DELAY_SAMPLE    0x080000
  51. #define PORT_INTER 0x040000
  52. #define PIX_PIPE_DEL 0x030000 /* bits 17 and 16 of Control A */
  53. #define PIX_PIPE_DEL2 0x008000 /* same as above - don't ask me why */
  54. #define TR_CYCLE_TOG 0x004000
  55. #define VRAM_ADR_INC 0x003000 /* bits 13 and 12 of Control A */
  56. #define BLANK_OFF 0x000800
  57. #define FORCE_BLANK 0x000400
  58. #define BLK_FUN_SWTCH 0x000200
  59. #define BLANK_IO 0x000100
  60. #define BLANK_LEVEL 0x000080
  61. #define A_VID_FORM 0x000040
  62. #define D_SYNC_FORM 0x000020
  63. #define FRAME_FLY_PAT 0x000010
  64. #define OP_MODE 0x000008
  65. #define INTL_STAND 0x000004
  66. #define SCRN_FORM 0x000002
  67. #define ENABLE_VTG 0x000001
  68. #define TOP_REG  0xe4080400
  69. #define CURS_PAL_REG  0xe4080508  /* to 0x080518 */
  70. #define CHKSUM_REG  0xe4080600  /* to 0x080610 - unused */
  71. #define CURS_POS_REG  0xe4080638
  72. #define CLR_PAL_REG  0xe4080800 /* to 0x080ff8 */
  73. #define CURS_PAT_REG  0xe4081000 /* to 0x081ff8 */
  74. #define MON_ID_REG  0xe4100000  /* unused */
  75. #define RESET_REG  0xe4180000   /* Write only */
  76. static int currcon = 0;
  77. static struct display disp;
  78. static struct fb_info fb_info;
  79. static struct { u_char red, green, blue, pad; } palette[256];
  80. static struct fb_fix_screeninfo fb_fix = { { "G364 8plane", } };
  81. static struct fb_var_screeninfo fb_var = { 0, };
  82. /*
  83.  *  Interface used by the world
  84.  */
  85. static int g364fb_get_fix(struct fb_fix_screeninfo *fix, int con,
  86.   struct fb_info *info);
  87. static int g364fb_get_var(struct fb_var_screeninfo *var, int con,
  88.   struct fb_info *info);
  89. static int g364fb_set_var(struct fb_var_screeninfo *var, int con,
  90.   struct fb_info *info);
  91. static int g364fb_pan_display(struct fb_var_screeninfo *var, int con,
  92.       struct fb_info *info);
  93. static int g364fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  94.    struct fb_info *info);
  95. static int g364fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  96.    struct fb_info *info);
  97. /*
  98.  *  Interface to the low level console driver
  99.  */
  100. int g364fb_init(void);
  101. static int g364fbcon_switch(int con, struct fb_info *info);
  102. static int g364fbcon_updatevar(int con, struct fb_info *info);
  103. static void g364fbcon_blank(int blank, struct fb_info *info);
  104. /*
  105.  *  Internal routines
  106.  */
  107. static int g364fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
  108.     u_int *transp, struct fb_info *info);
  109. static int g364fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  110.     u_int transp, struct fb_info *info);
  111. static void do_install_cmap(int con, struct fb_info *info);
  112. static struct fb_ops g364fb_ops = {
  113. owner: THIS_MODULE,
  114. fb_get_fix: g364fb_get_fix,
  115. fb_get_var: g364fb_get_var,
  116. fb_set_var: g364fb_set_var,
  117. fb_get_cmap: g364fb_get_cmap,
  118. fb_set_cmap: g364fb_set_cmap,
  119. fb_pan_display: g364fb_pan_display,
  120. };
  121. void fbcon_g364fb_cursor(struct display *p, int mode, int x, int y)
  122. {
  123.     switch (mode) {
  124.      case CM_ERASE:
  125. *(unsigned int *) CTLA_REG |= CURS_TOGGLE;
  126. break;
  127.      case CM_MOVE:
  128.      case CM_DRAW:
  129. *(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
  130. *(unsigned int *) CURS_POS_REG = ((x * fontwidth(p)) << 12) | ((y * fontheight(p))-p->var.yoffset);
  131. break;
  132.     }
  133. }
  134. static struct display_switch fbcon_g364cfb8 = {
  135.     setup: fbcon_cfb8_setup,
  136.     bmove: fbcon_cfb8_bmove,
  137.     clear: fbcon_cfb8_clear,
  138.     putc: fbcon_cfb8_putc,
  139.     putcs: fbcon_cfb8_putcs,
  140.     revc: fbcon_cfb8_revc,
  141.     cursor: fbcon_g364fb_cursor,
  142.     clear_margins: fbcon_cfb8_clear_margins,
  143.     fontwidthmask: FONTWIDTH(8)
  144. };
  145. /*
  146.  *  Get the Fixed Part of the Display
  147.  */
  148. static int g364fb_get_fix(struct fb_fix_screeninfo *fix, int con,
  149.   struct fb_info *info)
  150. {
  151.     memcpy(fix, &fb_fix, sizeof(fb_fix));
  152.     return 0;
  153. }
  154. /*
  155.  *  Get the User Defined Part of the Display
  156.  */
  157. static int g364fb_get_var(struct fb_var_screeninfo *var, int con,
  158.   struct fb_info *info)
  159. {
  160.     memcpy(var, &fb_var, sizeof(fb_var));
  161.     return 0;
  162. }
  163. /*
  164.  *  Set the User Defined Part of the Display
  165.  */
  166. static int g364fb_set_var(struct fb_var_screeninfo *var, int con,
  167.   struct fb_info *info)
  168. {
  169.     struct display *display;
  170.     int oldbpp = -1, err;
  171.     if (con >= 0)
  172. display = &fb_display[con];
  173.     else
  174. display = &disp; /* used during initialization */
  175.     if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
  176. var->xres_virtual > fb_var.xres_virtual ||
  177. var->yres_virtual > fb_var.yres_virtual ||
  178. var->bits_per_pixel > fb_var.bits_per_pixel ||
  179. var->nonstd ||
  180. (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
  181. return -EINVAL;
  182.     memcpy(var, &fb_var, sizeof(fb_var));
  183.     
  184.     if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
  185. oldbpp = display->var.bits_per_pixel;
  186. display->var = *var;
  187. *(unsigned int *)TOP_REG = var->yoffset * var->xres;
  188.     }
  189.     if (oldbpp != var->bits_per_pixel) {
  190. if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
  191.     return err;
  192. do_install_cmap(con, info);
  193.     }
  194.     return 0;
  195. }
  196. /*
  197.  *  Pan or Wrap the Display
  198.  *
  199.  *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
  200.  */
  201. static int g364fb_pan_display(struct fb_var_screeninfo *var, int con,
  202.       struct fb_info *info)
  203. {
  204.     if (var->xoffset || var->yoffset+var->yres > var->yres_virtual)
  205. return -EINVAL;
  206.     
  207.     *(unsigned int *)TOP_REG = var->yoffset * var->xres;
  208.     return 0;
  209. }
  210. /*
  211.  *  Get the Colormap
  212.  */
  213. static int g364fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  214.    struct fb_info *info)
  215. {
  216.     if (con == currcon) /* current console? */
  217. return fb_get_cmap(cmap, kspc, g364fb_getcolreg, info);
  218.     else if (fb_display[con].cmap.len) /* non default colormap? */
  219. fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  220.     else
  221. fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
  222.      cmap, kspc ? 0 : 2);
  223.     return 0;
  224. }
  225. /*
  226.  *  Set the Colormap
  227.  */
  228. static int g364fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  229.    struct fb_info *info)
  230. {
  231.     int err;
  232.     if (!fb_display[con].cmap.len) { /* no colormap allocated? */
  233. if ((err = fb_alloc_cmap(&fb_display[con].cmap,
  234.  1<<fb_display[con].var.bits_per_pixel, 0)))
  235.     return err;
  236.     }
  237.     if (con == currcon) { /* current console? */
  238. return fb_set_cmap(cmap, kspc, g364fb_setcolreg, info);
  239.     } else
  240. fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  241.     return 0;
  242. }
  243. /*
  244.  *  Initialisation
  245.  */
  246. int __init g364fb_init(void)
  247. {
  248.     int i,j;
  249.     volatile unsigned int *pal_ptr = (volatile unsigned int *) CLR_PAL_REG;
  250.     volatile unsigned int *curs_pal_ptr = (volatile unsigned int *) CURS_PAL_REG;
  251.     unsigned int xres, yres;
  252.     int mem;
  253.     /* TBD: G364 detection */
  254.     
  255.     /* get the resolution set by ARC console */
  256.     *(volatile unsigned int *)CTLA_REG &= ~ENABLE_VTG;
  257.     xres = (*((volatile unsigned int*)DISPLAY_REG) & 0x00ffffff) * 4;
  258.     yres = (*((volatile unsigned int*)VDISPLAY_REG) & 0x00ffffff) / 2;
  259.     *(volatile unsigned int *)CTLA_REG |= ENABLE_VTG;    
  260.     /* initialise color palette */
  261.     for (i = 0; i < 16; i++) {
  262. j = color_table[i];
  263. palette[i].red=default_red[j];
  264. palette[i].green=default_grn[j];
  265. palette[i].blue=default_blu[j];
  266. pal_ptr[i << 1] = (palette[i].red << 16) | (palette[i].green << 8) | palette[i].blue;
  267.     }
  268.     
  269.     /* setup cursor */
  270.     curs_pal_ptr[0] |= 0x00ffffff;
  271.     curs_pal_ptr[2] |= 0x00ffffff;
  272.     curs_pal_ptr[4] |= 0x00ffffff;
  273.     /*
  274.      * first set the whole cursor to transparent
  275.      */
  276.     for (i = 0; i < 512; i++)
  277. *(unsigned short *)(CURS_PAT_REG+i*8) = 0;
  278.     /*
  279.      * switch the last two lines to cursor palette 3
  280.      * we assume here, that FONTSIZE_X is 8
  281.      */
  282.     *(unsigned short *)(CURS_PAT_REG + 14*64) = 0xffff;
  283.     *(unsigned short *)(CURS_PAT_REG + 15*64) = 0xffff;     
  284.     fb_var.bits_per_pixel = 8;
  285.     fb_var.xres = fb_var.xres_virtual = xres;
  286.     fb_var.yres = yres;
  287.     fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel;
  288.     fb_fix.smem_start = 0x40000000; /* physical address */
  289.     /* get size of video memory; this is special for the JAZZ hardware */
  290.     mem = (r4030_read_reg32(JAZZ_R4030_CONFIG) >> 8) & 3;
  291.     fb_fix.smem_len = (1 << (mem*2)) * 512 * 1024;
  292.     fb_fix.type = FB_TYPE_PACKED_PIXELS;
  293.     fb_fix.type_aux = 0;
  294.     fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;    
  295.     fb_fix.xpanstep = 0;
  296.     fb_fix.ypanstep = 1;
  297.     fb_fix.ywrapstep = 0;
  298.     fb_fix.mmio_start = 0;
  299.     fb_fix.mmio_len = 0;
  300.     fb_fix.accel = FB_ACCEL_NONE;
  301.     
  302.     fb_var.yres_virtual = fb_fix.smem_len / xres;
  303.     fb_var.xoffset = fb_var.yoffset = 0;
  304.     fb_var.grayscale = 0;
  305.     fb_var.red.offset = 0;
  306.     fb_var.green.offset = 0;
  307.     fb_var.blue.offset = 0;
  308.     fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
  309.     fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
  310.     fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
  311.     fb_var.nonstd = 0;
  312.     fb_var.activate = 0;
  313.     fb_var.height = fb_var.width = -1;
  314.     fb_var.accel_flags = 0;
  315.     fb_var.pixclock = 39722;
  316.     fb_var.left_margin = 40;
  317.     fb_var.right_margin = 24;
  318.     fb_var.upper_margin = 32;
  319.     fb_var.lower_margin = 11;
  320.     fb_var.hsync_len = 96;
  321.     fb_var.vsync_len = 2;
  322.     fb_var.sync = 0;
  323.     fb_var.vmode = FB_VMODE_NONINTERLACED;
  324.     disp.var = fb_var;
  325.     disp.cmap.start = 0;
  326.     disp.cmap.len = 0;
  327.     disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
  328.     disp.screen_base = (char *)G364_MEM_BASE; /* virtual kernel address */
  329.     disp.visual = fb_fix.visual;
  330.     disp.type = fb_fix.type;
  331.     disp.type_aux = fb_fix.type_aux;
  332.     disp.ypanstep = fb_fix.ypanstep;
  333.     disp.ywrapstep = fb_fix.ywrapstep;
  334.     disp.line_length = fb_fix.line_length;
  335.     disp.can_soft_blank = 1;
  336.     disp.inverse = 0;
  337.     disp.dispsw = &fbcon_g364cfb8;
  338.     strcpy(fb_info.modename, fb_fix.id);
  339.     fb_info.node = -1;
  340.     fb_info.fbops = &g364fb_ops;
  341.     fb_info.disp = &disp;
  342.     fb_info.fontname[0] = '';
  343.     fb_info.changevar = NULL;
  344.     fb_info.switch_con = &g364fbcon_switch;
  345.     fb_info.updatevar = &g364fbcon_updatevar;
  346.     fb_info.blank = &g364fbcon_blank;
  347.     fb_info.flags = FBINFO_FLAG_DEFAULT;
  348.     g364fb_set_var(&fb_var, -1, &fb_info);
  349.     if (register_framebuffer(&fb_info) < 0)
  350. return -EINVAL;
  351.     printk("fb%d: %s frame buffer devicen", GET_FB_IDX(fb_info.node),
  352.    fb_fix.id);
  353.     return 0;
  354. }
  355. static int g364fbcon_switch(int con, struct fb_info *info)
  356. {
  357.     /* Do we have to save the colormap? */
  358.     if (fb_display[currcon].cmap.len)
  359. fb_get_cmap(&fb_display[currcon].cmap, 1, g364fb_getcolreg, info);
  360.     currcon = con;
  361.     /* Install new colormap */
  362.     do_install_cmap(con, info);
  363.     g364fbcon_updatevar(con, info);    
  364.     return 0;
  365. }
  366. /*
  367.  *  Update the `var' structure (called by fbcon.c)
  368.  */
  369. static int g364fbcon_updatevar(int con, struct fb_info *info)
  370. {
  371.     if (con == currcon) {
  372. struct fb_var_screeninfo *var = &fb_display[currcon].var;
  373. /* hardware scrolling */
  374. *(unsigned int *)TOP_REG = var->yoffset * var->xres;
  375.     }
  376.     return 0;
  377. }
  378. /*
  379.  *  Blank the display.
  380.  */
  381. static void g364fbcon_blank(int blank, struct fb_info *info)
  382. {
  383.     if (blank)
  384. *(unsigned int *) CTLA_REG |= FORCE_BLANK;
  385.     else
  386. *(unsigned int *) CTLA_REG &= ~FORCE_BLANK;
  387. }
  388. /*
  389.  *  Read a single color register and split it into
  390.  *  colors/transparent. Return != 0 for invalid regno.
  391.  */
  392. static int g364fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
  393.     u_int *transp, struct fb_info *info)
  394. {
  395.     if (regno > 255)
  396. return 1;
  397.     *red = (palette[regno].red << 8) | palette[regno].red;
  398.     *green = (palette[regno].green << 8) | palette[regno].green;
  399.     *blue = (palette[regno].blue << 8) | palette[regno].blue;
  400.     *transp = 0;
  401.     return 0;
  402. }
  403. /*
  404.  *  Set a single color register. Return != 0 for invalid regno.
  405.  */
  406. static int g364fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  407.     u_int transp, struct fb_info *info)
  408. {
  409.     volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG;
  410.     if (regno > 255)
  411. return 1;
  412.     red >>= 8;
  413.     green >>= 8;
  414.     blue >>=8;
  415.     palette[regno].red = red;
  416.     palette[regno].green = green;
  417.     palette[regno].blue = blue;
  418.     
  419.     ptr[regno << 1] = (red << 16) | (green << 8) | blue;
  420.     return 0;
  421. }
  422. static void do_install_cmap(int con, struct fb_info *info)
  423. {
  424.     if (con != currcon)
  425. return;
  426.     if (fb_display[con].cmap.len)
  427. fb_set_cmap(&fb_display[con].cmap, 1, g364fb_setcolreg, info);
  428.     else
  429. fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1,
  430.     g364fb_setcolreg, info);
  431. }
  432. MODULE_LICENSE("GPL");