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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: hitfb.c,v 1.2 2000/07/04 06:24:46 yaegashi Exp $
  3.  * linux/drivers/video/hitfb.c -- Hitachi LCD frame buffer device
  4.  * (C) 1999 Mihai Spatar
  5.  * (C) 2000 YAEGASHI Takeshi
  6.  *
  7.  *  This file is subject to the terms and conditions of the GNU General Public
  8.  *  License. See the file COPYING in the main directory of this archive for
  9.  *  more details.
  10.  */
  11.  
  12. #include <linux/config.h>
  13. #include <linux/module.h>
  14. #include <linux/kernel.h>
  15. #include <linux/sched.h>
  16. #include <linux/errno.h>
  17. #include <linux/string.h>
  18. #include <linux/mm.h>
  19. #include <linux/tty.h>
  20. #include <linux/slab.h>
  21. #include <linux/delay.h>
  22. #include <linux/nubus.h>
  23. #include <linux/init.h>
  24. #include <asm/machvec.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/pgtable.h>
  27. #include <asm/io.h>
  28. #include <asm/hd64461.h>
  29. #include <linux/fb.h>
  30. #include <video/fbcon.h>
  31. #include <video/fbcon-cfb8.h>
  32. #include <video/fbcon-cfb16.h>
  33. struct hitfb_par
  34. {
  35.     int x, y;
  36.     int bpp;
  37. };
  38. struct hitfb_info {
  39.     struct fb_info_gen gen;
  40.     struct display disp;
  41.     struct hitfb_par current_par;
  42.     struct fb_var_screeninfo default_var;
  43.     int current_par_valid;
  44.     unsigned long hit_videobase, hit_videosize;
  45.     union {
  46. #ifdef FBCON_HAS_CFB16
  47. u16 cfb16[16];
  48. #endif
  49.     } fbcon_cmap;
  50. } fb_info = {
  51.     {},
  52.     {},
  53.     {},
  54.     {},
  55.     0, 0, 0,
  56.     {},
  57. };
  58. static void hitfb_set_par(const void *fb_par, struct fb_info_gen *info);
  59. static int hitfb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
  60.     struct fb_info_gen *info);
  61. static void hitfb_detect(void)
  62. {
  63.     struct hitfb_par par;
  64.     unsigned short lcdclor, ldr3, ldvntr;
  65.     fb_info.hit_videobase = CONFIG_HD64461_IOBASE + 0x02000000;
  66.     fb_info.hit_videosize = (MACH_HP680 || MACH_HP690) ? 1024*1024 : 512*1024;
  67.     lcdclor = inw(HD64461_LCDCLOR);
  68.     ldvntr = inw(HD64461_LDVNTR);
  69.     ldr3 = inw(HD64461_LDR3);
  70.     switch(ldr3&15) {
  71.     default:
  72.     case 4:
  73.         par.bpp = 8;
  74. par.x = lcdclor;
  75. break;
  76.     case 8:
  77.         par.bpp = 16;
  78. par.x = lcdclor/2;
  79. break;
  80.     }
  81.     par.y = ldvntr+1;
  82.     hitfb_set_par(&par, NULL);
  83.     hitfb_encode_var(&fb_info.default_var, &par, NULL);
  84. }
  85. static int hitfb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
  86.      struct fb_info_gen *info)
  87. {
  88.     const struct hitfb_par *par = fb_par;
  89.     memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  90.     strcpy(fix->id, "Hitachi HD64461");
  91.     fix->smem_start = fb_info.hit_videobase;
  92.     fix->smem_len = fb_info.hit_videosize;
  93.     fix->type = FB_TYPE_PACKED_PIXELS;
  94.     fix->type_aux = 0;
  95.     fix->visual = (par->bpp == 8) ?
  96. FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
  97.     fix->xpanstep = 0;
  98.     fix->ypanstep = 0;
  99.     fix->ywrapstep = 0;
  100.     switch(par->bpp) {
  101.     default:
  102.     case 8:
  103. fix->line_length = par->x;
  104. break;
  105.     case 16:
  106. fix->line_length = par->x*2;
  107. break;
  108.     }
  109.     return 0;
  110. }
  111. static int hitfb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
  112.      struct fb_info_gen *info)
  113. {
  114.     struct hitfb_par *par = fb_par;
  115.     par->x = var->xres;
  116.     par->y = var->yres;
  117.     par->bpp = var->bits_per_pixel;
  118.     return 0;
  119. }
  120. static int hitfb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
  121.      struct fb_info_gen *info)
  122. {
  123.     const struct hitfb_par *par = fb_par;
  124.     memset(var, 0, sizeof(*var));
  125.     var->xres = par->x;
  126.     var->yres = par->y;
  127.     var->xres_virtual = var->xres;
  128.     var->yres_virtual = var->yres;
  129.     var->xoffset = 0;
  130.     var->yoffset = 0;
  131.     var->bits_per_pixel = par->bpp;
  132.     var->grayscale = 0;
  133.     var->transp.offset = 0;
  134.     var->transp.length = 0;
  135.     var->transp.msb_right = 0;
  136.     var->nonstd = 0;
  137.     var->activate = 0;
  138.     var->height = -1;
  139.     var->width = -1;
  140.     var->vmode = FB_VMODE_NONINTERLACED;
  141.     var->pixclock = 0;
  142.     var->sync = 0;
  143.     var->left_margin = 0;
  144.     var->right_margin = 0;
  145.     var->upper_margin = 0;
  146.     var->lower_margin = 0;
  147.     var->hsync_len = 0;
  148.     var->vsync_len = 0;
  149.     switch (var->bits_per_pixel) {
  150. case 8:
  151.     var->red.offset = 0;
  152.     var->red.length = 8;
  153.     var->green.offset = 0;
  154.     var->green.length = 8;
  155.     var->blue.offset = 0;
  156.     var->blue.length = 8;
  157.     var->transp.offset = 0;
  158.     var->transp.length = 0;
  159.     break;
  160. case 16: /* RGB 565 */
  161.     var->red.offset = 11;
  162.     var->red.length = 5;
  163.     var->green.offset = 5;
  164.     var->green.length = 6;
  165.     var->blue.offset = 0;
  166.     var->blue.length = 5;
  167.     var->transp.offset = 0;
  168.     var->transp.length = 0;
  169.     break;
  170.     }
  171.     var->red.msb_right = 0;
  172.     var->green.msb_right = 0;
  173.     var->blue.msb_right = 0;
  174.     var->transp.msb_right = 0;
  175.     return 0;
  176. }
  177. static void hitfb_get_par(void *par, struct fb_info_gen *info)
  178. {
  179.     *(struct hitfb_par *)par = fb_info.current_par;
  180. }
  181. static void hitfb_set_par(const void *fb_par, struct fb_info_gen *info)
  182. {
  183.     const struct hitfb_par *par = fb_par;
  184.     fb_info.current_par = *par;
  185.     fb_info.current_par_valid = 1;
  186. }
  187. static int hitfb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
  188.    unsigned *blue, unsigned *transp,
  189.    struct fb_info *info)
  190. {
  191.     if (regno > 255)
  192. return 1;
  193.     outw(regno<<8, HD64461_CPTRAR);
  194.     *red = inw(HD64461_CPTRDR)<<10;
  195.     *green = inw(HD64461_CPTRDR)<<10;
  196.     *blue = inw(HD64461_CPTRDR)<<10;
  197.     *transp = 0;
  198.     
  199.     return 0;
  200. }
  201. static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
  202.    unsigned blue, unsigned transp,
  203.    struct fb_info *info)
  204. {
  205.     if (regno > 255)
  206. return 1;
  207.     
  208.     outw(regno<<8, HD64461_CPTWAR);
  209.     outw(red>>10, HD64461_CPTWDR);
  210.     outw(green>>10, HD64461_CPTWDR);
  211.     outw(blue>>10, HD64461_CPTWDR);
  212.     
  213.     if(regno<16) {
  214. switch(fb_info.current_par.bpp) {
  215. #ifdef FBCON_HAS_CFB16
  216. case 16:
  217.     fb_info.fbcon_cmap.cfb16[regno] =
  218. ((red   & 0xf800)      ) |
  219. ((green & 0xfc00) >>  5) |
  220. ((blue  & 0xf800) >> 11);
  221.     break;
  222. #endif
  223. }
  224.     }
  225.     return 0;
  226. }
  227. static int hitfb_pan_display(const struct fb_var_screeninfo *var,
  228.      struct fb_info_gen *info)
  229. {
  230.     if (!fb_info.current_par_valid)
  231. return -EINVAL;
  232.     return 0;
  233. }
  234. static int hitfb_blank(int blank_mode, struct fb_info_gen *info)
  235. {
  236.     if (!fb_info.current_par_valid)
  237. return 1;
  238.     return 0;
  239. }
  240. static void hitfb_set_disp(const void *fb_par, struct display *disp,
  241.     struct fb_info_gen *info)
  242. {
  243.     const struct hitfb_par *par = fb_par;
  244.     disp->screen_base = (void *)fb_info.hit_videobase;
  245.     disp->scrollmode = SCROLL_YREDRAW;
  246.     switch(((struct hitfb_par *)par)->bpp) {
  247. #ifdef FBCON_HAS_CFB8
  248.     case 8:
  249. disp->dispsw = &fbcon_cfb8;
  250. break;
  251. #endif
  252. #ifdef FBCON_HAS_CFB16
  253.     case 16:
  254. disp->dispsw = &fbcon_cfb16;
  255. disp->dispsw_data = fb_info.fbcon_cmap.cfb16;
  256. break;
  257. #endif
  258.     default:
  259. disp->dispsw = &fbcon_dummy;
  260.     }
  261. }
  262. struct fbgen_hwswitch hitfb_switch = {
  263.     hitfb_detect,
  264.     hitfb_encode_fix,
  265.     hitfb_decode_var,
  266.     hitfb_encode_var,
  267.     hitfb_get_par,
  268.     hitfb_set_par,
  269.     hitfb_getcolreg,
  270.     hitfb_setcolreg,
  271.     hitfb_pan_display,
  272.     hitfb_blank,
  273.     hitfb_set_disp
  274. };
  275. static struct fb_ops hitfb_ops = {
  276.     owner: THIS_MODULE,
  277.     fb_get_fix: fbgen_get_fix,
  278.     fb_get_var: fbgen_get_var,
  279.     fb_set_var: fbgen_set_var,
  280.     fb_get_cmap: fbgen_get_cmap,
  281.     fb_set_cmap: fbgen_set_cmap,
  282.     fb_pan_display: fbgen_pan_display,
  283. };
  284. int __init hitfb_init(void)
  285. {
  286.     strcpy(fb_info.gen.info.modename, "Hitachi HD64461");
  287.     fb_info.gen.info.node = -1;
  288.     fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
  289.     fb_info.gen.info.fbops = &hitfb_ops;
  290.     fb_info.gen.info.disp = &fb_info.disp;
  291.     fb_info.gen.info.changevar = NULL;
  292.     fb_info.gen.info.switch_con = &fbgen_switch;
  293.     fb_info.gen.info.updatevar = &fbgen_update_var;
  294.     fb_info.gen.info.blank = &fbgen_blank;
  295.     fb_info.gen.parsize = sizeof(struct hitfb_par);
  296.     fb_info.gen.fbhw = &hitfb_switch;
  297.     fb_info.gen.fbhw->detect();
  298.     
  299.     fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
  300.     fb_info.disp.var.activate = FB_ACTIVATE_NOW;
  301.     fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen);
  302.     fbgen_set_disp(-1, &fb_info.gen);
  303.     fbgen_install_cmap(0, &fb_info.gen);
  304.     
  305.     if(register_framebuffer(&fb_info.gen.info)<0) return -EINVAL;
  306.     
  307.     printk(KERN_INFO "fb%d: %s frame buffer devicen",
  308.    GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);
  309.     
  310.     return 0;
  311. }
  312. void hitfb_cleanup(struct fb_info *info)
  313. {
  314.     unregister_framebuffer(info);
  315. }
  316. #ifdef MODULE
  317. MODULE_LICENSE("GPL");
  318. int init_module(void)
  319. {
  320.     return hitfb_init();
  321. }
  322. void cleanup_module(void)
  323. {
  324.   hitfb_cleanup(void);
  325. }
  326. #endif
  327. /*
  328.  * Local variables:
  329.  * c-basic-offset: 4
  330.  * End:
  331.  */