Linux S3C2440 LCD 设备驱动


主机:VM - RedHat 9.0

开发板:FL2440,linux-2.6.12

arm-linux-gcc:3.4.1

  1. /* 
  2.  *  linux/drivers/video/s3c2410fb.c 
  3.  */  
  4.   
  5. #include <linux/config.h>   
  6. #include <linux/module.h>   
  7. #include <linux/moduleparam.h>   
  8. #include <linux/kernel.h>   
  9. #include <linux/sched.h>   
  10. #include <linux/errno.h>   
  11. #include <linux/string.h>   
  12. #include <linux/interrupt.h>   
  13. #include <linux/slab.h>   
  14. #include <linux/fb.h>   
  15. #include <linux/delay.h>   
  16. #include <linux/init.h>   
  17. #include <linux/ioport.h>   
  18. #include <linux/cpufreq.h>   
  19. #include <linux/device.h>   
  20. #include <linux/dma-mapping.h>   
  21.   
  22. #include <asm/hardware.h>   
  23. #include <asm/io.h>   
  24. #include <asm/irq.h>   
  25. #include <asm/mach-types.h>   
  26. #include <asm/uaccess.h>   
  27. #include <asm/arch/regs-gpio.h>   
  28. #include <asm/arch/regs-lcd.h>   
  29. #include <asm/arch/regs-irq.h>   
  30.   
  31. #include "s3c2410fb.h"   
  32.   
  33. /* 
  34.  * Complain if VAR is out of range. 
  35.  */  
  36. #define DEBUG_VAR 1   
  37.   
  38. // 通过写入一个数据到此寄存器来清除SRCPND 寄存器的指定位。其只清除那些数据中被设置为1 的相应   
  39. // 位置的SRCPND 位。那些数据中被设置为0 的相应位置的位保持不变。   
  40. #define ClearPending(x) {   \   
  41.               __raw_writel((1 << (x)), S3C2410_SRCPND);   \  
  42.               __raw_writel((1 << (x)), S3C2410_INTPND);   \  
  43.             }  
  44.   
  45. struct gzliu_fb_mach_info fs2410_info = {  
  46.     .pixclock   = 270000,  
  47.     .xres       = 320,  
  48.     .yres       = 240,  
  49.     .bpp        = 16,  
  50.     .hsync_len  = 8,  
  51.     .left_margin    = 5,  
  52.     .right_margin   = 15,  
  53.     .vsync_len  = 15,  
  54.     .upper_margin   = 3,  
  55.     .lower_margin   = 5,  
  56.     .sync       = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,  
  57.     .cmap_greyscale = 0,  
  58.     .cmap_inverse   = 0,  
  59.     .cmap_static    = 0,  
  60.     .reg        = {  
  61.         .lcdcon1 = (6<<8)|(0<<7)|(3<<5)|(12<<1),  
  62.         .lcdcon2 = (3<<24) | (239<<14) | (5<<6) | (15),  
  63.         .lcdcon3 = (58<<19) | (319<<8) | (15),  
  64.         .lcdcon4 = (13<<8) | (8),  
  65.         .lcdcon5 = (1<<11) | (0<<10) | (1<<9) | (1<<8) | (0<<7) | (0<<6) | (1<<3)  |(0<<1) | (1),  
  66.     }  
  67. };  
  68.   
  69. static void (*gzliu_fb_backlight_power)(int);  
  70. static void (*gzliu_fb_lcd_power)(int);  
  71.   
  72. static int gzliu_fb_activate_var(struct fb_var_screeninfo *var, struct gzliu_fb_info *);  
  73. static void set_ctrlr_state(struct gzliu_fb_info *fbi, u_int state);  
  74.   
  75. static inline void gzliu_fb_schedule_work(struct gzliu_fb_info *fbi, u_int state)  
  76. {  
  77. printk("@@@@@@@@@@ gzliu_fb_schedule_work() @@@@@@@@@@@@\n");  
  78.     unsigned long flags;  
  79.   
  80.     local_irq_save(flags);  
  81.     /* 
  82.      * We need to handle two requests being made at the same time. 
  83.      * There are two important cases: 
  84.      *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE) 
  85.      *     We must perform the unblanking, which will do our REENABLE for us. 
  86.      *  2. When we are blanking, but immediately unblank before we have 
  87.      *     blanked.  We do the "REENABLE" thing here as well, just to be sure. 
  88.      */  
  89.     if (fbi->task_state == C_ENABLE && state == C_REENABLE)  
  90.         state = (u_int) -1;  
  91.     if (fbi->task_state == C_DISABLE && state == C_ENABLE)  
  92.         state = C_REENABLE;  
  93.   
  94.     if (state != (u_int)-1) {  
  95.         fbi->task_state = state;  
  96.         schedule_work(&fbi->task);  
  97.     }  
  98.     local_irq_restore(flags);  
  99. }  
  100.   
  101. static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)  
  102. {  
  103. printk("@@@@@@@@@@ chan_to_field() @@@@@@@@@@@@\n");  
  104.     chan &= 0xffff;  
  105.     chan >>= 16 - bf->length;  
  106.     return chan << bf->offset;  
  107. }  
  108.   
  109. static int gzliu_fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,  
  110.                u_int trans, struct fb_info *info)  
  111. {  
  112. printk("@@@@@@@@@@ gzliu_fb_setpalettereg() @@@@@@@@@@@@\n");  
  113.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  114.     u_int val, ret = 1;  
  115.   
  116.     if (regno < fbi->palette_size) {  
  117.         if (fbi->fb.var.grayscale) {  
  118.             val = ((blue >> 8) & 0x00ff);  
  119.         } else {  
  120.             val  = ((red   >>  0) & 0xf800);  
  121.             val |= ((green >>  5) & 0x07e0);  
  122.             val |= ((blue  >> 11) & 0x001f);  
  123.         }  
  124.   
  125.         fbi->palette_cpu[regno] = val;  
  126.         ret = 0;  
  127.     }  
  128.     return ret;  
  129. }  
  130.   
  131. static int gzliu_fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,  
  132.            u_int trans, struct fb_info *info)  
  133. {  
  134. printk("@@@@@@@@@@ gzliu_fb_setcolreg() @@@@@@@@@@@@\n");  
  135.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  136.     unsigned int val;  
  137.     int ret = 1;  
  138.   
  139.     /* 
  140.      * If inverse mode was selected, invert all the colours 
  141.      * rather than the register number.  The register number 
  142.      * is what you poke into the framebuffer to produce the 
  143.      * colour you requested. 
  144.      */  
  145.     if (fbi->cmap_inverse) {  
  146.         red   = 0xffff - red;  
  147.         green = 0xffff - green;  
  148.         blue  = 0xffff - blue;  
  149.     }  
  150.   
  151.     /* 
  152.      * If greyscale is true, then we convert the RGB value 
  153.      * to greyscale no matter what visual we are using. 
  154.      */  
  155.     if (fbi->fb.var.grayscale)  
  156.         red = green = blue = (19595 * red + 38470 * green +  
  157.                     7471 * blue) >> 16;  
  158.   
  159.     switch (fbi->fb.fix.visual) {  
  160.     case FB_VISUAL_TRUECOLOR:  
  161.         /* 
  162.          * 12 or 16-bit True Colour.  We encode the RGB value 
  163.          * according to the RGB bitfield information. 
  164.          */  
  165.         if (regno < 16) {  
  166.             u32 *pal = fbi->fb.pseudo_palette;  
  167.   
  168.             val  = chan_to_field(red, &fbi->fb.var.red);  
  169.             val |= chan_to_field(green, &fbi->fb.var.green);  
  170.             val |= chan_to_field(blue, &fbi->fb.var.blue);  
  171.   
  172.             pal[regno] = val;  
  173.             ret = 0;  
  174.         }  
  175.         break;  
  176.   
  177.     case FB_VISUAL_STATIC_PSEUDOCOLOR:  
  178.     case FB_VISUAL_PSEUDOCOLOR:  
  179.         ret = gzliu_fb_setpalettereg(regno, red, green, blue, trans, info);  
  180.         break;  
  181.     }  
  182.   
  183.     return ret;  
  184. }  
  185.   
  186. /* 
  187.  *  gzliu_fb_check_var(): 
  188.  *    Get the video params out of 'var'. If a value doesn't fit, round it up, 
  189.  *    if it's too big, return -EINVAL. 
  190.  * 
  191.  *    Round up in the following order: bits_per_pixel, xres, 
  192.  *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, 
  193.  *    bitfields, horizontal timing, vertical timing. 
  194.  */  
  195. static int gzliu_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)  
  196. {  
  197. printk("@@@@@@@@@@ gzliu_fb_check_var() @@@@@@@@@@@@\n");  
  198.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  199.   
  200.     if (var->xres < MIN_XRES)  
  201.         var->xres = MIN_XRES;  
  202.     if (var->yres < MIN_YRES)  
  203.         var->yres = MIN_YRES;  
  204.     if (var->xres > fbi->max_xres)  
  205.         var->xres = fbi->max_xres;  
  206.     if (var->yres > fbi->max_yres)  
  207.         var->yres = fbi->max_yres;  
  208.     var->xres_virtual =  
  209.         max(var->xres_virtual, var->xres);  
  210.     var->yres_virtual =  
  211.         max(var->yres_virtual, var->yres);  
  212.   
  213.         /* 
  214.      * Setup the RGB parameters for this display. 
  215.      * 
  216.      * The pixel packing format is described on page 7-11 of the 
  217.      * PXA2XX Developer's Manual. 
  218.          */  
  219.     if ( var->bits_per_pixel == 16 ) {  
  220.         var->red.offset   = 11; var->red.length   = 5;  
  221.         var->green.offset = 5;  var->green.length = 6;  
  222.         var->blue.offset  = 0;  var->blue.length  = 5;  
  223.         var->transp.offset = var->transp.length = 0;  
  224.     } else {  
  225.         var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0;  
  226.         var->red.length   = 8;  
  227.         var->green.length = 8;  
  228.         var->blue.length  = 8;  
  229.         var->transp.length = 0;  
  230.     }  
  231.   
  232. #ifdef CONFIG_CPU_FREQ   
  233.     DPRINTK("dma period = %d ps, clock = %d kHz\n",  
  234.         gzliu_fb_display_dma_period(var),  
  235.         get_clk_frequency_khz(0));  
  236. #endif   
  237.   
  238.     return 0;  
  239. }  
  240.   
  241. static inline void gzliu_fb_set_truecolor(u_int is_true_color)  
  242. {  
  243. printk("@@@@@@@@@@ gzliu_fb_set_truecolor() @@@@@@@@@@@@\n");  
  244.     DPRINTK("true_color = %d\n", is_true_color);  
  245. }  
  246.   
  247. /* 
  248.  * gzliu_fb_set_par(): 
  249.  *  Set the user defined part of the display for the specified console 
  250.  */  
  251. static int gzliu_fb_set_par(struct fb_info *info)  
  252. {  
  253. printk("@@@@@@@@@@ gzliu_fb_set_par() @@@@@@@@@@@@\n");  
  254.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  255.     struct fb_var_screeninfo *var = &info->var;  
  256.     unsigned long palette_mem_size;  
  257.   
  258.     DPRINTK("set_par\n");  
  259.   
  260.     if (var->bits_per_pixel == 16)  
  261.         fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;  
  262.     else if (!fbi->cmap_static)  
  263.         fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;  
  264.     else {  
  265.         /* 
  266.          * Some people have weird ideas about wanting static 
  267.          * pseudocolor maps.  I suspect their user space 
  268.          * applications are broken. 
  269.          */  
  270.         fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;  
  271.     }  
  272.   
  273.     fbi->fb.fix.line_length = var->xres_virtual *  
  274.                   var->bits_per_pixel / 8;  
  275.     if (var->bits_per_pixel == 16)  
  276.         fbi->palette_size = 0;  
  277.     else  
  278.         fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;  
  279.   
  280.     palette_mem_size = fbi->palette_size * sizeof(u16);  
  281.   
  282. printk("@@@@@@@ palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);  
  283.   
  284.     fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);  
  285.     fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;  
  286.   
  287.     /* 
  288.      * Set (any) board control register to handle new color depth 
  289.      */  
  290.     gzliu_fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);  
  291.       
  292.     if (fbi->fb.var.bits_per_pixel == 16)  
  293.         fb_dealloc_cmap(&fbi->fb.cmap);  
  294.     else  
  295.         fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);  
  296.   
  297.     gzliu_fb_activate_var(var, fbi);  
  298.   
  299.     return 0;  
  300. }  
  301.   
  302. /* 
  303.  * gzliu_fb_blank(): 
  304.  *  Blank the display by setting all palette values to zero.  Note, the 
  305.  *  12 and 16 bpp modes don't really use the palette, so this will not 
  306.  *      blank the display in all modes. 
  307.  */  
  308. static int gzliu_fb_blank(int blank, struct fb_info *info)  
  309. {  
  310. printk("@@@@@@@@@@ gzliu_fb_blank() @@@@@@@@@@@@\n");  
  311.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  312.     int i;  
  313.   
  314.     DPRINTK("gzliu_fb_blank: blank=%d\n", blank);  
  315.   
  316.     switch (blank) {  
  317.     case VESA_POWERDOWN:  
  318.     case VESA_VSYNC_SUSPEND:  
  319.     case VESA_HSYNC_SUSPEND:  
  320.         if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||  
  321.             fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)  
  322.             for (i = 0; i < fbi->palette_size; i++);  
  323.   
  324.         gzliu_fb_schedule_work(fbi, C_DISABLE);  
  325.         break;  
  326.   
  327.     case VESA_NO_BLANKING:  
  328.         if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||  
  329.             fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)  
  330.             fb_set_cmap(&fbi->fb.cmap, info);  
  331.         gzliu_fb_schedule_work(fbi, C_ENABLE);  
  332.     }  
  333.     return 0;  
  334. }  
  335.   
  336. static int soft_cursor_dummy(struct fb_info *info, struct fb_cursor *cursor)  
  337. {  
  338. printk("@@@@@@@@@@ soft_cursor_dummy() @@@@@@@@@@@@\n");  
  339.     return 0;  
  340. }  
  341.   
  342. static struct fb_ops gzliu_fb_ops = {  
  343.     .owner      = THIS_MODULE,  
  344.     .fb_check_var   = gzliu_fb_check_var,  
  345.     .fb_set_par = gzliu_fb_set_par,  
  346.     .fb_setcolreg   = gzliu_fb_setcolreg,  
  347.     .fb_blank   = gzliu_fb_blank,  
  348.     .fb_cursor  = soft_cursor_dummy,  
  349. };  
  350.   
  351. static inline unsigned int get_pcd(unsigned int pixclock)  
  352. {  
  353. printk("@@@@@@@@@@ get_pcd() @@@@@@@@@@@@\n");  
  354.     unsigned long long pcd;  
  355.   
  356.     pcd = s3c2410_hclk/(((__raw_readl(S3C2410_LCDCON1)>>8)&0x3ff)*2+1);  
  357.     return (unsigned int)pcd;  
  358. }  
  359.   
  360. /* 
  361.  * gzliu_fb_activate_var(): 
  362.  *  Configures LCD Controller based on entries in var parameter.  Settings are 
  363.  *  only written to the controller if changes were made. 
  364.  */  
  365. static int gzliu_fb_activate_var(struct fb_var_screeninfo *var, struct gzliu_fb_info *fbi)  
  366. {  
  367. printk("@@@@@@@@@@ gzliu_fb_activate_var() @@@@@@@@@@@@\n");  
  368.     struct gzliu_fb_lcd_reg new_regs;  
  369.     u_long flags;  
  370.     u_int half_screen_size, yres;  
  371.     unsigned long VideoPhysicalTemp = fbi->screen_dma;  
  372.   
  373.     DPRINTK("Configuring gzliu_ LCD\n");  
  374.   
  375.     DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",  
  376.         var->xres, var->hsync_len,  
  377.         var->left_margin, var->right_margin);  
  378.     DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",  
  379.         var->yres, var->vsync_len,  
  380.         var->upper_margin, var->lower_margin);  
  381.     DPRINTK("var: pixclock=%d pcd=%d\n", var->pixclock, pcd);  
  382.   
  383. #if DEBUG_VAR   
  384.     if (var->xres < 16 || var->xres > 1024)  
  385.         printk(KERN_ERR "%s: invalid xres %d\n",  
  386.             fbi->fb.fix.id, var->xres);  
  387.     switch(var->bits_per_pixel) {  
  388.     case 1:  
  389.     case 2:  
  390.     case 4:  
  391.     case 8:  
  392.     case 16:  
  393.         break;  
  394.     default:  
  395.         printk(KERN_ERR "%s: invalid bit depth %d\n",  
  396.                fbi->fb.fix.id, var->bits_per_pixel);  
  397.         break;  
  398.     }  
  399.     if (var->hsync_len < 1    || var->hsync_len > 64)  
  400.         printk(KERN_ERR "%s: invalid hsync_len %d\n",  
  401.             fbi->fb.fix.id, var->hsync_len);  
  402.     if (var->left_margin < 1  || var->left_margin > 255)  
  403.         printk(KERN_ERR "%s: invalid left_margin %d\n",  
  404.             fbi->fb.fix.id, var->left_margin);  
  405.     if (var->right_margin < 1 || var->right_margin > 255)  
  406.         printk(KERN_ERR "%s: invalid right_margin %d\n",  
  407.             fbi->fb.fix.id, var->right_margin);  
  408.     if (var->yres < 1         || var->yres > 1024)  
  409.         printk(KERN_ERR "%s: invalid yres %d\n",  
  410.             fbi->fb.fix.id, var->yres);  
  411.     if (var->vsync_len < 1    || var->vsync_len > 64)  
  412.         printk(KERN_ERR "%s: invalid vsync_len %d\n",  
  413.             fbi->fb.fix.id, var->vsync_len);  
  414.     if (var->upper_margin < 0 || var->upper_margin > 255)  
  415.         printk(KERN_ERR "%s: invalid upper_margin %d\n",  
  416.             fbi->fb.fix.id, var->upper_margin);  
  417.     if (var->lower_margin < 0 || var->lower_margin > 255)  
  418.         printk(KERN_ERR "%s: invalid lower_margin %d\n",  
  419.             fbi->fb.fix.id, var->lower_margin);  
  420. #endif   
  421.   
  422.     /* Update shadow copy atomically */  
  423.     local_irq_save(flags);  
  424.   
  425.     new_regs.lcdcon1 = fbi->reg.lcdcon1 & ~S3C2410_LCDCON1_ENVID;  
  426.   
  427.     new_regs.lcdcon2 = (fbi->reg.lcdcon2 & ~LCD2_LINEVAL_MSK)   
  428.                         | LCD2_LINEVAL(var->yres - 1);  
  429.   
  430.     /* TFT LCD only ! */  
  431.     new_regs.lcdcon3 = (fbi->reg.lcdcon3 & ~LCD3_HOZVAL_MSK)  
  432.                         | LCD3_HOZVAL(var->xres - 1);  
  433.   
  434.     new_regs.lcdcon4 = fbi->reg.lcdcon4;  
  435.     new_regs.lcdcon5 = fbi->reg.lcdcon5;  
  436.   
  437.     new_regs.lcdsaddr1 =   
  438.         LCDADDR_BANK(((unsigned long)VideoPhysicalTemp >> 22))  
  439.         | LCDADDR_BASEU(((unsigned long)VideoPhysicalTemp >> 1));  
  440.   
  441.     /* 16bpp */  
  442.     new_regs.lcdsaddr2 = LCDADDR_BASEL(   
  443.         ((unsigned long)VideoPhysicalTemp + (var->xres * 2 * (var->yres/*-1*/)))  
  444.         >> 1);  
  445.   
  446.     new_regs.lcdsaddr3 = LCDADDR_OFFSET(0) | (LCDADDR_PAGE(var->xres) /*>> 1*/);  
  447.   
  448.     yres = var->yres;  
  449.   
  450.     half_screen_size = var->bits_per_pixel;  
  451.     half_screen_size = half_screen_size * var->xres * var->yres / 16;  
  452.   
  453.     fbi->reg.lcdcon1 = new_regs.lcdcon1;  
  454.     fbi->reg.lcdcon2 = new_regs.lcdcon2;  
  455.     fbi->reg.lcdcon3 = new_regs.lcdcon3;  
  456.     fbi->reg.lcdcon4 = new_regs.lcdcon4;  
  457.     fbi->reg.lcdcon5 = new_regs.lcdcon5;  
  458.     fbi->reg.lcdsaddr1 = new_regs.lcdsaddr1;  
  459.     fbi->reg.lcdsaddr2 = new_regs.lcdsaddr2;  
  460.     fbi->reg.lcdsaddr3 = new_regs.lcdsaddr3;  
  461.   
  462.     __raw_writel(fbi->reg.lcdcon1&~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);  
  463.     __raw_writel(fbi->reg.lcdcon2, S3C2410_LCDCON2);  
  464.     __raw_writel(fbi->reg.lcdcon3, S3C2410_LCDCON3);  
  465.     __raw_writel(fbi->reg.lcdcon4, S3C2410_LCDCON4);  
  466.     __raw_writel(fbi->reg.lcdcon5, S3C2410_LCDCON5);  
  467.     __raw_writel(fbi->reg.lcdsaddr1, S3C2410_LCDSADDR1);  
  468.     __raw_writel(fbi->reg.lcdsaddr2, S3C2410_LCDSADDR2);  
  469.     __raw_writel(fbi->reg.lcdsaddr3, S3C2410_LCDSADDR3);  
  470.   
  471.     //next code should not be used in TX06D18 LCD   
  472.     #if !defined (TX06D18_TFT_LCD )     //change by gongjun   
  473.         #if defined(CONFIG_S3C2410_SMDK) && !defined(CONFIG_SMDK_AIJI)   
  474.             LCDLPCSEL = 0x2;  
  475.         #elif defined(CONFIG_S3C2410_SMDK) && defined(CONFIG_SMDK_AIJI)    
  476.             LCDLPCSEL = 0x7;  
  477.         #endif   
  478.     #endif   
  479.       
  480.     __raw_writel(0, S3C2410_TPAL);  
  481.     __raw_writel(fbi->reg.lcdcon1|S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);  
  482.   
  483. #if 1   
  484.     {  
  485.         printk("LCDCON1 0x%08x\n", __raw_readl(S3C2410_LCDCON1));  
  486.         printk("LCDCON2 0x%08x\n", __raw_readl(S3C2410_LCDCON2));  
  487.         printk("LCDCON3 0x%08x\n", __raw_readl(S3C2410_LCDCON3));  
  488.         printk("LCDCON4 0x%08x\n", __raw_readl(S3C2410_LCDCON4));  
  489.         printk("LCDCON5 0x%08x\n", __raw_readl(S3C2410_LCDCON5));  
  490.         printk("LCDSADDR1 0x%08x\n", __raw_readl(S3C2410_LCDSADDR1));  
  491.         printk("LCDSADDR2 0x%08x\n", __raw_readl(S3C2410_LCDSADDR2));  
  492.         printk("LCDSADDR3 0x%08x\n", __raw_readl(S3C2410_LCDSADDR3));  
  493.     }  
  494. #endif   
  495.     local_irq_restore(flags);  
  496.   
  497.     return 0;  
  498. }  
  499.   
  500. /* 
  501.  * NOTE!  The following functions are purely helpers for set_ctrlr_state. 
  502.  * Do not call them directly; set_ctrlr_state does the correct serialisation 
  503.  * to ensure that things happen in the right way 100% of time time. 
  504.  *  -- rmk 
  505.  */  
  506. static inline void __gzliu_fb_backlight_power(struct gzliu_fb_info *fbi, int on)  
  507. {  
  508. printk("@@@@@@@@@@ __gzliu_fb_backlight_power() @@@@@@@@@@@@\n");  
  509. printk("backlight o%s\n", on ? "n" : "ff");  
  510.   
  511.     if (gzliu_fb_backlight_power)  
  512.         gzliu_fb_backlight_power(on);  
  513. }  
  514.   
  515. static inline void __gzliu_fb_lcd_power(struct gzliu_fb_info *fbi, int on)  
  516. {  
  517. printk("@@@@@@@@@@ __gzliu_fb_lcd_power() @@@@@@@@@@@@\n");  
  518. printk("LCD power o%s\n", on ? "n" : "ff");  
  519.   
  520.     if (gzliu_fb_lcd_power)  
  521.         gzliu_fb_lcd_power(on);  
  522. }  
  523.   
  524. static void gzliu_fb_setup_gpio(struct gzliu_fb_info *fbi)  
  525. {  
  526. printk("@@@@@@@@@@ gzliu_fb_setup_gpio() @@@@@@@@@@@@\n");  
  527.     DPRINTK("setup gpio\n");  
  528.       
  529.     // 将GPD这组GPIO的16个引脚配置为VD   
  530.     __raw_writel(0xaaaaaaaa, S3C2410_GPDCON);  
  531.     __raw_writel(7, S3C2410_LCDINTMSK);         // 3 by gjl MASK LCD Sub Interrupt   
  532.     __raw_writel(0, S3C2410_TPAL);              // Disable Temp Palette   
  533.     __raw_writel(0, S3C2410_LPCSEL);            // 0 by gjl Disable LPC3600   
  534.     __raw_writel(0, S3C2410_PRIORITY);          //0x7f add by gjl   
  535. }  
  536.   
  537. static void gzliu_fb_enable_controller(struct gzliu_fb_info *fbi)  
  538. {  
  539. printk("@@@@@@@@@@ gzliu_fb_enable_controller() @@@@@@@@@@@@\n");  
  540.     __raw_writel(fbi->reg.lcdcon1&~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);  
  541.     __raw_writel(fbi->reg.lcdcon2, S3C2410_LCDCON2);  
  542.     __raw_writel(fbi->reg.lcdcon3, S3C2410_LCDCON3);  
  543.     __raw_writel(fbi->reg.lcdcon4, S3C2410_LCDCON4);  
  544.     __raw_writel(fbi->reg.lcdcon5, S3C2410_LCDCON5);  
  545.     __raw_writel(fbi->reg.lcdsaddr1, S3C2410_LCDSADDR1);  
  546.     __raw_writel(fbi->reg.lcdsaddr2, S3C2410_LCDSADDR2);  
  547.     __raw_writel(fbi->reg.lcdsaddr3, S3C2410_LCDSADDR3);  
  548.     __raw_writel(fbi->reg.lcdcon1|S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);     
  549.       
  550. #if 1   
  551.     printk("LCDCON1 0x%08x\n", __raw_readl(S3C2410_LCDCON1));  
  552.     printk("LCDCON2 0x%08x\n", __raw_readl(S3C2410_LCDCON2));  
  553.     printk("LCDCON3 0x%08x\n", __raw_readl(S3C2410_LCDCON3));  
  554.     printk("LCDCON4 0x%08x\n", __raw_readl(S3C2410_LCDCON4));  
  555.     printk("LCDCON5 0x%08x\n", __raw_readl(S3C2410_LCDCON5));  
  556.     printk("LCDSADDR1 0x%08x\n", __raw_readl(S3C2410_LCDSADDR1));  
  557.     printk("LCDSADDR2 0x%08x\n", __raw_readl(S3C2410_LCDSADDR2));  
  558.     printk("LCDSADDR3 0x%08x\n", __raw_readl(S3C2410_LCDSADDR3));  
  559. #endif   
  560. }  
  561.   
  562. static void gzliu_fb_disable_controller(struct gzliu_fb_info *fbi)  
  563. {  
  564. printk("@@@@@@@@@@ gzliu_fb_disable_controller() @@@@@@@@@@@@\n");  
  565.     __raw_writel(fbi->reg.lcdcon1&~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);  
  566. }  
  567.   
  568. /* 
  569.  * This function must be called from task context only, since it will 
  570.  * sleep when disabling the LCD controller, or if we get two contending 
  571.  * processes trying to alter state. 
  572.  */  
  573. static void set_ctrlr_state(struct gzliu_fb_info *fbi, u_int state)  
  574. {  
  575. printk("@@@@@@@@@@ set_ctrlr_state() @@@@@@@@@@@@\n");  
  576.     u_int old_state;  
  577.   
  578.     down(&fbi->ctrlr_sem);  
  579.   
  580.     old_state = fbi->state;  
  581.   
  582.     /* 
  583.      * Hack around fbcon initialisation. 
  584.      */  
  585.     if (old_state == C_STARTUP && state == C_REENABLE)  
  586.         state = C_ENABLE;  
  587.   
  588.     switch (state) {  
  589.     case C_DISABLE_CLKCHANGE:  
  590.         /* 
  591.          * Disable controller for clock change.  If the 
  592.          * controller is already disabled, then do nothing. 
  593.          */  
  594.         if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {  
  595.             fbi->state = state;  
  596.             gzliu_fb_disable_controller(fbi);  
  597.         }  
  598.         break;  
  599.   
  600.     case C_DISABLE_PM:  
  601.     case C_DISABLE:  
  602.         /* 
  603.          * Disable controller 
  604.          */  
  605.         if (old_state != C_DISABLE) {  
  606.             fbi->state = state;  
  607.             __gzliu_fb_backlight_power(fbi, 0);  
  608.             __gzliu_fb_lcd_power(fbi, 0);  
  609.             if (old_state != C_DISABLE_CLKCHANGE)  
  610.                 gzliu_fb_disable_controller(fbi);  
  611.         }  
  612.         break;  
  613.   
  614.     case C_ENABLE_CLKCHANGE:  
  615.         /* 
  616.          * Enable the controller after clock change.  Only 
  617.          * do this if we were disabled for the clock change. 
  618.          */  
  619.         if (old_state == C_DISABLE_CLKCHANGE) {  
  620.             fbi->state = C_ENABLE;  
  621.             gzliu_fb_enable_controller(fbi);  
  622.         }  
  623.         break;  
  624.   
  625.     case C_REENABLE:  
  626.         /* 
  627.          * Re-enable the controller only if it was already 
  628.          * enabled.  This is so we reprogram the control 
  629.          * registers. 
  630.          */  
  631.         if (old_state == C_ENABLE) {  
  632.             gzliu_fb_disable_controller(fbi);  
  633.             gzliu_fb_setup_gpio(fbi);  
  634.             gzliu_fb_enable_controller(fbi);  
  635.         }  
  636.         break;  
  637.   
  638.     case C_ENABLE_PM:  
  639.         /* 
  640.          * Re-enable the controller after PM.  This is not 
  641.          * perfect - think about the case where we were doing 
  642.          * a clock change, and we suspended half-way through. 
  643.          */  
  644.         if (old_state != C_DISABLE_PM)  
  645.             break;  
  646.         /* fall through */  
  647.   
  648.     case C_ENABLE:  
  649.         /* 
  650.          * Power up the LCD screen, enable controller, and 
  651.          * turn on the backlight. 
  652.          */  
  653.         if (old_state != C_ENABLE) {  
  654.             fbi->state = C_ENABLE;  
  655.             gzliu_fb_setup_gpio(fbi);  
  656.             gzliu_fb_enable_controller(fbi);  
  657.             __gzliu_fb_lcd_power(fbi, 1);  
  658.             __gzliu_fb_backlight_power(fbi, 1);  
  659.         }  
  660.         break;  
  661.     }  
  662.     up(&fbi->ctrlr_sem);  
  663.       
  664. }/* static void set_ctrlr_state() */  
  665.   
  666. /* 
  667.  * Our LCD controller task (which is called when we blank or unblank) 
  668.  * via keventd. 
  669.  */  
  670. static void gzliu_fb_task(void *dummy)  
  671. {  
  672. printk("@@@@@@@@@@ gzliu_fb_task() @@@@@@@@@@@@\n");  
  673.     struct gzliu_fb_info *fbi = dummy;  
  674.     u_int state = xchg(&fbi->task_state, -1);  
  675.   
  676.     set_ctrlr_state(fbi, state);  
  677. }  
  678.   
  679. void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)  
  680. {  
  681. printk("@@@@@@@@@@ consistent_alloc() @@@@@@@@@@@@\n");  
  682.     struct page *page, *end, *free;  
  683.     unsigned long order;  
  684.     void *ret, *virt;  
  685.   
  686.     if (in_interrupt())  
  687.         BUG();  
  688.   
  689.     /* 
  690.     * // PAGE_SHIFT determines the page size // 
  691.     *  
  692.     * #define PAGE_SHIFT        12 
  693.     * #define PAGE_SIZE     (1UL << PAGE_SHIFT) 
  694.     * #define PAGE_MASK     (~(PAGE_SIZE-1)) 
  695.     *  
  696.     * // to align the pointer to the (next) page boundary // 
  697.     *  
  698.     * #define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK) 
  699.     */  
  700.     size = PAGE_ALIGN(size);  
  701.       
  702.     /* 
  703.     * include/asm-arm/page.h 
  704.     *  
  705.     * // Pure 2^n version of get_order // 
  706.     * static inline int get_order(unsigned long size) 
  707.     * { 
  708.     *   int order; 
  709.     *  
  710.     *   size = (size-1) >> (PAGE_SHIFT-1); 
  711.     *   order = -1; 
  712.     *   do { 
  713.     *       size >>= 1; 
  714.     *       order++; 
  715.     *   } while (size); 
  716.     *   return order; 
  717.     * } 
  718.     */  
  719.     order = get_order(size);  
  720.   
  721.     page = alloc_pages(gfp, order);  
  722.     if (!page)  
  723.         goto no_page;  
  724.   
  725.     /* 
  726.      * We could do with a page_to_phys and page_to_bus here. 
  727.      */  
  728.     virt = page_address(page);  
  729.       
  730.     /* 
  731.     * #define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET) 
  732.     * #define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) 
  733.     *  
  734.     * dma_handle -- 物理地址 
  735.     * ret -- 映射后的虚拟地址 
  736.     */  
  737.       
  738.     *dma_handle = virt_to_bus(virt);  
  739.     ret = __ioremap(virt_to_phys(virt), size, 0,0);  
  740.     if (!ret)  
  741.         goto no_remap;  
  742.   
  743. #if 0 /* ioremap_does_flush_cache_all */   
  744.     /* 
  745.      * we need to ensure that there are no cachelines in use, or 
  746.      * worse dirty in this area.  Really, we don't need to do 
  747.      * this since __ioremap does a flush_cache_all() anyway. --rmk 
  748.      */  
  749.     invalidate_dcache_range(virt, virt + size);  
  750. #endif   
  751.   
  752.     /* 
  753.      * free wasted pages.  We skip the first page since we know 
  754.      * that it will have count = 1 and won't require freeing. 
  755.      * We also mark the pages in use as reserved so that 
  756.      * remap_page_range works. 
  757.      */  
  758.     page = virt_to_page(virt);  
  759.     free = page + (size >> PAGE_SHIFT);  
  760.     end  = page + (1 << order);  
  761.   
  762.     for (; page < end; page++) {  
  763.         set_page_count(page, 1);  
  764.         if (page >= free)  
  765.             __free_page(page);  
  766.         else  
  767.             SetPageReserved(page);  
  768.     }  
  769.     return ret;  
  770.   
  771. no_remap:  
  772.     __free_pages(page, order);  
  773. no_page:  
  774.     return NULL;  
  775. }  
  776. /* 
  777.  * gzliu_fb_map_video_memory(): 
  778.  *      Allocates the DRAM memory for the frame buffer.  This buffer is 
  779.  *  remapped into a non-cached, non-buffered, memory region to 
  780.  *      allow palette and pixel writes to occur without flushing the 
  781.  *      cache.  Once this area is remapped, all virtual memory 
  782.  *      access to the video memory should occur at the new region. 
  783.  */  
  784. static int __init gzliu_fb_map_video_memory(struct gzliu_fb_info *fbi)  
  785. {  
  786. printk("@@@@@@@@@@ gzliu_fb_map_video_memory() @@@@@@@@@@@@\n");  
  787.     u_long palette_mem_size;  
  788.   
  789.     /* 
  790.      * We reserve one page for the palette, plus the size 
  791.      * of the framebuffer. 
  792.      */  
  793.     fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);  
  794.     //changed by gjl  dma_alloc_writecombine dma_alloc_coherent   
  795.     fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,  
  796.                         &fbi->map_dma);  //fbi->dev, fbi->map_size,&fbi->map_dma, GFP_KERNEL);   
  797.   
  798.     if (fbi->map_cpu) {  
  799. printk("@@@@@@ VA=0x%p, PA=0x%08x, size=0x%08x\n", fbi->map_cpu, fbi->map_dma, fbi->map_size);  
  800.         /* prevent initial garbage on screen */  
  801.         memset(fbi->map_cpu, 0, fbi->map_size);  
  802.         fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;  
  803.         fbi->screen_dma = fbi->map_dma + PAGE_SIZE;  
  804.         /* 
  805.          * FIXME: this is actually the wrong thing to place in 
  806.          * smem_start.  But fbdev suffers from the problem that 
  807.          * it needs an API which doesn't exist (in this case, 
  808.          * dma_writecombine_mmap) 
  809.          */  
  810.         fbi->fb.fix.smem_start = fbi->screen_dma;  
  811.   
  812.         fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;  
  813.   
  814.         palette_mem_size = fbi->palette_size * sizeof(u16);  
  815. printk("@@@@@@@ palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);  
  816.   
  817.         fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);  
  818.         fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;  
  819.     }  
  820.   
  821.     return fbi->map_cpu ? 0 : -ENOMEM;  
  822. }  
  823.   
  824. static struct gzliu_fb_info * __init gzliu_fb_init_fbinfo(struct device *dev)  
  825. {  
  826. printk("@@@@@@@@@@ gzliu_fb_init_fbinfo() @@@@@@@@@@@@\n");  
  827.     struct gzliu_fb_info *fbi;  
  828.     void *addr;  
  829.     struct gzliu_fb_mach_info *inf = &fs2410_info;//dev->platform_data;   
  830.   
  831.     /* Alloc the gzliu_fb_info and pseudo_palette in one step */  
  832.     fbi = kmalloc(sizeof(struct gzliu_fb_info) + sizeof(u32) * 16, GFP_KERNEL);  
  833.     if (!fbi)  
  834.         return NULL;  
  835.   
  836.     memset(fbi, 0, sizeof(struct gzliu_fb_info));  
  837.     fbi->dev = dev;  
  838.   
  839.     strcpy(fbi->fb.fix.id, GZLIU_NAME);  
  840.   
  841.     fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;  
  842.     fbi->fb.fix.type_aux = 0;  
  843.     fbi->fb.fix.xpanstep = 0;  
  844.     fbi->fb.fix.ypanstep = 0;  
  845.     fbi->fb.fix.ywrapstep    = 0;  
  846.     fbi->fb.fix.accel    = FB_ACCEL_NONE;    // 没有硬件加速   
  847.   
  848.     fbi->fb.var.nonstd   = 0;  
  849.     fbi->fb.var.activate = FB_ACTIVATE_NOW;  
  850.     fbi->fb.var.height   = -1;  
  851.     fbi->fb.var.width    = -1;  
  852.     fbi->fb.var.accel_flags  = 0;  
  853.     fbi->fb.var.vmode    = FB_VMODE_NONINTERLACED;  
  854.   
  855.     fbi->fb.fbops        = &gzliu_fb_ops;  
  856.     fbi->fb.flags        = FBINFO_FLAG_DEFAULT;  
  857.     fbi->fb.node     = -1;  
  858.     fbi->fb.currcon      = -1;  
  859.   
  860.     addr = fbi;  
  861.     addr = addr + sizeof(struct gzliu_fb_info);  
  862.     fbi->fb.pseudo_palette   = addr;  
  863.   
  864.     fbi->max_xres            = inf->xres;  
  865.     fbi->fb.var.xres     = inf->xres;  
  866.     fbi->fb.var.xres_virtual = inf->xres;  
  867.     fbi->max_yres            = inf->yres;  
  868.     fbi->fb.var.yres     = inf->yres;  
  869.     fbi->fb.var.yres_virtual = inf->yres;  
  870.     fbi->max_bpp         = inf->bpp;  
  871.     fbi->fb.var.bits_per_pixel   = inf->bpp;  
  872.     fbi->fb.var.pixclock     = inf->pixclock;  
  873.     fbi->fb.var.hsync_len        = inf->hsync_len;  
  874.     fbi->fb.var.left_margin      = inf->left_margin;  
  875.     fbi->fb.var.right_margin = inf->right_margin;  
  876.     fbi->fb.var.vsync_len        = inf->vsync_len;  
  877.     fbi->fb.var.upper_margin = inf->upper_margin;  
  878.     fbi->fb.var.lower_margin = inf->lower_margin;  
  879.     fbi->fb.var.sync     = inf->sync;  
  880.     fbi->fb.var.grayscale        = inf->cmap_greyscale;  
  881.     fbi->cmap_inverse        = inf->cmap_inverse;  
  882.     fbi->cmap_static     = inf->cmap_static;  
  883.     fbi->reg.lcdcon1     = inf->reg.lcdcon1;  
  884.     fbi->reg.lcdcon2     = inf->reg.lcdcon2;  
  885.     fbi->reg.lcdcon3     = inf->reg.lcdcon3;  
  886.     fbi->reg.lcdcon4     = inf->reg.lcdcon4;  
  887.     fbi->reg.lcdcon5     = inf->reg.lcdcon5;  
  888.     fbi->state           = C_STARTUP;  
  889.     fbi->task_state          = (u_char)-1;  
  890.     fbi->fb.fix.smem_len     = fbi->max_xres * fbi->max_yres *  
  891.                       fbi->max_bpp / 8;  
  892.   
  893.     init_waitqueue_head(&fbi->ctrlr_wait);  
  894.     INIT_WORK(&fbi->task, gzliu_fb_task, fbi);  
  895.     init_MUTEX(&fbi->ctrlr_sem);  
  896.   
  897.     return fbi;  
  898. }  
  899. // add by   
  900. static void s3c2410fb_irq_fifo(int irq, void *dev_id, struct pt_regs *regs)  
  901. {  
  902. printk("@@@@@@@@@@ s3c2410fb_irq_fifo() @@@@@@@@@@@@\n");  
  903.     volatile register int a,b;  
  904.     local_irq_disable();  
  905.       
  906.     __raw_writel(__raw_readl(S3C2410_LCDINTMSK)|=3, S3C2410_LCDINTMSK);  
  907.     __raw_writel(1, S3C2410_LCDSRCPND);  
  908.     __raw_writel(1, S3C2410_LCDINTPND);  
  909.     __raw_writel(__raw_readl(S3C2410_LCDINTMSK)&=(~(1)), S3C2410_LCDINTMSK);  
  910.       
  911.     b=0;  
  912.     for(a=0;a<2000;a++)b++;  
  913.       
  914. printk("@@@@@@@@ irq: %d @@@@@@@@@\n", irq);  
  915.     ClearPending(irq);  
  916. }  
  917.   
  918. int __init gzliu_fb_probe(struct device *dev)  
  919. {  
  920. printk("@@@@@@@@@@ gzliu_fb_probe() @@@@@@@@@@@@\n");  
  921.     struct gzliu_fb_info *fbi;  
  922.     struct gzliu_fb_mach_info *inf;  
  923.     unsigned long flags;  
  924.     int ret;  
  925.   
  926.     printk(KERN_ERR "gzliu_fb_probe start!!!!!!!!!!!!!!!!!!!!!!!!!!\n");  
  927.     inf = &fs2410_info;//dev->platform_data;   
  928.     ret = -ENOMEM;  
  929.     fbi = NULL;  
  930.     if (!inf)  
  931.         goto failed;  
  932.   
  933.     dev_dbg(dev, "got a %dx%dx%d LCD\n",inf->xres, inf->yres, inf->bpp);  
  934.     if (inf->xres == 0 || inf->yres == 0 || inf->bpp == 0) {  
  935.         dev_err(dev, "Invalid resolution or bit depth\n");  
  936.         ret = -EINVAL;  
  937.         goto failed;  
  938.     }  
  939.     gzliu_fb_backlight_power = inf->gzliu_fb_backlight_power;  
  940.     gzliu_fb_lcd_power = inf->gzliu_fb_lcd_power;  
  941.   
  942.     fbi = gzliu_fb_init_fbinfo(dev);  
  943.     if (!fbi) {  
  944.         dev_err(dev, "Failed to initialize framebuffer device\n");  
  945.         ret = -ENOMEM;  
  946.         goto failed;  
  947.     }  
  948.   
  949.     /* Initialize video memory */  
  950.     ret = gzliu_fb_map_video_memory(fbi);  
  951.     if (ret) {  
  952.         dev_err(dev, "Failed to allocate video RAM: %d\n", ret);  
  953.         ret = -ENOMEM;  
  954.         goto failed;  
  955.     }  
  956.   
  957.     /* 
  958.      * This makes sure that our colour bitfield 
  959.      * descriptors are correctly initialised. 
  960.      */  
  961.     gzliu_fb_check_var(&fbi->fb.var, &fbi->fb);  
  962.     gzliu_fb_set_par(&fbi->fb);  
  963.   
  964.     /* 
  965.     * include/linux/device.h 
  966.     *  
  967.     * static inline void dev_set_drvdata (struct device *dev, void *data) 
  968.     * { 
  969.     *   dev->driver_data = data; 
  970.     * } 
  971.     */  
  972.     dev_set_drvdata(dev, fbi);  
  973.   
  974.     /* 
  975.     * drivers/vedio/fbmem.c 
  976.     *  
  977.     * int register_framebuffer(struct fb_info *fb_info) 
  978.     * { 
  979.     *   int i; 
  980.     *   struct fb_event event; 
  981.     *  
  982.     *   if (num_registered_fb == FB_MAX) 
  983.     *       return -ENXIO; 
  984.     *   num_registered_fb++; 
  985.     *   for (i = 0 ; i < FB_MAX; i++) 
  986.     *       if (!registered_fb[i]) 
  987.     *           break; 
  988.     *   fb_info->node = i; 
  989.     *  
  990.     *   fb_info->class_device = class_simple_device_add(fb_class, MKDEV(FB_MAJOR, i), 
  991.     *               fb_info->device, "fb%d", i); 
  992.     *   if (IS_ERR(fb_info->class_device)) { 
  993.     *       // Not fatal // 
  994.     *       printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->class_device)); 
  995.     *       fb_info->class_device = NULL; 
  996.     *   } else 
  997.     *       fb_init_class_device(fb_info); 
  998.     *  
  999.     *   if (fb_info->pixmap.addr == NULL) { 
  1000.     *       fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL); 
  1001.     *       if (fb_info->pixmap.addr) { 
  1002.     *           fb_info->pixmap.size = FBPIXMAPSIZE; 
  1003.     *           fb_info->pixmap.buf_align = 1; 
  1004.     *           fb_info->pixmap.scan_align = 1; 
  1005.     *           fb_info->pixmap.access_align = 4; 
  1006.     *           fb_info->pixmap.flags = FB_PIXMAP_DEFAULT; 
  1007.     *       } 
  1008.     *   } 
  1009.     *   fb_info->pixmap.offset = 0; 
  1010.     * 
  1011.     *   if (!fb_info->modelist.prev || 
  1012.     *   !fb_info->modelist.next || 
  1013.     *   list_empty(&fb_info->modelist)) { 
  1014.     *       struct fb_videomode mode; 
  1015.     *  
  1016.     *       INIT_LIST_HEAD(&fb_info->modelist); 
  1017.     *       fb_var_to_videomode(&mode, &fb_info->var); 
  1018.     *       fb_add_videomode(&mode, &fb_info->modelist); 
  1019.     *   } 
  1020.     *  
  1021.     *   registered_fb[i] = fb_info; 
  1022.     *  
  1023.     *   devfs_mk_cdev(MKDEV(FB_MAJOR, i), S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i); 
  1024.     *   event.info = fb_info; 
  1025.     *   notifier_call_chain(&fb_notifier_list, FB_EVENT_FB_REGISTERED, &event); 
  1026.     *   return 0; 
  1027.     * } 
  1028.     *  
  1029.     */  
  1030.     ret = register_framebuffer(&fbi->fb);  
  1031.     if (ret < 0) {  
  1032.         dev_err(dev, "Failed to register framebuffer device: %d\n", ret);  
  1033.         goto failed;  
  1034.     }  
  1035.         printk("success to register framebuffer device: %d!!!\n", ret);  
  1036.     // add by         
  1037.     disable_irq(IRQ_LCD);  
  1038.     ret = request_irq(IRQ_LCD, s3c2410fb_irq_fifo, SA_INTERRUPT, "LCD", fbi);  
  1039.     if (ret) {  
  1040.         printk(KERN_ERR "s3c2440fb: request_irq failed: %d\n", ret);  
  1041.         goto failed;  
  1042.     }  
  1043.     enable_irq(IRQ_LCD);  
  1044.           
  1045.     /* 
  1046.      * Ok, now enable the LCD controller 
  1047.      */  
  1048.     set_ctrlr_state(fbi, C_ENABLE);  
  1049.     printk("@@@@@@@ done probe @@@@@@@@\n");  
  1050.     return 0;  
  1051.   
  1052. failed:  
  1053.     dev_set_drvdata(dev, NULL);  
  1054.     if (fbi)  
  1055.         kfree(fbi);  
  1056.     return ret;  
  1057.       
  1058. }/* int __init gzliu_fb_probe() */  
  1059.   
  1060. static struct device_driver gzliu_fb_driver = {  
  1061.     .name       = "s3c2410-lcd",  
  1062.     .bus        = &platform_bus_type,  
  1063.     .probe  = gzliu_fb_probe,  
  1064. };  
  1065.   
  1066. int __devinit s3c2410fb_init(void)  
  1067. {  
  1068. printk("@@@@@@@@@@ s3c2410fb_init() @@@@@@@@@@@@\n");  
  1069.     int ret;  
  1070.     printk("@@@@@ --- s3c2410fb init --- @@@@@\n");  
  1071.   
  1072.     ret = driver_register(&gzliu_fb_driver);  
  1073.     if(ret)  
  1074.         printk("register device driver failed, return code is %d\n", ret);  
  1075.           
  1076.     __raw_writel(__raw_readl(S3C2410_LCDINTMSK)|=3, S3C2410_LCDINTMSK);  
  1077.     __raw_writel(1, S3C2410_LCDSRCPND);  
  1078.     __raw_writel(1, S3C2410_LCDINTPND);  
  1079.     __raw_writel(__raw_readl(S3C2410_LCDINTMSK)&=(~(1)), S3C2410_LCDINTMSK);  
  1080.       
  1081.       
  1082.     return ret;  
  1083. }  
  1084.   
  1085.   
  1086. module_init(s3c2410fb_init);  
  1087.   
  1088. MODULE_AUTHOR("gzliu_hit@qq.com");  
  1089. MODULE_DESCRIPTION("framebuffer driver for s3c2440");  
  1090. MODULE_LICENSE("GPL"); 
  1. /* 
  2.  *  linux/drivers/video/s3c2410fb.h 
  3.  */  
  4.   
  5. #ifndef __GZLIU_FB_H__   
  6. #define __GZLIU_FB_H__   
  7.   
  8. /* Shadows for LCD controller registers */  
  9. struct gzliu_fb_lcd_reg {  
  10.     unsigned long lcdcon1;  
  11.     unsigned long lcdcon2;  
  12.     unsigned long lcdcon3;  
  13.     unsigned long lcdcon4;  
  14.     unsigned long lcdcon5;  
  15.     unsigned long lcdsaddr1;  
  16.     unsigned long lcdsaddr2;  
  17.     unsigned long lcdsaddr3;  
  18. };  
  19.   
  20. struct gzliu_fb_info {  
  21.     struct fb_info      fb;  
  22.     struct device       *dev;  
  23.   
  24.     u_int           max_bpp;  
  25.     u_int           max_xres;  
  26.     u_int           max_yres;  
  27.   
  28.     /* 
  29.      * These are the addresses we mapped 
  30.      * the framebuffer memory region to. 
  31.      */  
  32.     /* raw memory addresses */  
  33.     dma_addr_t      map_dma;    /* physical */  
  34.     u_char *        map_cpu;    /* virtual */  
  35.     u_int           map_size;  
  36.   
  37.     /* addresses of pieces placed in raw buffer */  
  38.     u_char *        screen_cpu; /* virtual address of frame buffer */  
  39.     dma_addr_t      screen_dma; /* physical address of frame buffer */  
  40.     u16 *           palette_cpu;    /* virtual address of palette memory */  
  41.     dma_addr_t      palette_dma;    /* physical address of palette memory */  
  42.     u_int           palette_size;  
  43.   
  44.     /* DMA descriptors */     
  45.     dma_addr_t      dmadesc_fblow_dma;  
  46.     dma_addr_t      dmadesc_fbhigh_dma;  
  47.     dma_addr_t      dmadesc_palette_dma;  
  48.       
  49.     u_int           cmap_inverse:1,  
  50.                 cmap_static:1,  
  51.                 unused:30;  
  52.       
  53.     volatile u_char     state;  
  54.     volatile u_char     task_state;  
  55.     struct semaphore    ctrlr_sem;  
  56.     wait_queue_head_t   ctrlr_wait;  
  57.     struct work_struct  task;  
  58.       
  59.     struct gzliu_fb_lcd_reg reg;  
  60.   
  61. #ifdef CONFIG_CPU_FREQ   
  62.     struct notifier_block   freq_transition;  
  63.     struct notifier_block   freq_policy;  
  64. #endif   
  65. };  
  66.   
  67. struct gzliu_fb_mach_info {  
  68.     u_long      pixclock;  
  69.   
  70.     u_short     xres;  
  71.     u_short     yres;  
  72.   
  73.     u_char      bpp;  
  74.     u_char      hsync_len;  
  75.     u_char      left_margin;  
  76.     u_char      right_margin;  
  77.   
  78.     u_char      vsync_len;  
  79.     u_char      upper_margin;  
  80.     u_char      lower_margin;  
  81.     u_char      sync;  
  82.   
  83.     u_int       cmap_greyscale:1,  
  84.             cmap_inverse:1,  
  85.             cmap_static:1,  
  86.             unused:29;  
  87.   
  88.     struct gzliu_fb_lcd_reg reg;  
  89.       
  90.     void (*gzliu_fb_backlight_power)(int);  
  91.     void (*gzliu_fb_lcd_power)(int);  
  92.   
  93. };  
  94.   
  95. /* 
  96.  *  Debug macros 
  97.  */  
  98. //#define   DEBUG   1   
  99. #if DEBUG   
  100. #  define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)   
  101. #else   
  102. #  define DPRINTK(fmt, args...)   
  103. #endif   
  104.   
  105. #define TO_INF(ptr,member) container_of(ptr,struct gzliu_fb_info,member)   
  106.   
  107. /* 
  108.  * These are the actions for set_ctrlr_state 
  109.  */  
  110. #define C_DISABLE       (0)   
  111. #define C_ENABLE        (1)   
  112. #define C_DISABLE_CLKCHANGE (2)   
  113. #define C_ENABLE_CLKCHANGE  (3)   
  114. #define C_REENABLE      (4)   
  115. #define C_DISABLE_PM        (5)   
  116. #define C_ENABLE_PM     (6)   
  117. #define C_STARTUP       (7)   
  118.   
  119. #define GZLIU_NAME  "GZLIU"   
  120.   
  121. /* 
  122.  * Minimum X and Y resolutions 
  123.  */  
  124. #define MIN_XRES    64   
  125. #define MIN_YRES    64   
  126.   
  127. #ifndef __ASSEMBLY__   
  128. #define UData(Data) ((unsigned long) (Data))   
  129. #else   
  130. #define UData(Data) (Data)   
  131. #endif   
  132.   
  133. #define Fld(Size, Shft) (((Size) << 16) + (Shft))   
  134. #define FSize(Field)    ((Field) >> 16)   
  135. #define FShft(Field)    ((Field) & 0x0000FFFF)   
  136. #define FMsk(Field) (((UData (1) << FSize (Field)) - 1) << FShft (Field))   
  137. #define FInsrt(Value, Field) \   
  138.                     (UData (Value) << FShft (Field))  
  139.   
  140. #define fLCD2_LINEVAL   Fld(10,14)  /* TFT/STN: vertical size of LCD */   
  141. #define LCD2_LINEVAL(x) FInsrt((x), fLCD2_LINEVAL)   
  142. #define LCD2_LINEVAL_MSK    FMsk(fLCD2_LINEVAL)   
  143. #define fLCD3_HOZVAL    Fld(11,8)   /* horizontal size of LCD */   
  144. #define LCD3_HOZVAL(x)  FInsrt((x), fLCD3_HOZVAL)   
  145. #define LCD3_HOZVAL_MSK FMsk(fLCD3_HOZVAL)   
  146.   
  147. #define fLCDADDR_BANK   Fld(9,21)   /* bank location for video buffer */   
  148. #define LCDADDR_BANK(x) FInsrt((x), fLCDADDR_BANK)   
  149.   
  150. #define fLCDADDR_BASEU  Fld(21,0)   /* address of upper left corner */   
  151. #define LCDADDR_BASEU(x)    FInsrt((x), fLCDADDR_BASEU)   
  152.   
  153. #define fLCDADDR_BASEL  Fld(21,0)   /* address of lower right corner */   
  154. #define LCDADDR_BASEL(x)    FInsrt((x), fLCDADDR_BASEL)   
  155.   
  156. #define fLCDADDR_OFFSET Fld(11,11)  /* Virtual screen offset size   
  157.                        (# of half words) */  
  158. #define LCDADDR_OFFSET(x)   FInsrt((x), fLCDADDR_OFFSET)   
  159.   
  160. #define fLCDADDR_PAGE   Fld(11,0)   /* Virtual screen page width   
  161.                        (# of half words) */  
  162. #define LCDADDR_PAGE(x) FInsrt((x), fLCDADDR_PAGE)   
  163.   
  164. #endif /* __GZLIU_FB_H__ */  

相关内容