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

嵌入式Linux

开发平台:

Unix_Linux

  1. #include <linux/kernel.h>
  2. #include <linux/errno.h>
  3. #include <linux/string.h>
  4. #include <linux/mm.h>
  5. #include <linux/tty.h>
  6. #include <linux/slab.h>
  7. #include <linux/delay.h>
  8. #include <linux/interrupt.h>
  9. #include <asm/uaccess.h>
  10. #include <asm/setup.h>
  11. #include <asm/segment.h>
  12. #include <asm/system.h>
  13. /*#include <asm/irq.h>*/
  14. #include <asm/q40_master.h>
  15. #include <linux/fb.h>
  16. #include <linux/module.h>
  17. #include <asm/pgtable.h>
  18. #include <video/fbcon.h>
  19. #include <video/fbcon-cfb16.h>
  20. #define FBIOSETSCROLLMODE   0x4611
  21. #define Q40_PHYS_SCREEN_ADDR 0xFE800000
  22. static unsigned long q40_screen_addr;
  23. static u16 fbcon_cmap_cfb16[16];
  24. /* frame buffer operations */
  25. static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con,
  26. struct fb_info *info);
  27. static int q40fb_get_var(struct fb_var_screeninfo *var, int con,
  28. struct fb_info *info);
  29. static int q40fb_set_var(struct fb_var_screeninfo *var, int con,
  30. struct fb_info *info);
  31. static int q40fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
  32.  struct fb_info *info);
  33. static int q40fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
  34.  struct fb_info *info);
  35. static int q40fb_ioctl(struct inode *inode, struct file *file,
  36.       unsigned int cmd, unsigned long arg, int con,
  37.       struct fb_info *info);
  38. static int q40con_switch(int con, struct fb_info *info);
  39. static int q40con_updatevar(int con, struct fb_info *info);
  40. static void q40con_blank(int blank, struct fb_info *info);
  41. static void q40fb_set_disp(int con, struct fb_info *info);
  42. static struct display disp[MAX_NR_CONSOLES];
  43. static struct fb_info fb_info;
  44. static struct fb_ops q40fb_ops = {
  45. owner: THIS_MODULE,
  46. fb_get_fix: q40fb_get_fix,
  47. fb_get_var: q40fb_get_var,
  48. fb_set_var: q40fb_set_var,
  49. fb_get_cmap: q40fb_get_cmap,
  50. fb_set_cmap: q40fb_set_cmap,
  51. fb_ioctl: q40fb_ioctl,
  52. };
  53. static int currcon=0;
  54. static char q40fb_name[]="Q40";
  55. static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con,
  56. struct fb_info *info)
  57. {
  58. memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  59. strcpy(fix->id,"Q40");
  60. fix->smem_start=q40_screen_addr;
  61. fix->smem_len=1024*1024;
  62. fix->type=FB_TYPE_PACKED_PIXELS;
  63. fix->type_aux=0;
  64. fix->visual=FB_VISUAL_TRUECOLOR;  /* good approximation so far ..*/;
  65. fix->xpanstep=0;
  66. fix->ypanstep=0;
  67. fix->ywrapstep=0;
  68.         fix->line_length=1024*2;
  69. /* no mmio,accel ...*/
  70. return 0;
  71. }
  72.         
  73. static int q40fb_get_var(struct fb_var_screeninfo *var, int con,
  74. struct fb_info *info)
  75. {
  76. memset(var, 0, sizeof(struct fb_var_screeninfo));
  77. var->xres=1024;
  78. var->yres=512;
  79. var->xres_virtual=1024;
  80. var->yres_virtual=512;
  81. var->xoffset=0;
  82. var->yoffset=0;
  83. var->bits_per_pixel=16;
  84. var->grayscale=0;
  85. var->nonstd=0;
  86. var->activate=FB_ACTIVATE_NOW;
  87. var->height=230;     /* approx for my 17" monitor, more important */
  88. var->width=300;      /* than the absolute values is the unusual aspect ratio*/
  89. var->red.offset=6; /*6*/
  90. var->red.length=5;
  91. var->green.offset=11; /*11*/
  92. var->green.length=5;
  93. var->blue.offset=0;
  94. var->blue.length=6;
  95. var->transp.length=0;
  96. var->pixclock=0;
  97. var->left_margin=0;
  98. var->right_margin=0;
  99. var->hsync_len=0;
  100. var->vsync_len=0;
  101. var->sync=0;
  102. var->vmode=FB_VMODE_NONINTERLACED;
  103. return 0;
  104. }
  105. static int q40fb_set_var(struct fb_var_screeninfo *var, int con,
  106. struct fb_info *info)
  107. {
  108. if(var->xres!=1024) 
  109. return -EINVAL;
  110. if(var->yres!=512)
  111. return -EINVAL;
  112. if(var->xres_virtual!=1024)
  113. return -EINVAL;
  114. if(var->yres_virtual!=512)
  115. return -EINVAL;
  116. if(var->xoffset!=0)
  117. return -EINVAL;
  118. if(var->yoffset!=0)
  119. return -EINVAL;
  120. if(var->bits_per_pixel!=16)
  121. return -EINVAL;
  122. if(var->grayscale!=0)
  123. return -EINVAL;
  124. if(var->nonstd!=0)
  125. return -EINVAL;
  126. if(var->activate!=FB_ACTIVATE_NOW)
  127. return -EINVAL;
  128. if(var->pixclock!=0)
  129. return -EINVAL;
  130. if(var->left_margin!=0)
  131. return -EINVAL;
  132. if(var->right_margin!=0)
  133. return -EINVAL;
  134. if(var->hsync_len!=0)
  135. return -EINVAL;
  136. if(var->vsync_len!=0)
  137. return -EINVAL;
  138. if(var->sync!=0)
  139. return -EINVAL;
  140. if(var->vmode!=FB_VMODE_NONINTERLACED)
  141. return -EINVAL;
  142. return 0;
  143. }
  144. static int q40_getcolreg(unsigned regno, unsigned *red, unsigned *green,
  145.  unsigned *blue, unsigned *transp,
  146.  struct fb_info *info)
  147. {
  148.     /*
  149.      *  Read a single color register and split it into colors/transparent.
  150.      *  The return values must have a 16 bit magnitude.
  151.      *  Return != 0 for invalid regno.
  152.      */
  153.     if (regno>=16) return 1;
  154.     *transp=0;
  155.     *green = ((fbcon_cmap_cfb16[regno]>>11) & 31)<<11;
  156.     *red   = ((fbcon_cmap_cfb16[regno]>>6) & 31)<<11;
  157.     *blue  = ((fbcon_cmap_cfb16[regno]) & 63)<<10;
  158.     return 0;
  159. }
  160. static int q40_setcolreg(unsigned regno, unsigned red, unsigned green,
  161.  unsigned blue, unsigned transp,
  162.  const struct fb_info *info)
  163. {
  164.     /*
  165.      *  Set a single color register. The values supplied have a 16 bit
  166.      *  magnitude.
  167.      *  Return != 0 for invalid regno.
  168.      */
  169.   
  170.   red>>=11;
  171.   green>>=11;
  172.   blue>>=10;
  173.     if (regno < 16) {
  174.       fbcon_cmap_cfb16[regno] = ((red & 31) <<6) |
  175.                          ((green & 31) << 11) |
  176.                          (blue & 63);
  177.     }
  178.     return 0;
  179. }
  180. static int q40fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  181.  struct fb_info *info)
  182. {
  183. #if 1
  184. if (con == currcon) /* current console? */
  185. return fb_get_cmap(cmap, kspc, q40_getcolreg, info);
  186. else if (fb_display[con].cmap.len) /* non default colormap? */
  187. fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  188. else
  189. fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
  190.      cmap, kspc ? 0 : 2);
  191. return 0;
  192. #else
  193. printk(KERN_ERR "get cmap not supportedn");
  194. return -EINVAL;
  195. #endif
  196. }
  197. static int q40fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  198.  struct fb_info *info)
  199. {
  200. #if 1
  201. int err;
  202. if (!fb_display[con].cmap.len) { /* no colormap allocated? */
  203. if ((err = fb_alloc_cmap(&fb_display[con].cmap,
  204.  1<<fb_display[con].var.bits_per_pixel,
  205.  0)))
  206. return err;
  207. }
  208. if (con == currcon) /* current console? */
  209. return fb_set_cmap(cmap, kspc, q40_setcolreg, info);
  210. else
  211. fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  212. return 0;
  213. #else
  214. printk(KERN_ERR "set cmap not supportedn");
  215. return -EINVAL;
  216. #endif
  217. }
  218. static int q40fb_ioctl(struct inode *inode, struct file *file,
  219.       unsigned int cmd, unsigned long arg, int con,
  220.       struct fb_info *info)
  221. {
  222. #if 0
  223.         unsigned long i;
  224. struct display *display;
  225. if (con>=0)
  226.   display = &fb_display[con];
  227. else
  228.   display = &disp[0];
  229.         if (cmd == FBIOSETSCROLLMODE)
  230.   {
  231.     i = verify_area(VERIFY_READ, (void *)arg, sizeof(unsigned long));
  232.     if (!i) 
  233.       {
  234. copy_from_user(&i, (void *)arg, sizeof(unsigned long));
  235. display->scrollmode = i;
  236.       }
  237.     q40_updatescrollmode(display);
  238.     return i;
  239.   }
  240. #endif
  241. return -EINVAL;
  242. }
  243. static void q40fb_set_disp(int con, struct fb_info *info)
  244. {
  245.   struct fb_fix_screeninfo fix;
  246.   struct display *display;
  247.   q40fb_get_fix(&fix, con, info);
  248.   if (con>=0)
  249.     display = &fb_display[con];
  250.   else 
  251.     display = &disp[0];
  252.   if (con<0) con=0;
  253.    display->screen_base = fix.smem_start;
  254.    display->visual = fix.visual;
  255.    display->type = fix.type;
  256.    display->type_aux = fix.type_aux;
  257.    display->ypanstep = fix.ypanstep;
  258.    display->ywrapstep = fix.ywrapstep;
  259.    display->can_soft_blank = 0;
  260.    display->inverse = 0;
  261.    display->line_length = fix.line_length;
  262.    display->scrollmode = SCROLL_YREDRAW;
  263. #ifdef FBCON_HAS_CFB16
  264.    display->dispsw = &fbcon_cfb16;
  265.    disp->dispsw_data = fbcon_cmap_cfb16;
  266. #else
  267.    display->dispsw = &fbcon_dummy;
  268. #endif
  269. }
  270.   
  271. int __init q40fb_init(void)
  272. {
  273.         if ( !MACH_IS_Q40)
  274.   return -ENXIO;
  275. #if 0
  276.         q40_screen_addr = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024,
  277.    KERNELMAP_NO_COPYBACK, NULL);
  278. #else
  279. q40_screen_addr = Q40_PHYS_SCREEN_ADDR; /* mapped in q40/config.c */
  280. #endif
  281. fb_info.changevar=NULL;
  282. strcpy(&fb_info.modename[0],q40fb_name);
  283. fb_info.fontname[0]=0;
  284. fb_info.disp=disp;
  285. fb_info.switch_con=&q40con_switch;
  286. fb_info.updatevar=&q40con_updatevar;
  287. fb_info.blank=&q40con_blank;
  288. fb_info.node = -1;
  289. fb_info.fbops = &q40fb_ops;
  290. fb_info.flags = FBINFO_FLAG_DEFAULT;  /* not as module for now */
  291. master_outb(3,DISPLAY_CONTROL_REG);
  292.         q40fb_get_var(&disp[0].var, 0, &fb_info);
  293. q40fb_set_disp(-1, &fb_info);
  294. if (register_framebuffer(&fb_info) < 0) {
  295. printk(KERN_ERR "unable to register Q40 frame buffern");
  296. return -EINVAL;
  297. }
  298.         printk(KERN_INFO "fb%d: Q40 frame buffer alive and kicking !n",
  299.        GET_FB_IDX(fb_info.node));
  300. return 0;
  301. }
  302. static int q40con_switch(int con, struct fb_info *info)
  303. currcon=con;
  304. return 0;
  305. }
  306. static int q40con_updatevar(int con, struct fb_info *info)
  307. {
  308. return 0;
  309. }
  310. static void q40con_blank(int blank, struct fb_info *info)
  311. {
  312. }
  313. MODULE_LICENSE("GPL");