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

Linux/Unix编程

开发平台:

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, struct fb_info *info)
  162. {
  163.     /*
  164.      *  Set a single color register. The values supplied have a 16 bit
  165.      *  magnitude.
  166.      *  Return != 0 for invalid regno.
  167.      */
  168.   
  169.   red>>=11;
  170.   green>>=11;
  171.   blue>>=10;
  172.     if (regno < 16) {
  173.       fbcon_cmap_cfb16[regno] = ((red & 31) <<6) |
  174.                          ((green & 31) << 11) |
  175.                          (blue & 63);
  176.     }
  177.     return 0;
  178. }
  179. static int q40fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  180.  struct fb_info *info)
  181. {
  182. #if 1
  183. if (con == currcon) /* current console? */
  184. return fb_get_cmap(cmap, kspc, q40_getcolreg, info);
  185. else if (fb_display[con].cmap.len) /* non default colormap? */
  186. fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  187. else
  188. fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
  189.      cmap, kspc ? 0 : 2);
  190. return 0;
  191. #else
  192. printk(KERN_ERR "get cmap not supportedn");
  193. return -EINVAL;
  194. #endif
  195. }
  196. static int q40fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  197.  struct fb_info *info)
  198. {
  199. #if 1
  200. int err;
  201. if (!fb_display[con].cmap.len) { /* no colormap allocated? */
  202. if ((err = fb_alloc_cmap(&fb_display[con].cmap,
  203.  1<<fb_display[con].var.bits_per_pixel,
  204.  0)))
  205. return err;
  206. }
  207. if (con == currcon) /* current console? */
  208. return fb_set_cmap(cmap, kspc, q40_setcolreg, info);
  209. else
  210. fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  211. return 0;
  212. #else
  213. printk(KERN_ERR "set cmap not supportedn");
  214. return -EINVAL;
  215. #endif
  216. }
  217. static int q40fb_ioctl(struct inode *inode, struct file *file,
  218.       unsigned int cmd, unsigned long arg, int con,
  219.       struct fb_info *info)
  220. {
  221. #if 0
  222.         unsigned long i;
  223. struct display *display;
  224. if (con>=0)
  225.   display = &fb_display[con];
  226. else
  227.   display = &disp[0];
  228.         if (cmd == FBIOSETSCROLLMODE)
  229.   {
  230.     i = verify_area(VERIFY_READ, (void *)arg, sizeof(unsigned long));
  231.     if (!i) 
  232.       {
  233. copy_from_user(&i, (void *)arg, sizeof(unsigned long));
  234. display->scrollmode = i;
  235.       }
  236.     q40_updatescrollmode(display);
  237.     return i;
  238.   }
  239. #endif
  240. return -EINVAL;
  241. }
  242. static void q40fb_set_disp(int con, struct fb_info *info)
  243. {
  244.   struct fb_fix_screeninfo fix;
  245.   struct display *display;
  246.   q40fb_get_fix(&fix, con, info);
  247.   if (con>=0)
  248.     display = &fb_display[con];
  249.   else 
  250.     display = &disp[0];
  251.   if (con<0) con=0;
  252.    display->screen_base = (char *)fix.smem_start;
  253.    display->visual = fix.visual;
  254.    display->type = fix.type;
  255.    display->type_aux = fix.type_aux;
  256.    display->ypanstep = fix.ypanstep;
  257.    display->ywrapstep = fix.ywrapstep;
  258.    display->can_soft_blank = 0;
  259.    display->inverse = 0;
  260.    display->line_length = fix.line_length;
  261.    display->scrollmode = SCROLL_YREDRAW;
  262. #ifdef FBCON_HAS_CFB16
  263.    display->dispsw = &fbcon_cfb16;
  264.    disp->dispsw_data = fbcon_cmap_cfb16;
  265. #else
  266.    display->dispsw = &fbcon_dummy;
  267. #endif
  268. }
  269.   
  270. int __init q40fb_init(void)
  271. {
  272.         if ( !MACH_IS_Q40)
  273.   return -ENXIO;
  274. #if 0
  275.         q40_screen_addr = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024,
  276.    KERNELMAP_NO_COPYBACK, NULL);
  277. #else
  278. q40_screen_addr = Q40_PHYS_SCREEN_ADDR; /* mapped in q40/config.c */
  279. #endif
  280. fb_info.changevar=NULL;
  281. strcpy(&fb_info.modename[0],q40fb_name);
  282. fb_info.fontname[0]=0;
  283. fb_info.disp=disp;
  284. fb_info.switch_con=&q40con_switch;
  285. fb_info.updatevar=&q40con_updatevar;
  286. fb_info.blank=&q40con_blank;
  287. fb_info.node = -1;
  288. fb_info.fbops = &q40fb_ops;
  289. fb_info.flags = FBINFO_FLAG_DEFAULT;  /* not as module for now */
  290. master_outb(3,DISPLAY_CONTROL_REG);
  291.         q40fb_get_var(&disp[0].var, 0, &fb_info);
  292. q40fb_set_disp(-1, &fb_info);
  293. if (register_framebuffer(&fb_info) < 0) {
  294. printk(KERN_ERR "unable to register Q40 frame buffern");
  295. return -EINVAL;
  296. }
  297.         printk(KERN_INFO "fb%d: Q40 frame buffer alive and kicking !n",
  298.        GET_FB_IDX(fb_info.node));
  299. return 0;
  300. }
  301. static int q40con_switch(int con, struct fb_info *info)
  302. currcon=con;
  303. return 0;
  304. }
  305. static int q40con_updatevar(int con, struct fb_info *info)
  306. {
  307. return 0;
  308. }
  309. static void q40con_blank(int blank, struct fb_info *info)
  310. {
  311. }
  312. MODULE_LICENSE("GPL");